]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9338 Make all date pickers consistent (#3157)
authorStas Vilchik <stas.vilchik@sonarsource.com>
Fri, 16 Mar 2018 15:24:04 +0000 (16:24 +0100)
committerSonarTech <sonartech@sonarsource.com>
Thu, 22 Mar 2018 11:37:48 +0000 (12:37 +0100)
50 files changed:
server/sonar-web/config/webpack.config.js
server/sonar-web/package.json
server/sonar-web/src/main/js/app/styles/components/search-navigator.css
server/sonar-web/src/main/js/app/styles/jquery-ui.css [deleted file]
server/sonar-web/src/main/js/app/styles/sonar.css
server/sonar-web/src/main/js/app/styles/style.css
server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js
server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js [deleted file]
server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/background-tasks/components/Search.js
server/sonar-web/src/main/js/apps/background-tasks/constants.js
server/sonar-web/src/main/js/apps/background-tasks/utils.js
server/sonar-web/src/main/js/apps/coding-rules/components/AvailableSinceFacet.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js
server/sonar-web/src/main/js/apps/issues/utils.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityDateInput-test.js.snap
server/sonar-web/src/main/js/apps/projectsManagement/App.tsx
server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx
server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx
server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/BulkApplyTemplateModal-test.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/DeleteModal-test.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx
server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.tsx
server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.tsx
server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/__snapshots__/ChangelogSearch-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/DateInput.tsx
server/sonar-web/src/main/js/components/controls/DateRangeInput.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/DayPicker.css [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/OutsideClickHandler.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/__tests__/DateRangeInput-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateRangeInput-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/controls/styles.css
server/sonar-web/src/main/js/components/icons-components/CalendarIcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/ChevronDownIcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/ChevronLeftIcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/ChevronRightcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/ChevronUpIcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/OpenCloseIcon.tsx
server/sonar-web/src/main/js/helpers/l10n.ts
server/sonar-web/src/main/js/helpers/query.ts
server/sonar-web/src/main/js/libs/third-party/jquery-ui.js [deleted file]
server/sonar-web/yarn.lock
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 5a7513de97165253187cfcfeadd8dbfd2ca39b56..ecb1b446b134aca4907bf1b64d199d4521e0c101 100644 (file)
@@ -58,8 +58,7 @@ module.exports = ({ production = true, fast = false }) => ({
       'react-dom',
       'backbone',
       'backbone.marionette',
-      'handlebars/runtime',
-      './src/main/js/libs/third-party/jquery-ui.js'
+      'handlebars/runtime'
     ].filter(Boolean),
 
     app: [
index ac465a81a0bddc48e03122e9663b4c4348104806..377677ee3693c306fbb273ed440dfe7ed8c6a39c 100644 (file)
@@ -28,6 +28,7 @@
     "prop-types": "15.6.0",
     "rc-tooltip": "3.5.0",
     "react": "16.2.0",
+    "react-day-picker": "7.1.2",
     "react-dom": "16.2.0",
     "react-draggable": "3.0.3",
     "react-helmet": "5.2.0",
index c997af3dae1c6ac5eb121abedb1c8b10b966271f..761df0dccdc1925967d03e403dafb0e5292048b6 100644 (file)
@@ -598,7 +598,7 @@ a.search-navigator-facet:focus .facet-stat {
 
 .search-navigator-date-facet-selection {
   position: relative;
-  padding: 0 10px;
+  padding-left: var(--gridSize);
   font-size: var(--smallFontSize);
 }
 
@@ -613,7 +613,7 @@ a.search-navigator-facet:focus .facet-stat {
   clear: both;
 }
 
-.search-navigator-date-facet-selection-input {
+.search-navigator-date-facet-selection .date-input-control-input {
   width: 115px !important;
 }
 
@@ -641,6 +641,13 @@ a.search-navigator-facet:focus .facet-stat {
   visibility: hidden;
 }
 
+.search-navigator-date-facet-selection
+  .date-input-control:not(:nth-of-type(1))
+  .date-input-calendar {
+  left: auto;
+  right: 0;
+}
+
 .search-navigator-filters {
   position: relative;
   padding: 5px 10px;
diff --git a/server/sonar-web/src/main/js/app/styles/jquery-ui.css b/server/sonar-web/src/main/js/app/styles/jquery-ui.css
deleted file mode 100644 (file)
index 123bdfd..0000000
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-/*! jQuery UI - v1.10.3 - 2013-06-18
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.button.css, jquery.ui.dialog.css
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
-/* Layout helpers
-----------------------------------*/
-/* SONAR */
-.no-close .ui-dialog-titlebar-close {
-  display: none;
-}
-
-.ui-dialog .ui-dialog-titlebar {
-  display: none;
-}
-
-.ui-widget-header {
-  color: #ffffff;
-  font-weight: bold;
-}
-
-.ui-widget-header a {
-  color: #ffffff;
-}
-
-.ui-widget-shadow {
-  margin: -5px 0 0 -5px;
-  padding: 5px;
-  background: #000000 50% 50% repeat-x;
-  opacity: 0.2;
-  -moz-border-radius: 5px;
-  -khtml-border-radius: 5px;
-  -webkit-border-radius: 5px;
-  border-radius: 5px;
-}
-
-.ui-dialog {
-  position: absolute;
-  width: 300px;
-  overflow: hidden;
-  box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5);
-  background-color: #fff;
-}
-
-/* /SONAR */
-.ui-helper-hidden {
-  display: none;
-}
-
-.ui-helper-hidden-accessible {
-  border: 0;
-  clip: rect(0 0 0 0);
-  height: 1px;
-  margin: -1px;
-  overflow: hidden;
-  padding: 0;
-  position: absolute;
-  width: 1px;
-}
-
-.ui-helper-reset {
-  margin: 0;
-  padding: 0;
-  border: 0;
-  outline: 0;
-  line-height: 1.3;
-  text-decoration: none;
-  font-size: 100%;
-  list-style: none;
-}
-
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
-  content: '';
-  display: table;
-  border-collapse: collapse;
-}
-
-.ui-helper-clearfix:after {
-  clear: both;
-}
-
-.ui-helper-clearfix {
-  min-height: 0;
-  /* support: IE7 */
-}
-
-.ui-helper-zfix {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  position: absolute;
-  opacity: 0;
-}
-
-.ui-front {
-  z-index: 1000;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
-  cursor: default !important;
-}
-
-/* Icons
-----------------------------------*/
-/* states and images */
-.ui-icon {
-  display: block;
-  text-indent: -99999px;
-  overflow: hidden;
-  background-repeat: no-repeat;
-}
-
-/* Misc visuals
-----------------------------------*/
-/* Overlays */
-.ui-widget-overlay {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  /* sonar */
-  background-color: #000000;
-  opacity: 0.5;
-  /* /sonar */
-}
-
-.ui-resizable {
-  position: relative;
-}
-
-.ui-resizable-handle {
-  position: absolute;
-  font-size: 0.1px;
-  display: block;
-}
-
-.ui-resizable-disabled .ui-resizable-handle,
-.ui-resizable-autohide .ui-resizable-handle {
-  display: none;
-}
-
-.ui-resizable-n {
-  cursor: n-resize;
-  height: 7px;
-  width: 100%;
-  top: -5px;
-  left: 0;
-}
-
-.ui-resizable-s {
-  cursor: s-resize;
-  height: 7px;
-  width: 100%;
-  bottom: -5px;
-  left: 0;
-}
-
-.ui-resizable-e {
-  cursor: e-resize;
-  width: 7px;
-  right: -5px;
-  top: 0;
-  height: 100%;
-}
-
-.ui-resizable-w {
-  cursor: w-resize;
-  width: 7px;
-  left: -5px;
-  top: 0;
-  height: 100%;
-}
-
-.ui-resizable-se {
-  cursor: se-resize;
-  width: 12px;
-  height: 12px;
-  right: 1px;
-  bottom: 1px;
-}
-
-.ui-resizable-sw {
-  cursor: sw-resize;
-  width: 9px;
-  height: 9px;
-  left: -5px;
-  bottom: -5px;
-}
-
-.ui-resizable-nw {
-  cursor: nw-resize;
-  width: 9px;
-  height: 9px;
-  left: -5px;
-  top: -5px;
-}
-
-.ui-resizable-ne {
-  cursor: ne-resize;
-  width: 9px;
-  height: 9px;
-  right: -5px;
-  top: -5px;
-}
-
-.ui-button {
-  display: inline-block;
-  position: relative;
-  padding: 0;
-  line-height: normal;
-  margin-right: 0.1em;
-  cursor: pointer;
-  vertical-align: middle;
-  text-align: center;
-  overflow: visible;
-  /* removes extra width in IE */
-}
-
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
-  text-decoration: none;
-}
-
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
-  width: 2.2em;
-}
-
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
-  width: 2.4em;
-}
-
-.ui-button-icons-only {
-  width: 3.4em;
-}
-
-button.ui-button-icons-only {
-  width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
-  display: block;
-  line-height: normal;
-}
-
-.ui-button-text-only .ui-button-text {
-  padding: 0.4em 1em;
-}
-
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
-  padding: 0.4em;
-  text-indent: -9999999px;
-}
-
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-  padding: 0.4em 1em 0.4em 2.1em;
-}
-
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-  padding: 0.4em 2.1em 0.4em 1em;
-}
-
-.ui-button-text-icons .ui-button-text {
-  padding-left: 2.1em;
-  padding-right: 2.1em;
-}
-
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
-  padding: 0.4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
-  position: absolute;
-  top: 50%;
-  margin-top: -8px;
-}
-
-.ui-button-icon-only .ui-icon {
-  left: 50%;
-  margin-left: -8px;
-}
-
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
-  left: 0.5em;
-}
-
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-  right: 0.5em;
-}
-
-/* button sets */
-.ui-buttonset {
-  margin-right: 7px;
-}
-
-.ui-buttonset .ui-button {
-  margin-left: 0;
-  margin-right: -0.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
-  border: 0;
-  padding: 0;
-}
-
-.ui-dialog {
-  position: absolute;
-  top: 0;
-  left: 0;
-  /* sonar
-  padding: .2em;
-  */
-  outline: 0;
-}
-
-/* sonar
-.ui-dialog .ui-dialog-titlebar {
-  padding: .4em 1em;
-  position: relative;
-}
-
-.ui-dialog .ui-dialog-title {
-  float: left;
-  margin: .1em 0;
-  white-space: nowrap;
-  width: 90%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.ui-dialog .ui-dialog-titlebar-close {
-  position: absolute;
-  right: .3em;
-  top: 50%;
-  width: 21px;
-  margin: -10px 0 0 0;
-  padding: 1px;
-  height: 20px;
-}
-
-*/
-.ui-dialog .ui-dialog-content {
-  position: relative;
-  border: 0;
-  /* sonar
-  padding: .5em 1em;
-  */
-  background: none;
-  overflow: auto;
-}
-
-.ui-dialog .ui-dialog-buttonpane {
-  text-align: left;
-  border-width: 1px 0 0 0;
-  background-image: none;
-  margin-top: 0.5em;
-  padding: 0.3em 1em 0.5em 0.4em;
-}
-
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
-  float: right;
-}
-
-.ui-dialog .ui-dialog-buttonpane button {
-  margin: 0.5em 0.4em 0.5em 0;
-  cursor: pointer;
-}
-
-.ui-dialog .ui-resizable-se {
-  width: 12px;
-  height: 12px;
-  right: -5px;
-  bottom: -5px;
-  background-position: 16px 16px;
-}
-
-.ui-draggable .ui-dialog-titlebar {
-  cursor: move;
-}
-
-.ui-datepicker {
-  width: 17em;
-  padding: 5px 5px 0;
-  display: none;
-  background-color: #fff;
-  border: 1px solid #e1e1e1;
-}
-
-.ui-datepicker .ui-datepicker-header {
-  position: relative;
-  padding: 0.2em 0;
-  color: var(--baseFontColor);
-}
-
-.ui-datepicker .ui-widget-header a {
-  color: var(--baseFontColor);
-}
-
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
-  position: absolute;
-  top: 7px;
-}
-
-.ui-datepicker .ui-datepicker-prev {
-  left: 2px;
-}
-
-.ui-datepicker .ui-datepicker-next {
-  right: 2px;
-}
-
-.ui-datepicker .ui-datepicker-title {
-  margin: 0 48px;
-  line-height: 1.8em;
-  color: var(--baseFontColor);
-  text-align: center;
-}
-
-.ui-datepicker .ui-datepicker-title select {
-  font-size: 1em;
-  margin: 1px 0;
-}
-
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
-  width: 49%;
-}
-
-.ui-datepicker table {
-  width: 100%;
-  font-size: 0.9em;
-  border-collapse: collapse;
-  margin: 0 0 0.4em;
-}
-
-.ui-datepicker th {
-  padding: 0.7em 0.3em;
-  text-align: center;
-  font-weight: bold;
-  border: 0;
-}
-
-.ui-datepicker td {
-  border: 0;
-  padding: 1px;
-}
-
-.ui-datepicker td span,
-.ui-datepicker td a {
-  display: block;
-  padding: 0.2em;
-  text-align: right;
-  text-decoration: none;
-}
-
-.ui-datepicker .ui-datepicker-buttonpane {
-  background-image: none;
-  margin: 0.7em 0 0 0;
-  padding: 0 0.2em;
-  border-left: 0;
-  border-right: 0;
-  border-bottom: 0;
-}
-
-.ui-datepicker .ui-datepicker-buttonpane button {
-  float: right;
-  margin: 0.5em 0.2em 0.4em;
-  cursor: pointer;
-  padding: 0.2em 0.6em 0.3em 0.6em;
-  width: auto;
-  overflow: visible;
-}
-
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
-  float: left;
-}
-
-.ui-datepicker-today {
-  background-color: #eee1f8;
-}
-
-.ui-datepicker-current-day {
-  background-color: var(--blue);
-}
-
-.ui-datepicker-current-day a {
-  color: #fff;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
-  width: auto;
-}
-
-.ui-datepicker-multi .ui-datepicker-group {
-  float: left;
-}
-
-.ui-datepicker-multi .ui-datepicker-group table {
-  width: 95%;
-  margin: 0 auto 0.4em;
-}
-
-.ui-datepicker-multi-2 .ui-datepicker-group {
-  width: 50%;
-}
-
-.ui-datepicker-multi-3 .ui-datepicker-group {
-  width: 33.3%;
-}
-
-.ui-datepicker-multi-4 .ui-datepicker-group {
-  width: 25%;
-}
-
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
-  border-left-width: 0;
-}
-
-.ui-datepicker-multi .ui-datepicker-buttonpane {
-  clear: left;
-}
-
-.ui-datepicker-row-break {
-  clear: both;
-  width: 100%;
-  font-size: 0;
-}
-
-.ui-datepicker .ui-icon {
-  text-indent: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
-  direction: rtl;
-}
-
-.ui-datepicker-rtl .ui-datepicker-prev {
-  right: 2px;
-  left: auto;
-}
-
-.ui-datepicker-rtl .ui-datepicker-next {
-  left: 2px;
-  right: auto;
-}
-
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
-  right: 1px;
-  left: auto;
-}
-
-.ui-datepicker-rtl .ui-datepicker-next:hover {
-  left: 1px;
-  right: auto;
-}
-
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
-  clear: right;
-}
-
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
-  float: left;
-}
-
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
-  float: right;
-}
-
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
-  border-right-width: 0;
-  border-left-width: 1px;
-}
index f48136b4f1fb6a4969acdc65ee9f311fad4406c4..714ed9d74b29eb7ac5ef9941ea75bbc993813471 100644 (file)
@@ -17,8 +17,6 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-@import './jquery-ui.css';
-
 @import './init/base.css';
 @import './init/type.css';
 @import './init/links.css';
index 99f727e3b72cc04c1af4c2e5e84deac307e07b22..f5bcff13ca54dabbf2a1ba04c7bc7a8b2e84139e 100644 (file)
@@ -48,8 +48,7 @@
   transition: none;
 }
 
-.tabs li a.selected,
-.tabs .ui-tabs-active a {
+.tabs li a.selected {
   text-decoration: none;
   color: #555 !important;
   font-weight: bold;
index 8fb098b91662fb000b639e826875d2932d4ddda8..0c2770ca719e4fcaf78c0962f1332f3c29b46e32 100644 (file)
@@ -41,6 +41,8 @@ import { updateTask, mapFiltersToParameters } from '../utils';
 import '../background-tasks.css';
 import { fetchOrganizations } from '../../../store/rootActions';
 import { translate } from '../../../helpers/l10n';
+import { parseAsDate } from '../../../helpers/query';
+import { toShortNotSoISOString } from '../../../helpers/dates';
 
 /*::
 type Props = {
@@ -157,6 +159,14 @@ class BackgroundTasksApp extends React.PureComponent {
       }
     });
 
+    if (nextQuery.minSubmittedAt) {
+      nextQuery.minSubmittedAt = toShortNotSoISOString(nextQuery.minSubmittedAt);
+    }
+
+    if (nextQuery.maxExecutedAt) {
+      nextQuery.maxExecutedAt = toShortNotSoISOString(nextQuery.maxExecutedAt);
+    }
+
     this.context.router.push({
       pathname: this.props.location.pathname,
       query: nextQuery
@@ -211,8 +221,8 @@ class BackgroundTasksApp extends React.PureComponent {
     const status = this.props.location.query.status || DEFAULT_FILTERS.status;
     const taskType = this.props.location.query.taskType || DEFAULT_FILTERS.taskType;
     const currents = this.props.location.query.currents || DEFAULT_FILTERS.currents;
-    const minSubmittedAt = this.props.location.query.minSubmittedAt || '';
-    const maxExecutedAt = this.props.location.query.maxExecutedAt || '';
+    const minSubmittedAt = parseAsDate(this.props.location.query.minSubmittedAt);
+    const maxExecutedAt = parseAsDate(this.props.location.query.maxExecutedAt);
     const query = this.props.location.query.query || '';
 
     return (
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js
deleted file mode 100644 (file)
index ea51021..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import $ from 'jquery';
-import React, { Component } from 'react';
-import { isValidDate, parseDate, toShortNotSoISOString } from '../../../helpers/dates';
-import { translate } from '../../../helpers/l10n';
-
-export default class DateFilter extends Component {
-  componentDidMount() {
-    this.attachDatePicker();
-  }
-
-  componentDidUpdate() {
-    this.attachDatePicker();
-  }
-
-  attachDatePicker() {
-    const opts = {
-      dateFormat: 'yy-mm-dd',
-      changeMonth: true,
-      changeYear: true,
-      onSelect: this.handleChange.bind(this)
-    };
-    if ($.fn && $.fn.datepicker) {
-      $(this.refs.minDate).datepicker(opts);
-      $(this.refs.maxDate).datepicker(opts);
-    }
-  }
-
-  handleChange() {
-    const date = {};
-    const minDate = parseDate(this.refs.minDate.value);
-    const maxDate = parseDate(this.refs.maxDate.value);
-
-    if (isValidDate(minDate)) {
-      date.minSubmittedAt = toShortNotSoISOString(minDate);
-    }
-
-    if (isValidDate(maxDate)) {
-      date.maxExecutedAt = toShortNotSoISOString(maxDate);
-    }
-
-    this.props.onChange(date);
-  }
-
-  render() {
-    const { minSubmittedAt, maxExecutedAt } = this.props;
-
-    return (
-      <div className="nowrap">
-        <input
-          className="input-small"
-          value={minSubmittedAt}
-          onChange={() => true}
-          ref="minDate"
-          type="text"
-          placeholder={translate('from')}
-        />{' '}
-        <input
-          className="input-small"
-          value={maxExecutedAt}
-          onChange={() => true}
-          ref="maxDate"
-          type="text"
-          placeholder={translate('to')}
-        />
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.tsx
new file mode 100644 (file)
index 0000000..6d8b0e9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import DageRangeInput from '../../../components/controls/DateRangeInput';
+
+interface Props {
+  maxExecutedAt: Date | undefined;
+  minSubmittedAt: Date | undefined;
+  onChange: (x: { maxExecutedAt?: Date; minSubmittedAt?: Date }) => void;
+}
+
+export default class DateFilter extends React.PureComponent<Props> {
+  handleDateRangeChange = ({ from, to }: { from?: Date; to?: Date }) => {
+    this.props.onChange({ minSubmittedAt: from, maxExecutedAt: to });
+  };
+
+  render() {
+    const dateRange = { from: this.props.minSubmittedAt, to: this.props.maxExecutedAt };
+    return (
+      <div className="nowrap">
+        <DageRangeInput onChange={this.handleDateRangeChange} value={dateRange} />
+      </div>
+    );
+  }
+}
index 70fb29450d8a45ea031a6152cab6bf2fc32f3a70..11f7de80c0af42fd95d445da7ad3fbbf4a793622 100644 (file)
@@ -51,9 +51,9 @@ export default class Search extends React.PureComponent {
     this.props.onFilterUpdate({ currents });
   }
 
-  handleDateChange(date /*: string */) {
+  handleDateChange = (date /*: { maxExecutedAt?: Date; minSubmittedAt?: Date } */) => {
     this.props.onFilterUpdate(date);
-  }
+  };
 
   handleQueryChange = (query /*: string */) => {
     this.props.onFilterUpdate({ query });
@@ -129,9 +129,9 @@ export default class Search extends React.PureComponent {
           <li>
             <h6 className="bt-search-form-label">{translate('date')}</h6>
             <DateFilter
-              minSubmittedAt={minSubmittedAt}
               maxExecutedAt={maxExecutedAt}
-              onChange={this.handleDateChange.bind(this)}
+              minSubmittedAt={minSubmittedAt}
+              onChange={this.handleDateChange}
             />
           </li>
 
index bd41ffdcf4d3ec202f4045fc70944c53ba807323..5cee6f2068d55c4280d3960fc04d5a6c3cdf1fcf 100644 (file)
@@ -45,8 +45,8 @@ export const DEFAULT_FILTERS = {
   status: STATUSES.ALL_EXCEPT_PENDING,
   taskType: ALL_TYPES,
   currents: CURRENTS.ALL,
-  minSubmittedAt: '',
-  maxExecutedAt: '',
+  minSubmittedAt: undefined,
+  maxExecutedAt: undefined,
   query: ''
 };
 
index 319ef9f2d98bec3cb60317fca7a9d71f7afb0069..4d425d33e91c2bdde4a9b2378b362b29d4aff16f 100644 (file)
@@ -19,6 +19,7 @@
  */
 /* @flow */
 import { STATUSES, ALL_TYPES, CURRENTS } from './constants';
+import { toShortNotSoISOString } from '../../helpers/dates';
 /*:: import type { Task } from './types'; */
 
 export function updateTask(tasks /*: Task[] */, newTask /*: Task */) {
@@ -56,11 +57,11 @@ export function mapFiltersToParameters(filters /*: Object */ = {}) {
   }
 
   if (filters.minSubmittedAt) {
-    parameters.minSubmittedAt = filters.minSubmittedAt;
+    parameters.minSubmittedAt = toShortNotSoISOString(filters.minSubmittedAt);
   }
 
   if (filters.maxExecutedAt) {
-    parameters.maxExecutedAt = filters.maxExecutedAt;
+    parameters.maxExecutedAt = toShortNotSoISOString(filters.maxExecutedAt);
   }
 
   if (filters.query) {
index b0a18157f67b349a41cfe82511be4c3bf9c3c508..7bc746a447bbbf802a37dac2dd36451714e6c1a7 100644 (file)
@@ -24,9 +24,7 @@ import DateInput from '../../../components/controls/DateInput';
 import FacetBox from '../../../components/facet/FacetBox';
 import FacetHeader from '../../../components/facet/FacetHeader';
 import { longFormatterOption } from '../../../components/intl/DateFormatter';
-import { parseDate } from '../../../helpers/dates';
 import { translate } from '../../../helpers/l10n';
-import { serializeDateShort } from '../../../helpers/query';
 
 interface Props {
   onChange: (changes: Partial<Query>) => void;
@@ -44,23 +42,15 @@ export default class AvailableSinceFacet extends React.PureComponent<Props> {
 
   handleClear = () => this.props.onChange({ availableSince: undefined });
 
-  handlePeriodChange = (value?: string) =>
-    this.props.onChange({ availableSince: value ? parseDate(value) : undefined });
+  handlePeriodChange = (date: Date | undefined) => {
+    this.props.onChange({ availableSince: date });
+  };
 
   getValues = () =>
     this.props.value
       ? [this.context.intl.formatDate(this.props.value, longFormatterOption)]
       : undefined;
 
-  renderDateInput = () => (
-    <DateInput
-      name="available-since"
-      onChange={this.handlePeriodChange}
-      placeholder={translate('date')}
-      value={serializeDateShort(this.props.value)}
-    />
-  );
-
   render() {
     return (
       <FacetBox property="availableSince">
@@ -72,7 +62,14 @@ export default class AvailableSinceFacet extends React.PureComponent<Props> {
           values={this.getValues()}
         />
 
-        {this.props.open && this.renderDateInput()}
+        {this.props.open && (
+          <DateInput
+            name="available-since"
+            onChange={this.handlePeriodChange}
+            placeholder={translate('date')}
+            value={this.props.value}
+          />
+        )}
       </FacetBox>
     );
   }
index ed43efee2e35137f8ae115091473d20c989545c0..cfa9c803f41aedd6c1870e44123fea9b9e5dbd5b 100644 (file)
@@ -28,8 +28,8 @@ import FacetBox from '../../../components/facet/FacetBox';
 import FacetHeader from '../../../components/facet/FacetHeader';
 import FacetItem from '../../../components/facet/FacetItem';
 import { BarChart } from '../../../components/charts/bar-chart';
-import DateInput from '../../../components/controls/DateInput';
-import { isSameDay, parseDate, toShortNotSoISOString } from '../../../helpers/dates';
+import DateRangeInput from '../../../components/controls/DateRangeInput';
+import { isSameDay, parseDate } from '../../../helpers/dates';
 import { translate } from '../../../helpers/l10n';
 import { formatMeasure } from '../../../helpers/measures';
 /*:: import type { Component } from '../utils'; */
@@ -37,9 +37,9 @@ import { formatMeasure } from '../../../helpers/measures';
 /*::
 type Props = {|
   component?: Component,
-  createdAfter: string,
+  createdAfter: Date | void,
   createdAt: string,
-  createdBefore: string,
+  createdBefore: Date | void,
   createdInLast: string,
   facetMode: string,
   onChange: (changes: {}) => void,
@@ -64,9 +64,9 @@ export default class CreationDateFacet extends React.PureComponent {
   };
 
   hasValue = () =>
-    this.props.createdAfter.length > 0 ||
+    this.props.createdAfter !== undefined ||
     this.props.createdAt.length > 0 ||
-    this.props.createdBefore.length > 0 ||
+    this.props.createdBefore !== undefined ||
     this.props.createdInLast.length > 0 ||
     this.props.sinceLeakPeriod;
 
@@ -95,26 +95,13 @@ export default class CreationDateFacet extends React.PureComponent {
     createdBefore?: Date
   } */
   ) => {
-    this.resetTo({
-      createdAfter: toShortNotSoISOString(createdAfter),
-      createdBefore: createdBefore && toShortNotSoISOString(createdBefore)
-    });
+    this.resetTo({ createdAfter, createdBefore });
   };
 
-  handlePeriodChange = (property /*: string */, value /*: string */) => {
-    this.props.onChange({
-      createdAt: undefined,
-      createdInLast: undefined,
-      sinceLeakPeriod: undefined,
-      [property]: value ? toShortNotSoISOString(parseDate(value)) : undefined
-    });
+  handlePeriodChange = ({ from, to } /*: { from?: Date, to?: Date } */) => {
+    this.resetTo({ createdAfter: from, createdBefore: to });
   };
 
-  handlePeriodChangeBefore = (value /*: string */) =>
-    this.handlePeriodChange('createdBefore', value);
-
-  handlePeriodChangeAfter = (value /*: string */) => this.handlePeriodChange('createdAfter', value);
-
   handlePeriodClick = (period /*: string */) => this.resetTo({ createdInLast: period });
 
   handleLeakPeriodClick = () => this.resetTo({ sinceLeakPeriod: true });
@@ -191,8 +178,8 @@ export default class CreationDateFacet extends React.PureComponent {
       };
     });
 
-    const barsWidth = Math.floor(240 / data.length);
-    const width = barsWidth * data.length - 1 + 20;
+    const barsWidth = Math.floor(250 / data.length);
+    const width = barsWidth * data.length - 1 + 10;
 
     const maxValue = max(data.map(d => d.y));
     const format = this.props.facetMode === 'count' ? 'SHORT_INT' : 'SHORT_WORK_DUR';
@@ -204,7 +191,7 @@ export default class CreationDateFacet extends React.PureComponent {
         data={data}
         height={75}
         onBarClick={this.handleBarClick}
-        padding={[25, 10, 5, 10]}
+        padding={[25, 0, 5, 10]}
         width={width}
         xValues={xValues}
       />
@@ -227,21 +214,9 @@ export default class CreationDateFacet extends React.PureComponent {
     const { createdAfter, createdBefore } = this.props;
     return (
       <div className="search-navigator-date-facet-selection">
-        <DateInput
-          className="search-navigator-date-facet-selection-dropdown-left"
-          inputClassName="search-navigator-date-facet-selection-input"
-          maxDate={createdBefore ? toShortNotSoISOString(createdBefore) : '+0'}
-          onChange={this.handlePeriodChangeAfter}
-          placeholder={translate('from')}
-          value={createdAfter ? toShortNotSoISOString(createdAfter) : undefined}
-        />
-        <DateInput
-          className="search-navigator-date-facet-selection-dropdown-right"
-          inputClassName="search-navigator-date-facet-selection-input"
-          minDate={createdAfter ? toShortNotSoISOString(createdAfter) : undefined}
-          onChange={this.handlePeriodChangeBefore}
-          placeholder={translate('to')}
-          value={createdBefore ? toShortNotSoISOString(createdBefore) : undefined}
+        <DateRangeInput
+          onChange={this.handlePeriodChange}
+          value={{ from: createdAfter, to: createdBefore }}
         />
       </div>
     );
index 0878f213bd0089d91bfe3e64467e2de244ad291c..21656e444d7ced442f7d32a8374167fecf8ba453 100644 (file)
@@ -29,7 +29,9 @@ import {
   parseAsArray,
   parseAsString,
   serializeString,
-  serializeStringArray
+  serializeStringArray,
+  parseAsDate,
+  serializeDateShort
 } from '../../helpers/query';
 /*:: import type { RawQuery } from '../../helpers/query'; */
 
@@ -38,9 +40,9 @@ export type Query = {|
   assigned: boolean,
   assignees: Array<string>,
   authors: Array<string>,
-  createdAfter: string,
+  createdAfter: Date | void,
   createdAt: string,
-  createdBefore: string,
+  createdBefore: Date | void,
   createdInLast: string,
   directories: Array<string>,
   facetMode: string,
@@ -77,9 +79,9 @@ export function parseQuery(query /*: RawQuery */) /*: Query */ {
     assigned: parseAsBoolean(query.assigned),
     assignees: parseAsArray(query.assignees, parseAsString),
     authors: parseAsArray(query.authors, parseAsString),
-    createdAfter: parseAsString(query.createdAfter),
+    createdAfter: parseAsDate(query.createdAfter),
     createdAt: parseAsString(query.createdAt),
-    createdBefore: parseAsString(query.createdBefore),
+    createdBefore: parseAsDate(query.createdBefore),
     createdInLast: parseAsString(query.createdInLast),
     directories: parseAsArray(query.directories, parseAsString),
     facetMode: parseAsFacetMode(query.facetMode),
@@ -111,9 +113,9 @@ export function serializeQuery(query /*: Query */) /*: RawQuery */ {
     assigned: query.assigned ? undefined : 'false',
     assignees: serializeStringArray(query.assignees),
     authors: serializeStringArray(query.authors),
-    createdAfter: serializeString(query.createdAfter),
+    createdAfter: serializeDateShort(query.createdAfter),
     createdAt: serializeString(query.createdAt),
-    createdBefore: serializeString(query.createdBefore),
+    createdBefore: serializeDateShort(query.createdBefore),
     createdInLast: serializeString(query.createdInLast),
     directories: serializeStringArray(query.directories),
     facetMode: query.facetMode === 'effort' ? serializeString(query.facetMode) : undefined,
index afd26c06b83e8a1d0d65773290ceb1cfaba69ca0..1cb10269e5d9984f34ba71fc81f6ea191e581e48 100644 (file)
  */
 // @flow
 import React from 'react';
-import DateInput from '../../../components/controls/DateInput';
-import { parseAsDate } from '../../../helpers/query';
+import DateRangeInput from '../../../components/controls/DateRangeInput';
 import { translate } from '../../../helpers/l10n';
-import { toShortNotSoISOString } from '../../../helpers/dates';
 /*:: import type { RawQuery } from '../../../helpers/query'; */
 
 /*::
@@ -36,33 +34,20 @@ type Props = {
 export default class ProjectActivityDateInput extends React.PureComponent {
   /*:: props: Props; */
 
-  handleFromDateChange = (from /*: string */) => this.props.onChange({ from: parseAsDate(from) });
+  handleChange = ({ from, to } /*: { from?: Date, to?: Date } */) => {
+    this.props.onChange({ from, to });
+  };
 
-  handleToDateChange = (to /*: string */) => this.props.onChange({ to: parseAsDate(to) });
-
-  handleResetClick = () => this.props.onChange({ from: null, to: null });
-
-  formatDate = (date /*: ?Date */) => (date ? toShortNotSoISOString(date) : undefined);
+  handleResetClick = () => {
+    this.props.onChange({ from: null, to: null });
+  };
 
   render() {
     return (
       <div>
-        <DateInput
-          className="little-spacer-right"
-          maxDate={this.formatDate(this.props.to) || '+0'}
-          name="from"
-          onChange={this.handleFromDateChange}
-          placeholder={translate('from')}
-          value={this.formatDate(this.props.from)}
-        />
-        {'—'}
-        <DateInput
-          className="little-spacer-left"
-          minDate={this.formatDate(this.props.from)}
-          name="to"
-          onChange={this.handleToDateChange}
-          placeholder={translate('to')}
-          value={this.formatDate(this.props.to)}
+        <DateRangeInput
+          onChange={this.handleChange}
+          value={{ from: this.props.from, to: this.props.to }}
         />
         <button
           className="spacer-left"
index 5967a6968c2d6502d38094d811249497e16d8413..3406b3b0c76274cf97ff1d15f637e9aed05ee214 100644 (file)
@@ -2,25 +2,14 @@
 
 exports[`should render correctly the date inputs 1`] = `
 <div>
-  <DateInput
-    className="little-spacer-right"
-    format="yy-mm-dd"
-    maxDate="2016-12-27"
-    name="from"
+  <DateRangeInput
     onChange={[Function]}
-    placeholder="from"
-    value="2016-10-27"
-  />
-  â€”
-  <DateInput
-    className="little-spacer-left"
-    format="yy-mm-dd"
-    maxDate="+0"
-    minDate="2016-10-27"
-    name="to"
-    onChange={[Function]}
-    placeholder="to"
-    value="2016-12-27"
+    value={
+      Object {
+        "from": 2016-10-27T12:21:15.000Z,
+        "to": 2016-12-27T12:21:15.000Z,
+      }
+    }
   />
   <button
     className="spacer-left"
index 71376df4a741697b5c4a8cc979132738e3e2718a..24b422552fe5428cdfc8a2d6b46fa6ef616deced 100644 (file)
@@ -28,6 +28,7 @@ import { PAGE_SIZE, Project } from './utils';
 import ListFooter from '../../components/controls/ListFooter';
 import { getComponents } from '../../api/components';
 import { Organization } from '../../app/types';
+import { toNotSoISOString } from '../../helpers/dates';
 import { translate } from '../../helpers/l10n';
 
 export interface Props {
@@ -39,7 +40,7 @@ export interface Props {
 }
 
 interface State {
-  analyzedBefore?: string;
+  analyzedBefore?: Date;
   createProjectForm: boolean;
   page: number;
   projects: Project[];
@@ -80,8 +81,9 @@ export default class App extends React.PureComponent<Props, State> {
   }
 
   requestProjects = () => {
+    const { analyzedBefore } = this.state;
     const parameters = {
-      analyzedBefore: this.state.analyzedBefore,
+      analyzedBefore: analyzedBefore && toNotSoISOString(analyzedBefore),
       onProvisionedOnly: this.state.provisioned || undefined,
       organization: this.props.organization.key,
       p: this.state.page !== 1 ? this.state.page : undefined,
@@ -129,7 +131,7 @@ export default class App extends React.PureComponent<Props, State> {
     );
   };
 
-  handleDateChanged = (analyzedBefore?: string) =>
+  handleDateChanged = (analyzedBefore: Date | undefined) =>
     this.setState({ ready: false, page: 1, analyzedBefore }, this.requestProjects);
 
   onProjectSelected = (project: string) => {
index 663c51055777d9fc644e23969ef5536fd3cbe7f8..8fdcf361536ff4fdfc37e2155fd384e4c718fbad 100644 (file)
@@ -25,9 +25,10 @@ import AlertWarnIcon from '../../components/icons-components/AlertWarnIcon';
 import Modal from '../../components/controls/Modal';
 import Select from '../../components/controls/Select';
 import { Button, ResetButtonLink } from '../../components/ui/buttons';
+import { toNotSoISOString } from '../../helpers/dates';
 
 export interface Props {
-  analyzedBefore?: string;
+  analyzedBefore: Date | undefined;
   onClose: () => void;
   organization: string;
   provisioned: boolean;
@@ -80,6 +81,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S
   }
 
   handleConfirmClick = () => {
+    const { analyzedBefore } = this.props;
     const { permissionTemplate } = this.state;
     if (permissionTemplate) {
       this.setState({ submitting: true });
@@ -90,7 +92,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S
             templateId: permissionTemplate
           }
         : {
-            analyzedBefore: this.props.analyzedBefore,
+            analyzedBefore: analyzedBefore && toNotSoISOString(analyzedBefore),
             onProvisionedOnly: this.props.provisioned || undefined,
             organization: this.props.organization,
             qualifiers: this.props.qualifier,
index 9300d2bc96b83b9d302c08b86a447d25bb9a6a42..6eaf827ec804a9b6f0f19e6e6879cb2092b7845e 100644 (file)
@@ -23,9 +23,10 @@ import Modal from '../../components/controls/Modal';
 import AlertWarnIcon from '../../components/icons-components/AlertWarnIcon';
 import { Button, ResetButtonLink } from '../../components/ui/buttons';
 import { translate, translateWithParameters } from '../../helpers/l10n';
+import { toNotSoISOString } from '../../helpers/dates';
 
 export interface Props {
-  analyzedBefore?: string;
+  analyzedBefore: Date | undefined;
   onClose: () => void;
   onConfirm: () => void;
   organization: string;
@@ -54,13 +55,14 @@ export default class DeleteModal extends React.PureComponent<Props, State> {
 
   handleConfirmClick = () => {
     this.setState({ loading: true });
+    const { analyzedBefore } = this.props;
     const parameters = this.props.selection.length
       ? {
           organization: this.props.organization,
           projects: this.props.selection.join()
         }
       : {
-          analyzedBefore: this.props.analyzedBefore,
+          analyzedBefore: analyzedBefore && toNotSoISOString(analyzedBefore),
           onProvisionedOnly: this.props.provisioned || undefined,
           organization: this.props.organization,
           qualifiers: this.props.qualifier,
index c2df72d6befcda1878a1968f068685ccef97ee89..54d3e0704d833e0ab92eb6f3ca223497a298032b 100644 (file)
@@ -33,10 +33,10 @@ import SearchBox from '../../components/controls/SearchBox';
 import { Button } from '../../components/ui/buttons';
 
 export interface Props {
-  analyzedBefore?: string;
+  analyzedBefore: Date | undefined;
   onAllDeselected: () => void;
   onAllSelected: () => void;
-  onDateChanged: (analyzedBefore?: string) => void;
+  onDateChanged: (analyzedBefore: Date | undefined) => void;
   onDeleteProjects: () => void;
   onProvisionedChanged: (provisioned: boolean) => void;
   onQualifierChanged: (qualifier: string) => void;
index aa61b48ec408baa93bafcf0add4c03c48e842f8f..f8b0f32445dfa55b8ba32af917c83549c9c2e150 100644 (file)
  */
 /* eslint-disable import/order */
 import * as React from 'react';
-import { mount } from 'enzyme';
+import { shallow } from 'enzyme';
 import App, { Props } from '../App';
 import { Visibility } from '../../../app/types';
 
-jest.mock('react-dom');
-
 jest.mock('lodash', () => {
   const lodash = require.requireActual('lodash');
   lodash.debounce = (fn: Function) => (...args: any[]) => fn(args);
   return lodash;
 });
 
-// actual version breaks `mount`
-jest.mock('rc-tooltip', () => ({
-  // eslint-disable-next-line
-  default: function Tooltip() {
-    return null;
-  }
-}));
-
 jest.mock('../../../api/components', () => ({ getComponents: jest.fn() }));
 
 const getComponents = require('../../../api/components').getComponents as jest.Mock<any>;
@@ -59,12 +49,12 @@ beforeEach(() => {
 });
 
 it('fetches all projects on mount', () => {
-  mountRender();
+  shallowRender();
   expect(getComponents).lastCalledWith({ ...defaultSearchParameters, qualifiers: 'TRK' });
 });
 
 it('selects provisioned', () => {
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   wrapper.find('Search').prop<Function>('onProvisionedChanged')(true);
   expect(getComponents).lastCalledWith({
     ...defaultSearchParameters,
@@ -74,20 +64,20 @@ it('selects provisioned', () => {
 });
 
 it('changes qualifier and resets provisioned', () => {
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   wrapper.setState({ provisioned: true });
   wrapper.find('Search').prop<Function>('onQualifierChanged')('VW');
   expect(getComponents).lastCalledWith({ ...defaultSearchParameters, qualifiers: 'VW' });
 });
 
 it('searches', () => {
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   wrapper.find('Search').prop<Function>('onSearch')('foo');
   expect(getComponents).lastCalledWith({ ...defaultSearchParameters, q: 'foo', qualifiers: 'TRK' });
 });
 
 it('loads more', () => {
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   wrapper.find('ListFooter').prop<Function>('loadMore')();
   expect(getComponents).lastCalledWith({ ...defaultSearchParameters, p: 2, qualifiers: 'TRK' });
 });
@@ -96,7 +86,7 @@ it('selects and deselects projects', async () => {
   getComponents.mockImplementation(() =>
     Promise.resolve({ paging: { total: 2 }, components: [{ key: 'foo' }, { key: 'bar' }] })
   );
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   await new Promise(setImmediate);
 
   wrapper.find('Projects').prop<Function>('onProjectSelected')('foo');
@@ -120,7 +110,7 @@ it('selects and deselects projects', async () => {
 });
 
 it('creates project', () => {
-  const wrapper = mountRender();
+  const wrapper = shallowRender();
   expect(wrapper.find('CreateProjectForm').exists()).toBeFalsy();
 
   wrapper.find('Header').prop<Function>('onProjectCreate')();
@@ -138,13 +128,13 @@ it('creates project', () => {
 
 it('changes default project visibility', () => {
   const onVisibilityChange = jest.fn();
-  const wrapper = mountRender({ onVisibilityChange });
+  const wrapper = shallowRender({ onVisibilityChange });
   wrapper.find('Header').prop<Function>('onVisibilityChange')('private');
   expect(onVisibilityChange).toBeCalledWith('private');
 });
 
-function mountRender(props?: { [P in keyof Props]?: Props[P] }) {
-  return mount(
+function shallowRender(props?: { [P in keyof Props]?: Props[P] }) {
+  return shallow(
     <App
       currentUser={{ login: 'foo' }}
       hasProvisionPermission={true}
index 2ce76067896885cdb00bd5ac1255dbb46c2352ff..4667b3ef251926cef9c85a5dacc0af5151a7cd84 100644 (file)
@@ -22,6 +22,7 @@ import * as React from 'react';
 import { mount, shallow } from 'enzyme';
 import BulkApplyTemplateModal, { Props } from '../BulkApplyTemplateModal';
 import { click, waitAndUpdate } from '../../../helpers/testUtils';
+import { parseDate } from '../../../helpers/dates';
 
 jest.mock('react-dom');
 
@@ -58,7 +59,7 @@ it('bulk applies template to all results', async () => {
 
   click(wrapper.find('Button'));
   expect(bulkApplyTemplate).toBeCalledWith({
-    analyzedBefore: '2017-04-08T00:00:00.000Z',
+    analyzedBefore: '2017-04-08T00:00:00+0000',
     onProvisionedOnly: true,
     organization: 'org',
     q: 'bla',
@@ -106,7 +107,7 @@ it('closes', () => {
 function render(props?: { [P in keyof Props]?: Props[P] }) {
   return (
     <BulkApplyTemplateModal
-      analyzedBefore="2017-04-08T00:00:00.000Z"
+      analyzedBefore={parseDate('2017-04-08T00:00:00.000Z')}
       onClose={jest.fn()}
       organization="org"
       provisioned={true}
index 853593d2058bcd700fb37b97cdab179574c08269..75a0ffddf9cffec117383b8aa22df25e15dcbe74 100644 (file)
@@ -26,6 +26,7 @@ import * as React from 'react';
 import { shallow } from 'enzyme';
 import DeleteModal, { Props } from '../DeleteModal';
 import { click } from '../../../helpers/testUtils';
+import { parseDate } from '../../../helpers/dates';
 
 const bulkDeleteProjects = require('../../../api/components').bulkDeleteProjects as jest.Mock<any>;
 
@@ -42,7 +43,7 @@ it('deletes all projects', async () => {
   click(wrapper.find('Button'));
   expect(wrapper).toMatchSnapshot();
   expect(bulkDeleteProjects).toBeCalledWith({
-    analyzedBefore: '2017-04-08T00:00:00.000Z',
+    analyzedBefore: '2017-04-08T00:00:00+0000',
     onProvisionedOnly: undefined,
     organization: 'org',
     q: 'bla',
@@ -77,7 +78,7 @@ it('closes', () => {
 function shallowRender(props?: { [P in keyof Props]?: Props[P] }) {
   return shallow(
     <DeleteModal
-      analyzedBefore="2017-04-08T00:00:00.000Z"
+      analyzedBefore={parseDate('2017-04-08T00:00:00.000Z')}
       onClose={jest.fn()}
       onConfirm={jest.fn()}
       organization="org"
index 8e0fdb415ac61fb08b45c5ec4f44950e1b0afc9e..4b0b3bcae64899ae6ce3c0e828c37e8b4fad0299 100644 (file)
@@ -105,6 +105,7 @@ it('bulk applies permission template', () => {
 function shallowRender(props?: { [P in keyof Props]?: Props[P] }) {
   return shallow(
     <Search
+      analyzedBefore={undefined}
       onAllDeselected={jest.fn()}
       onAllSelected={jest.fn()}
       onDateChanged={jest.fn()}
index 31530ef6a9d55995b940de4ea7ad2278067eee55..07a23973ef753fc8d46504ae8f6be4b66c516928 100644 (file)
@@ -84,9 +84,7 @@ exports[`render qualifiers filter 1`] = `
           className="thin nowrap text-middle"
         >
           <DateInput
-            format="yy-mm-dd"
             inputClassName="input-medium"
-            maxDate="+0"
             name="analyzed-before"
             onChange={[MockFunction]}
             placeholder="last_analysis_before"
@@ -174,9 +172,7 @@ exports[`renders 1`] = `
           className="thin nowrap text-middle"
         >
           <DateInput
-            format="yy-mm-dd"
             inputClassName="input-medium"
-            maxDate="+0"
             name="analyzed-before"
             onChange={[MockFunction]}
             placeholder="last_analysis_before"
index 114807dd0f9bb2c282b202812ca6491bfe3e1cef..7c690dbc3df0ddcb869a422fb3ad7665344212d5 100644 (file)
@@ -26,6 +26,7 @@ import { getProfileChangelog } from '../../../api/quality-profiles';
 import { translate } from '../../../helpers/l10n';
 import { getProfileChangelogPath } from '../utils';
 import { Profile, ProfileChangelogEvent } from '../types';
+import { parseDate, toShortNotSoISOString } from '../../../helpers/dates';
 
 interface Props {
   location: {
@@ -125,27 +126,14 @@ export default class ChangelogContainer extends React.PureComponent<Props, State
     }
   }
 
-  handleFromDateChange = (fromDate?: string) => {
+  handleDateRangeChange = ({ from, to }: { from?: Date; to?: Date }) => {
     const path = getProfileChangelogPath(
       this.props.profile.name,
       this.props.profile.language,
       this.props.organization,
       {
-        since: fromDate,
-        to: this.props.location.query.to
-      }
-    );
-    this.context.router.push(path);
-  };
-
-  handleToDateChange = (toDate?: string) => {
-    const path = getProfileChangelogPath(
-      this.props.profile.name,
-      this.props.profile.language,
-      this.props.organization,
-      {
-        since: this.props.location.query.since,
-        to: toDate
+        since: from && toShortNotSoISOString(from),
+        to: to && toShortNotSoISOString(to)
       }
     );
     this.context.router.push(path);
@@ -172,10 +160,11 @@ export default class ChangelogContainer extends React.PureComponent<Props, State
       <div className="boxed-group boxed-group-inner js-profile-changelog">
         <header className="spacer-bottom">
           <ChangelogSearch
-            fromDate={query.since}
-            toDate={query.to}
-            onFromDateChange={this.handleFromDateChange}
-            onToDateChange={this.handleToDateChange}
+            dateRange={{
+              from: query.since ? parseDate(query.since) : undefined,
+              to: query.to ? parseDate(query.to) : undefined
+            }}
+            onDateRangeChange={this.handleDateRangeChange}
             onReset={this.handleReset}
           />
 
index f298e8f40567d6488545da41e4ab7ce0f4d1976a..7ea8aa32b51129c67700df6f62389516e82ad1ca 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import DateInput from '../../../components/controls/DateInput';
+import DateRangeInput from '../../../components/controls/DateRangeInput';
 import { Button } from '../../../components/ui/buttons';
-import { toShortNotSoISOString } from '../../../helpers/dates';
 import { translate } from '../../../helpers/l10n';
 
 interface Props {
-  fromDate?: string;
-  toDate?: string;
-  onFromDateChange: () => void;
+  dateRange: { from?: Date; to?: Date } | undefined;
+  onDateRangeChange: (range: { from?: Date; to?: Date }) => void;
   onReset: () => void;
-  onToDateChange: () => void;
 }
 
 export default class ChangelogSearch extends React.PureComponent<Props> {
-  formatDate = (date?: string) => (date ? toShortNotSoISOString(date) : undefined);
-
   render() {
     return (
       <div className="display-inline-block" id="quality-profile-changelog-form">
-        <DateInput
-          maxDate={this.formatDate(this.props.toDate) || '+0'}
-          name="since"
-          onChange={this.props.onFromDateChange}
-          placeholder={translate('from')}
-          value={this.formatDate(this.props.fromDate)}
-        />
-        {' â€” '}
-        <DateInput
-          minDate={this.formatDate(this.props.fromDate)}
-          name="to"
-          onChange={this.props.onToDateChange}
-          placeholder={translate('to')}
-          value={this.formatDate(this.props.toDate)}
-        />
+        <DateRangeInput onChange={this.props.onDateRangeChange} value={this.props.dateRange} />
         <Button className="spacer-left" onClick={this.props.onReset}>
           {translate('reset_verb')}
         </Button>
index e0812fa388d2c0408c702a585f21181d776d3dfe..7e9115e62e9d3a596035e96c860ef95479694989 100644 (file)
 import { shallow } from 'enzyme';
 import * as React from 'react';
 import ChangelogSearch from '../ChangelogSearch';
-import DateInput from '../../../../components/controls/DateInput';
 import { click } from '../../../../helpers/testUtils';
+import { parseDate } from '../../../../helpers/dates';
 
-it('should render DateInput', () => {
-  const onFromDateChange = jest.fn();
-  const onToDateChange = jest.fn();
+it('should render', () => {
   const output = shallow(
     <ChangelogSearch
-      fromDate="2016-01-01"
-      onFromDateChange={onFromDateChange}
+      dateRange={{
+        from: parseDate('2016-01-01T00:00:00.000Z'),
+        to: parseDate('2016-05-05T00:00:00.000Z')
+      }}
+      onDateRangeChange={jest.fn()}
       onReset={jest.fn()}
-      onToDateChange={onToDateChange}
-      toDate="2016-05-05"
     />
   );
-  const dateInputs = output.find(DateInput);
-  expect(dateInputs.length).toBe(2);
-  expect(dateInputs.at(0).prop('value')).toBe('2016-01-01');
-  expect(dateInputs.at(0).prop('onChange')).toBe(onFromDateChange);
-  expect(dateInputs.at(1).prop('value')).toBe('2016-05-05');
-  expect(dateInputs.at(1).prop('onChange')).toBe(onToDateChange);
+  expect(output).toMatchSnapshot();
 });
 
 it('should reset', () => {
   const onReset = jest.fn();
   const output = shallow(
     <ChangelogSearch
-      fromDate="2016-01-01"
-      onFromDateChange={jest.fn()}
+      dateRange={{
+        from: parseDate('2016-01-01T00:00:00.000Z'),
+        to: parseDate('2016-05-05T00:00:00.000Z')
+      }}
+      onDateRangeChange={jest.fn()}
       onReset={onReset}
-      onToDateChange={jest.fn()}
-      toDate="2016-05-05"
     />
   );
   expect(onReset).not.toBeCalled();
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/__snapshots__/ChangelogSearch-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/__snapshots__/ChangelogSearch-test.tsx.snap
new file mode 100644 (file)
index 0000000..cd8ed3b
--- /dev/null
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render 1`] = `
+<div
+  className="display-inline-block"
+  id="quality-profile-changelog-form"
+>
+  <DateRangeInput
+    onChange={[MockFunction]}
+    value={
+      Object {
+        "from": 2016-01-01T00:00:00.000Z,
+        "to": 2016-05-05T00:00:00.000Z,
+      }
+    }
+  />
+  <Button
+    className="spacer-left"
+    onClick={[MockFunction]}
+  >
+    reset_verb
+  </Button>
+</div>
+`;
index 7c1523338f7765146b5bc91f303b2e809e7c7d6c..8e9047701fe4ec7107b1d09a15a5d0f7c0984dc5 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import * as $ from 'jquery';
 import * as React from 'react';
 import * as classNames from 'classnames';
-import { pick } from 'lodash';
+import DayPicker, { DayModifiers, Modifier, Modifiers } from 'react-day-picker';
+import { intlShape, InjectedIntlProps } from 'react-intl';
+import { range } from 'lodash';
+import { addMonths, subMonths, setYear, setMonth } from 'date-fns';
+import OutsideClickHandler from './OutsideClickHandler';
+import Select from './Select';
 import * as theme from '../../app/theme';
+import CalendarIcon from '../icons-components/CalendarIcon';
+import ChevronLeftIcon from '../icons-components/ChevronLeftIcon';
+import ChevronRightIcon from '../icons-components/ChevronRightcon';
 import ClearIcon from '../icons-components/ClearIcon';
 import { ButtonIcon } from '../ui/buttons';
+import { getShortMonthName, getWeekDayName, getShortWeekDayName } from '../../helpers/l10n';
+import './DayPicker.css';
 import './styles.css';
 
-interface Props {
+export interface Props {
   className?: string;
-  format?: string;
+  currentMonth?: Date;
+  highlightFrom?: Date;
+  highlightTo?: Date;
   inputClassName?: string;
-  // see http://api.jqueryui.com/datepicker/#option-maxDate for details
-  maxDate?: Date | string | number;
-  minDate?: Date | string | number;
-  name: string;
-  onChange: (value?: string) => void;
+  maxDate?: Date;
+  minDate?: Date;
+  name?: string;
+  onChange: (date: Date | undefined) => void;
   placeholder: string;
-  value?: string;
+  value?: Date;
 }
 
-export default class DateInput extends React.PureComponent<Props> {
+interface State {
+  currentMonth: Date;
+  open: boolean;
+  lastHovered?: Date;
+}
+
+type Week = [string, string, string, string, string, string, string];
+
+export default class DateInput extends React.PureComponent<Props, State> {
+  // prettier-ignore
+  context!: InjectedIntlProps;
   input?: HTMLInputElement | null;
 
-  static defaultProps = {
-    format: 'yy-mm-dd',
-    maxDate: '+0'
+  static contextTypes = {
+    intl: intlShape
   };
 
-  componentDidMount() {
-    this.attachDatePicker();
-  }
-
-  componentDidUpdate(prevProps: Props) {
-    if ($.fn && ($.fn as any).datepicker && this.input) {
-      if (prevProps.maxDate !== this.props.maxDate) {
-        ($(this.input) as any).datepicker('option', { maxDate: this.props.maxDate });
-      }
-      if (prevProps.minDate !== this.props.minDate) {
-        ($(this.input) as any).datepicker('option', { minDate: this.props.minDate });
-      }
-    }
+  constructor(props: Props) {
+    super(props);
+    this.state = { currentMonth: props.value || props.currentMonth || new Date(), open: false };
   }
 
-  handleChange = () => {
+  focus = () => {
     if (this.input) {
-      const { value } = this.input;
-      this.props.onChange(value);
+      this.input.focus();
     }
+    this.openCalendar();
   };
 
   handleResetClick = () => {
+    this.closeCalendar();
     this.props.onChange(undefined);
   };
 
-  attachDatePicker() {
-    const opts = {
-      dateFormat: this.props.format,
-      changeMonth: true,
-      changeYear: true,
-      maxDate: this.props.maxDate,
-      minDate: this.props.minDate,
-      onSelect: this.handleChange
-    };
-
-    if ($.fn && ($.fn as any).datepicker && this.input) {
-      ($(this.input) as any).datepicker(opts);
+  openCalendar = () => {
+    this.setState({
+      currentMonth: this.props.value || this.props.currentMonth || new Date(),
+      lastHovered: undefined,
+      open: true
+    });
+  };
+
+  closeCalendar = () => {
+    this.setState({ open: false });
+  };
+
+  handleDayClick = (day: Date, modifiers: DayModifiers) => {
+    if (!modifiers.disabled) {
+      this.closeCalendar();
+      this.props.onChange(day);
     }
-  }
+  };
+
+  handleDayMouseEnter = (day: Date, modifiers: DayModifiers) => {
+    this.setState({ lastHovered: modifiers.disabled ? undefined : day });
+  };
+
+  handleCurrentMonthChange = ({ value }: { value: number }) => {
+    this.setState((state: State) => ({ currentMonth: setMonth(state.currentMonth, value) }));
+  };
+
+  handleCurrentYearChange = ({ value }: { value: number }) => {
+    this.setState(state => ({ currentMonth: setYear(state.currentMonth, value) }));
+  };
+
+  handlePreviousMonthClick = () => {
+    this.setState(state => ({ currentMonth: subMonths(state.currentMonth, 1) }));
+  };
+
+  handleNextMonthClick = () => {
+    this.setState(state => ({ currentMonth: addMonths(state.currentMonth, 1) }));
+  };
 
   render() {
-    const inputProps: { name?: string; placeholder?: string } = pick(this.props, [
-      'placeholder',
-      'name'
-    ]);
+    const { highlightFrom, highlightTo, minDate, value } = this.props;
+    const { formatDate } = this.context.intl;
+    const { lastHovered } = this.state;
+    const formattedValue =
+      value && formatDate(value, { year: 'numeric', month: 'short', day: 'numeric' });
+
+    const after = this.props.maxDate || new Date();
+
+    const months = range(12);
+    const years = range(new Date().getFullYear() - 10, new Date().getFullYear() + 1);
+
+    const selectedDays: Modifier[] = value ? [value] : [];
+    let modifiers: Partial<Modifiers> | undefined;
+    const lastHoveredOrValue = lastHovered || value;
+
+    if (highlightFrom && lastHoveredOrValue) {
+      modifiers = { highlighted: { from: highlightFrom, to: lastHoveredOrValue } };
+      selectedDays.push(highlightFrom);
+    }
+    if (highlightTo && lastHoveredOrValue) {
+      modifiers = { highlighted: { from: lastHoveredOrValue, to: highlightTo } };
+      selectedDays.push(highlightTo);
+    }
+
+    const weekdaysLong = range(7).map(getWeekDayName) as Week;
+    const weekdaysShort = range(7).map(getShortWeekDayName) as Week;
 
     return (
-      <span className={classNames('date-input-control', this.props.className)}>
-        <input
-          className={classNames('date-input-control-input', this.props.inputClassName)}
-          onChange={this.handleChange}
-          readOnly={true}
-          ref={node => (this.input = node)}
-          type="text"
-          value={this.props.value || ''}
-          {...inputProps}
-        />
-        <span className="date-input-control-icon">
-          <svg width="14" height="14" viewBox="0 0 16 16">
-            <path d="M5.5 6h2v2h-2V6zm3 0h2v2h-2V6zm3 0h2v2h-2V6zm-9 6h2v2h-2v-2zm3 0h2v2h-2v-2zm3 0h2v2h-2v-2zm-3-3h2v2h-2V9zm3 0h2v2h-2V9zm3 0h2v2h-2V9zm-9 0h2v2h-2V9zm11-9v1h-2V0h-7v1h-2V0h-2v16h15V0h-2zm1 15h-13V4h13v11z" />
-          </svg>
-        </span>
-        {this.props.value !== undefined && (
-          <ButtonIcon
-            className="button-tiny date-input-control-reset"
-            color={theme.gray60}
-            onClick={this.handleResetClick}>
-            <ClearIcon size={12} />
-          </ButtonIcon>
+      <OutsideClickHandler onClickOutside={this.closeCalendar}>
+        {({ ref }) => (
+          <span className={classNames('date-input-control', this.props.className)} ref={ref}>
+            <input
+              className={classNames('date-input-control-input', this.props.inputClassName, {
+                'is-filled': this.props.value !== undefined
+              })}
+              name={this.props.name}
+              onFocus={this.openCalendar}
+              placeholder={this.props.placeholder}
+              readOnly={true}
+              ref={node => (this.input = node)}
+              type="text"
+              value={formattedValue || ''}
+            />
+            <CalendarIcon className="date-input-control-icon" fill="" />
+            {this.props.value !== undefined && (
+              <ButtonIcon
+                className="button-tiny date-input-control-reset"
+                color={theme.gray60}
+                onClick={this.handleResetClick}>
+                <ClearIcon size={12} />
+              </ButtonIcon>
+            )}
+            {this.state.open && (
+              <div className="date-input-calendar">
+                <nav className="date-input-calendar-nav">
+                  <ButtonIcon className="button-small" onClick={this.handlePreviousMonthClick}>
+                    <ChevronLeftIcon />
+                  </ButtonIcon>
+                  <div className="date-input-calender-month">
+                    <Select
+                      className="date-input-calender-month-select"
+                      onChange={this.handleCurrentMonthChange}
+                      options={months.map(month => ({
+                        label: getShortMonthName(month),
+                        value: month
+                      }))}
+                      value={this.state.currentMonth.getMonth()}
+                    />
+                    <Select
+                      className="date-input-calender-month-select spacer-left"
+                      onChange={this.handleCurrentYearChange}
+                      options={years.map(year => ({ label: String(year), value: year }))}
+                      value={this.state.currentMonth.getFullYear()}
+                    />
+                  </div>
+                  <ButtonIcon className="button-small" onClick={this.handleNextMonthClick}>
+                    <ChevronRightIcon />
+                  </ButtonIcon>
+                </nav>
+                <DayPicker
+                  captionElement={<NullComponent />}
+                  disabledDays={{ after, before: minDate }}
+                  firstDayOfWeek={1}
+                  modifiers={modifiers}
+                  month={this.state.currentMonth}
+                  navbarElement={<NullComponent />}
+                  onDayClick={this.handleDayClick}
+                  onDayMouseEnter={this.handleDayMouseEnter}
+                  selectedDays={selectedDays}
+                  weekdaysLong={weekdaysLong}
+                  weekdaysShort={weekdaysShort}
+                />
+              </div>
+            )}
+          </span>
         )}
-      </span>
+      </OutsideClickHandler>
     );
   }
 }
+
+function NullComponent() {
+  return null;
+}
diff --git a/server/sonar-web/src/main/js/components/controls/DateRangeInput.tsx b/server/sonar-web/src/main/js/components/controls/DateRangeInput.tsx
new file mode 100644 (file)
index 0000000..b92650f
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import * as classNames from 'classnames';
+import DateInput from './DateInput';
+import { translate } from '../../helpers/l10n';
+
+type DateRange = { from?: Date; to?: Date };
+
+interface Props {
+  className?: string;
+  maxDate?: Date;
+  minDate?: Date;
+  onChange: (date: DateRange) => void;
+  value?: DateRange;
+}
+
+export default class DateRangeInput extends React.PureComponent<Props> {
+  toDateInput?: DateInput | null;
+
+  get from() {
+    return this.props.value && this.props.value.from;
+  }
+
+  get to() {
+    return this.props.value && this.props.value.to;
+  }
+
+  handleFromChange = (from: Date | undefined) => {
+    this.props.onChange({ from, to: this.to });
+
+    // use `setTimeout` to work around the immediate closing of the `toDateInput`
+    setTimeout(() => {
+      if (from && !this.to && this.toDateInput) {
+        this.toDateInput.focus();
+      }
+    }, 0);
+  };
+
+  handleToChange = (to: Date | undefined) => {
+    this.setState({ to });
+    this.props.onChange({ from: this.from, to });
+  };
+
+  render() {
+    return (
+      <div className={classNames('display-inline-flex-center', this.props.className)}>
+        <DateInput
+          currentMonth={this.to}
+          data-test="from"
+          highlightTo={this.to}
+          maxDate={this.to}
+          onChange={this.handleFromChange}
+          placeholder={translate('start_date')}
+          value={this.from}
+        />
+        <span className="note little-spacer-left little-spacer-right">{translate('to_')}</span>
+        <DateInput
+          currentMonth={this.from}
+          data-test="to"
+          highlightFrom={this.from}
+          minDate={this.from}
+          onChange={this.handleToChange}
+          placeholder={translate('end_date')}
+          ref={element => (this.toDateInput = element)}
+          value={this.to}
+        />
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/components/controls/DayPicker.css b/server/sonar-web/src/main/js/components/controls/DayPicker.css
new file mode 100644 (file)
index 0000000..153a183
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+.DayPicker {
+  display: inline-block;
+}
+
+.DayPicker-wrapper {
+  position: relative;
+  user-select: none;
+  padding-bottom: var(--gridSize);
+  flex-direction: row;
+}
+
+.DayPicker-Months {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+}
+
+.DayPicker-Month {
+  display: table;
+  border-collapse: collapse;
+  border-spacing: 0;
+  user-select: none;
+  margin: 0 var(--gridSize);
+  margin-top: var(--gridSize);
+}
+
+.DayPicker-Weekdays {
+  display: table-header-group;
+}
+
+.DayPicker-WeekdaysRow {
+  display: table-row;
+}
+
+.DayPicker-Weekday {
+  display: table-cell;
+  padding: var(--gridSize);
+  font-size: var(--smallFontSize);
+  text-align: center;
+  color: var(--gray60);
+}
+
+.DayPicker-Weekday abbr[title] {
+  border-bottom: none;
+  text-decoration: none;
+}
+
+.DayPicker-Body {
+  display: table-row-group;
+}
+
+.DayPicker-Week {
+  display: table-row;
+}
+
+.DayPicker-Day {
+  display: table-cell;
+  line-height: 15px;
+  padding: var(--gridSize);
+  text-align: center;
+  cursor: pointer;
+  vertical-align: top;
+  outline: none;
+}
+
+.DayPicker--interactionDisabled .DayPicker-Day {
+  cursor: default;
+}
+
+.DayPicker-Footer {
+  padding-top: var(--gridSize);
+}
+
+/* Default modifiers */
+
+.DayPicker-Day--today {
+  font-weight: bold;
+}
+
+.DayPicker-Day--outside {
+  cursor: default;
+  color: #8b9898;
+}
+
+.DayPicker-Day--disabled {
+  color: var(--gray80);
+  cursor: not-allowed;
+}
+
+/* Example modifiers */
+
+.DayPicker-Day--sunday {
+  background-color: #f7f8f8;
+}
+
+.DayPicker-Day--sunday:not(.DayPicker-Day--today) {
+  color: #dce0e0;
+}
+
+.DayPicker-Day--selected:not(.DayPicker-Day--disabled):not(.DayPicker-Day--outside) {
+  background-color: var(--blue);
+  color: #fff;
+}
+
+.DayPicker:not(.DayPicker--interactionDisabled)
+  .DayPicker-Day:not(.DayPicker-Day--disabled):not(.DayPicker-Day--selected):not(.DayPicker-Day--highlighted):not(.DayPicker-Day--outside):hover {
+  background-color: var(--barBackgroundColor);
+}
+
+.DayPicker-Day--highlighted:not(.DayPicker-Day--disabled):not(.DayPicker-Day--selected):not(.DayPicker-Day--outside) {
+  background-color: var(--lightBlue);
+}
diff --git a/server/sonar-web/src/main/js/components/controls/OutsideClickHandler.tsx b/server/sonar-web/src/main/js/components/controls/OutsideClickHandler.tsx
new file mode 100644 (file)
index 0000000..3886a89
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+
+interface Props {
+  children: (props: { ref: React.Ref<Element> }) => React.ReactNode;
+  onClickOutside: () => void;
+}
+
+export default class OutsideClickHandler extends React.Component<Props> {
+  element?: Element | null;
+
+  componentDidMount() {
+    this.addClickHandler();
+  }
+
+  componentWillUnmount() {
+    this.removeClickHandler();
+  }
+
+  addClickHandler = () => {
+    window.addEventListener('click', this.handleWindowClick);
+  };
+
+  removeClickHandler = () => {
+    window.removeEventListener('click', this.handleWindowClick);
+  };
+
+  handleWindowClick = (event: MouseEvent) => {
+    if (!this.element || !this.element.contains(event.target as Node)) {
+      this.props.onClickOutside();
+    }
+  };
+
+  handleRef = (element: Element | null) => {
+    this.element = element;
+  };
+
+  render() {
+    return this.props.children({ ref: this.handleRef });
+  }
+}
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
new file mode 100644 (file)
index 0000000..37c9744
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { subMonths, setMonth, setYear, addDays, subDays } from 'date-fns';
+import DateInput, { Props } from '../DateInput';
+import { shallowWithIntl } from '../../../helpers/testUtils';
+import { parseDate } from '../../../helpers/dates';
+
+// need to mock, because react-day-picker uses `new Date()` as a default prop for `initialMonth`
+jest.mock('react-day-picker', () => ({
+  // eslint-disable-next-line func-name-matching
+  default: function DayPicker() {
+    return null;
+  }
+}));
+
+const dateA = parseDate('2018-01-17T00:00:00.000Z');
+const dateB = parseDate('2018-02-05T00:00:00.000Z');
+
+it('should render', () => {
+  // pass `maxDate` and `minDate` to avoid differences in snapshots
+  const { wrapper } = shallowRender();
+
+  expect(wrapper).toMatchSnapshot();
+  expect(wrapper.dive()).toMatchSnapshot();
+
+  wrapper.setProps({ value: dateA });
+  expect(wrapper.dive()).toMatchSnapshot();
+
+  wrapper.setState({ open: true });
+  expect(wrapper.dive()).toMatchSnapshot();
+});
+
+it('should change current month', () => {
+  const { wrapper, instance } = shallowRender();
+  expect(wrapper.state().currentMonth).toEqual(dateA);
+
+  instance.handlePreviousMonthClick();
+  expect(wrapper.state().currentMonth).toEqual(subMonths(dateA, 1));
+
+  instance.handleNextMonthClick();
+  expect(wrapper.state().currentMonth).toEqual(dateA);
+
+  instance.handleCurrentMonthChange({ value: 5 });
+  expect(wrapper.state().currentMonth).toEqual(setMonth(dateA, 5));
+
+  instance.handleCurrentYearChange({ value: 2015 });
+  expect(wrapper.state().currentMonth).toEqual(setYear(setMonth(dateA, 5), 2015));
+});
+
+it('should select a day', () => {
+  const onChange = jest.fn();
+  const { wrapper, instance } = shallowRender({ onChange });
+  wrapper.setState({ open: true });
+
+  instance.handleDayClick(dateA, { disabled: true, outside: undefined, today: undefined });
+  expect(onChange).not.toBeCalled();
+  expect(wrapper.state().open).toBe(true);
+
+  instance.handleDayClick(dateA, { outside: undefined, today: undefined });
+  expect(onChange).lastCalledWith(dateA);
+  expect(wrapper.state().open).toBe(false);
+  expect(wrapper.dive()).toMatchSnapshot();
+
+  instance.handleResetClick();
+  expect(onChange).lastCalledWith(undefined);
+});
+
+it('should hightlightFrom range', () => {
+  const { wrapper, instance } = shallowRender({ highlightFrom: dateA });
+  wrapper.setState({ open: true });
+
+  const dateC = addDays(dateA, 3);
+  instance.handleDayMouseEnter(dateC, { outside: undefined, today: undefined });
+  wrapper.update();
+  const dayPicker = wrapper.dive().find('DayPicker');
+  expect(dayPicker.prop('modifiers')).toEqual({ highlighted: { from: dateA, to: dateC } });
+  expect(dayPicker.prop('selectedDays')).toEqual([dateA]);
+});
+
+it('should hightlightTo range', () => {
+  const { wrapper, instance } = shallowRender({ highlightTo: dateB });
+  wrapper.setState({ open: true });
+
+  const dateC = subDays(dateB, 5);
+  instance.handleDayMouseEnter(dateC, { outside: undefined, today: undefined });
+  wrapper.update();
+  const dayPicker = wrapper.dive().find('DayPicker');
+  expect(dayPicker.prop('modifiers')).toEqual({ highlighted: { from: dateC, to: dateB } });
+  expect(dayPicker.prop('selectedDays')).toEqual([dateB]);
+});
+
+function shallowRender(props?: Partial<Props>) {
+  const wrapper = shallowWithIntl(
+    <DateInput
+      currentMonth={dateA}
+      maxDate={dateB}
+      minDate={dateA}
+      onChange={jest.fn()}
+      placeholder="placeholder"
+      {...props}
+    />
+  );
+  const instance = wrapper.instance() as DateInput;
+  return { wrapper, instance };
+}
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/DateRangeInput-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/DateRangeInput-test.tsx
new file mode 100644 (file)
index 0000000..ad4a3bc
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import DateRangeInput from '../DateRangeInput';
+import { parseDate } from '../../../helpers/dates';
+
+const dateA = parseDate('2018-01-17T00:00:00.000Z');
+const dateB = parseDate('2018-02-05T00:00:00.000Z');
+
+it('should render', () => {
+  expect(
+    shallow(<DateRangeInput onChange={jest.fn()} value={{ from: dateA, to: dateB }} />)
+  ).toMatchSnapshot();
+});
+
+it('should change', () => {
+  const onChange = jest.fn();
+  const wrapper = shallow(<DateRangeInput onChange={onChange} />);
+
+  wrapper.find('DateInput[data-test="from"]').prop<Function>('onChange')(dateA);
+  expect(onChange).lastCalledWith({ from: dateA, to: undefined });
+  wrapper.setProps({ value: { from: dateA } });
+
+  wrapper.find('DateInput[data-test="to"]').prop<Function>('onChange')(dateB);
+  wrapper.update();
+  expect(onChange).lastCalledWith({ from: dateA, to: dateB });
+});
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap
new file mode 100644 (file)
index 0000000..af68360
--- /dev/null
@@ -0,0 +1,276 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render 1`] = `
+<OutsideClickHandler
+  onClickOutside={[Function]}
+/>
+`;
+
+exports[`should render 2`] = `
+<span
+  className="date-input-control"
+>
+  <input
+    className="date-input-control-input"
+    onFocus={[Function]}
+    placeholder="placeholder"
+    readOnly={true}
+    type="text"
+    value=""
+  />
+  <CalendarIcon
+    className="date-input-control-icon"
+    fill=""
+  />
+</span>
+`;
+
+exports[`should render 3`] = `
+<span
+  className="date-input-control"
+>
+  <input
+    className="date-input-control-input is-filled"
+    onFocus={[Function]}
+    placeholder="placeholder"
+    readOnly={true}
+    type="text"
+    value="Jan 17, 2018"
+  />
+  <CalendarIcon
+    className="date-input-control-icon"
+    fill=""
+  />
+  <ButtonIcon
+    className="button-tiny date-input-control-reset"
+    color="#999"
+    onClick={[Function]}
+  >
+    <ClearIcon
+      size={12}
+    />
+  </ButtonIcon>
+</span>
+`;
+
+exports[`should render 4`] = `
+<span
+  className="date-input-control"
+>
+  <input
+    className="date-input-control-input is-filled"
+    onFocus={[Function]}
+    placeholder="placeholder"
+    readOnly={true}
+    type="text"
+    value="Jan 17, 2018"
+  />
+  <CalendarIcon
+    className="date-input-control-icon"
+    fill=""
+  />
+  <ButtonIcon
+    className="button-tiny date-input-control-reset"
+    color="#999"
+    onClick={[Function]}
+  >
+    <ClearIcon
+      size={12}
+    />
+  </ButtonIcon>
+  <div
+    className="date-input-calendar"
+  >
+    <nav
+      className="date-input-calendar-nav"
+    >
+      <ButtonIcon
+        className="button-small"
+        onClick={[Function]}
+      >
+        <ChevronLeftIcon />
+      </ButtonIcon>
+      <div
+        className="date-input-calender-month"
+      >
+        <Select
+          className="date-input-calender-month-select"
+          onChange={[Function]}
+          options={
+            Array [
+              Object {
+                "label": "Jan",
+                "value": 0,
+              },
+              Object {
+                "label": "Feb",
+                "value": 1,
+              },
+              Object {
+                "label": "Mar",
+                "value": 2,
+              },
+              Object {
+                "label": "Apr",
+                "value": 3,
+              },
+              Object {
+                "label": "May",
+                "value": 4,
+              },
+              Object {
+                "label": "Jun",
+                "value": 5,
+              },
+              Object {
+                "label": "Jul",
+                "value": 6,
+              },
+              Object {
+                "label": "Aug",
+                "value": 7,
+              },
+              Object {
+                "label": "Sep",
+                "value": 8,
+              },
+              Object {
+                "label": "Oct",
+                "value": 9,
+              },
+              Object {
+                "label": "Nov",
+                "value": 10,
+              },
+              Object {
+                "label": "Dec",
+                "value": 11,
+              },
+            ]
+          }
+          value={0}
+        />
+        <Select
+          className="date-input-calender-month-select spacer-left"
+          onChange={[Function]}
+          options={
+            Array [
+              Object {
+                "label": "2008",
+                "value": 2008,
+              },
+              Object {
+                "label": "2009",
+                "value": 2009,
+              },
+              Object {
+                "label": "2010",
+                "value": 2010,
+              },
+              Object {
+                "label": "2011",
+                "value": 2011,
+              },
+              Object {
+                "label": "2012",
+                "value": 2012,
+              },
+              Object {
+                "label": "2013",
+                "value": 2013,
+              },
+              Object {
+                "label": "2014",
+                "value": 2014,
+              },
+              Object {
+                "label": "2015",
+                "value": 2015,
+              },
+              Object {
+                "label": "2016",
+                "value": 2016,
+              },
+              Object {
+                "label": "2017",
+                "value": 2017,
+              },
+              Object {
+                "label": "2018",
+                "value": 2018,
+              },
+            ]
+          }
+          value={2018}
+        />
+      </div>
+      <ButtonIcon
+        className="button-small"
+        onClick={[Function]}
+      >
+        <ChevronRightIcon />
+      </ButtonIcon>
+    </nav>
+    <DayPicker
+      captionElement={<NullComponent />}
+      disabledDays={
+        Object {
+          "after": 2018-02-05T00:00:00.000Z,
+          "before": 2018-01-17T00:00:00.000Z,
+        }
+      }
+      firstDayOfWeek={1}
+      month={2018-01-17T00:00:00.000Z}
+      navbarElement={<NullComponent />}
+      onDayClick={[Function]}
+      onDayMouseEnter={[Function]}
+      selectedDays={
+        Array [
+          2018-01-17T00:00:00.000Z,
+        ]
+      }
+      weekdaysLong={
+        Array [
+          "Sunday",
+          "Monday",
+          "Tuesday",
+          "Wednesday",
+          "Thursday",
+          "Friday",
+          "Saturday",
+        ]
+      }
+      weekdaysShort={
+        Array [
+          "Sun",
+          "Mon",
+          "Tue",
+          "Wed",
+          "Thu",
+          "Fri",
+          "Sat",
+        ]
+      }
+    />
+  </div>
+</span>
+`;
+
+exports[`should select a day 1`] = `
+<span
+  className="date-input-control"
+>
+  <input
+    className="date-input-control-input"
+    onFocus={[Function]}
+    placeholder="placeholder"
+    readOnly={true}
+    type="text"
+    value=""
+  />
+  <CalendarIcon
+    className="date-input-control-icon"
+    fill=""
+  />
+</span>
+`;
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateRangeInput-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateRangeInput-test.tsx.snap
new file mode 100644 (file)
index 0000000..2faf7c8
--- /dev/null
@@ -0,0 +1,31 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render 1`] = `
+<div
+  className="display-inline-flex-center"
+>
+  <DateInput
+    currentMonth={2018-02-05T00:00:00.000Z}
+    data-test="from"
+    highlightTo={2018-02-05T00:00:00.000Z}
+    maxDate={2018-02-05T00:00:00.000Z}
+    onChange={[Function]}
+    placeholder="start_date"
+    value={2018-01-17T00:00:00.000Z}
+  />
+  <span
+    className="note little-spacer-left little-spacer-right"
+  >
+    to_
+  </span>
+  <DateInput
+    currentMonth={2018-01-17T00:00:00.000Z}
+    data-test="to"
+    highlightFrom={2018-01-17T00:00:00.000Z}
+    minDate={2018-01-17T00:00:00.000Z}
+    onChange={[Function]}
+    placeholder="end_date"
+    value={2018-02-05T00:00:00.000Z}
+  />
+</div>
+`;
index 1d3ad71f9d5d4fb0254b3682e1544646f89cee6d..a68db8e3879486d08d26156e05c98216a263ff5a 100644 (file)
   cursor: pointer;
 }
 
+.date-input-control-input.is-filled {
+  padding-right: 16px !important;
+}
+
 .date-input-control-icon {
   position: absolute;
-  top: 5px;
-  left: 5px;
+  top: 4px;
+  left: 4px;
 }
 
 .date-input-control-icon path {
   border: none;
 }
 
+.date-input-calendar {
+  position: absolute;
+  z-index: var(--dropdownMenuZIndex);
+  top: 100%;
+  left: 0;
+  border: 1px solid var(--barBorderColor);
+  background-color: #fff;
+  box-shadow: var(--defaultShadow);
+}
+
+.date-input-calendar-nav {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-top: var(--gridSize);
+  padding-left: var(--gridSize);
+  padding-right: var(--gridSize);
+}
+
+.date-input-calender-month {
+}
+
+.date-input-calender-month-select {
+  width: 70px;
+}
+
 .boolean-toggle {
   display: inline-block;
   vertical-align: middle;
diff --git a/server/sonar-web/src/main/js/components/icons-components/CalendarIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/CalendarIcon.tsx
new file mode 100644 (file)
index 0000000..8ad412e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { IconProps } from './types';
+
+export default function CalendarIcon({ className, fill = 'currentColor', size = 16 }: IconProps) {
+  return (
+    <svg
+      className={className}
+      height={size}
+      version="1.1"
+      viewBox="0 0 16 16"
+      width={size}
+      xmlSpace="preserve"
+      xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path
+        d="M2 14h2.25v-2.25H2V14zm2.75 0h2.5v-2.25h-2.5V14zM2 11.25h2.25v-2.5H2v2.5zm2.75 0h2.5v-2.5h-2.5v2.5zM2 8.25h2.25V6H2v2.25zM7.75 14h2.5v-2.25h-2.5V14zm-3-5.75h2.5V6h-2.5v2.25zm6 5.75H13v-2.25h-2.25V14zm-3-2.75h2.5v-2.5h-2.5v2.5zM5 4.5V2.25a.24.24 0 0 0-.074-.176A.24.24 0 0 0 4.75 2h-.5a.24.24 0 0 0-.176.074A.24.24 0 0 0 4 2.25V4.5a.24.24 0 0 0 .074.176.24.24 0 0 0 .176.074h.5a.24.24 0 0 0 .176-.074A.24.24 0 0 0 5 4.5zm5.75 6.75H13v-2.5h-2.25v2.5zm-3-3h2.5V6h-2.5v2.25zm3 0H13V6h-2.25v2.25zM11 4.5V2.25a.24.24 0 0 0-.074-.176A.24.24 0 0 0 10.75 2h-.5a.24.24 0 0 0-.176.074.24.24 0 0 0-.074.176V4.5a.24.24 0 0 0 .074.176.24.24 0 0 0 .176.074h.5a.24.24 0 0 0 .176-.074A.24.24 0 0 0 11 4.5zm3-.5v10c0 .27-.099.505-.297.703A.961.961 0 0 1 13 15H2a.961.961 0 0 1-.703-.297A.961.961 0 0 1 1 14V4c0-.27.099-.505.297-.703A.961.961 0 0 1 2 3h1v-.75c0-.344.122-.638.367-.883S3.907 1 4.25 1h.5c.344 0 .638.122.883.367S6 1.907 6 2.25V3h3v-.75c0-.344.122-.638.367-.883S9.907 1 10.25 1h.5c.344 0 .638.122.883.367s.367.54.367.883V3h1c.27 0 .505.099.703.297A.961.961 0 0 1 14 4z"
+        style={{ fill }}
+      />
+    </svg>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/icons-components/ChevronDownIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/ChevronDownIcon.tsx
new file mode 100644 (file)
index 0000000..e70784e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { IconProps } from './types';
+
+export default function ChevronDownIcon({
+  className,
+  fill = 'currentColor',
+  size = 16
+}: IconProps) {
+  return (
+    <svg
+      className={className}
+      height={size}
+      version="1.1"
+      viewBox="0 0 16 16"
+      width={size}
+      xmlSpace="preserve"
+      xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path
+        d="M7.72 11.596L3.119 6.992A.382.382 0 0 1 3 6.713c0-.108.04-.2.118-.279l1.03-1.03a.382.382 0 0 1 .278-.117c.108 0 .201.04.28.117L8 8.7l3.294-3.295a.382.382 0 0 1 .28-.117c.108 0 .2.04.279.117l1.03 1.03a.382.382 0 0 1 .117.28c0 .107-.04.2-.118.278L8.28 11.596a.382.382 0 0 1-.279.117.382.382 0 0 1-.28-.117z"
+        style={{ fill }}
+      />;
+    </svg>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/icons-components/ChevronLeftIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/ChevronLeftIcon.tsx
new file mode 100644 (file)
index 0000000..8bfb0dc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { IconProps } from './types';
+
+export default function ChevronLeftIcon({
+  className,
+  fill = 'currentColor',
+  size = 16
+}: IconProps) {
+  return (
+    <svg
+      className={className}
+      height={size}
+      version="1.1"
+      viewBox="0 0 16 16"
+      width={size}
+      xmlSpace="preserve"
+      xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path
+        d="M4.404 8.28l4.604 4.602a.382.382 0 0 0 .279.118c.108 0 .2-.04.279-.118l1.03-1.03a.382.382 0 0 0 .117-.278.382.382 0 0 0-.117-.28L7.3 8l3.295-3.294a.382.382 0 0 0 .117-.28.382.382 0 0 0-.117-.279l-1.03-1.03A.382.382 0 0 0 9.286 3a.382.382 0 0 0-.278.118L4.404 7.72A.382.382 0 0 0 4.287 8c0 .108.04.201.117.28z"
+        style={{ fill }}
+      />;
+    </svg>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/icons-components/ChevronRightcon.tsx b/server/sonar-web/src/main/js/components/icons-components/ChevronRightcon.tsx
new file mode 100644 (file)
index 0000000..86772ee
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { IconProps } from './types';
+
+export default function ChevronRightIcon({
+  className,
+  fill = 'currentColor',
+  size = 16
+}: IconProps) {
+  return (
+    <svg
+      className={className}
+      height={size}
+      version="1.1"
+      viewBox="0 0 16 16"
+      width={size}
+      xmlSpace="preserve"
+      xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path
+        d="M11.596 8.28l-4.604 4.602a.382.382 0 0 1-.279.118.382.382 0 0 1-.279-.118l-1.03-1.03a.382.382 0 0 1-.117-.278c0-.108.04-.201.117-.28L8.7 8 5.404 4.706a.382.382 0 0 1-.117-.28c0-.108.04-.2.117-.279l1.03-1.03A.382.382 0 0 1 6.714 3c.107 0 .2.04.278.118l4.604 4.603a.382.382 0 0 1 .117.279c0 .108-.04.201-.117.28z"
+        style={{ fill }}
+      />;
+    </svg>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/icons-components/ChevronUpIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/ChevronUpIcon.tsx
new file mode 100644 (file)
index 0000000..e1d105e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { IconProps } from './types';
+
+export default function ChevronUpIcon({ className, fill = 'currentColor', size = 16 }: IconProps) {
+  return (
+    <svg
+      className={className}
+      height={size}
+      version="1.1"
+      viewBox="0 0 16 16"
+      width={size}
+      xmlSpace="preserve"
+      xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path
+        d="M8.28 4.404l4.602 4.604a.382.382 0 0 1 .118.279c0 .108-.04.2-.118.279l-1.03 1.03a.382.382 0 0 1-.278.117.382.382 0 0 1-.28-.117L8 7.3l-3.294 3.295a.382.382 0 0 1-.28.117.382.382 0 0 1-.279-.117l-1.03-1.03A.382.382 0 0 1 3 9.286c0-.107.04-.2.118-.278L7.72 4.404A.382.382 0 0 1 8 4.287c.108 0 .201.04.28.117z"
+        style={{ fill }}
+      />;
+    </svg>
+  );
+}
index 1a8c0c1954bf45593759c307b9b84d508cd03ef8..a42f3285601d68c84d0fc31cc5efcbd72367392f 100644 (file)
  */
 import * as React from 'react';
 import { IconProps } from './types';
+import ChevronDownIcon from './ChevronDownIcon';
+import ChevronRightIcon from './ChevronRightcon';
 
 interface Props extends IconProps {
   open: boolean;
 }
 
-export default function OpenCloseIcon({
-  className,
-  fill = 'currentColor',
-  open,
-  size = 14
-}: Props) {
-  return (
-    <svg
-      className={className}
-      width={size}
-      height={size}
-      viewBox="0 0 16 16"
-      version="1.1"
-      xmlnsXlink="http://www.w3.org/1999/xlink"
-      xmlSpace="preserve">
-      {open ? (
-        <path
-          style={{ fill }}
-          d="M13.506 9.289l-5.191 5.184q-0.133 0.133-0.315 0.133t-0.315-0.133l-5.191-5.184q-0.133-0.133-0.133-0.318t0.133-0.318l1.161-1.154q0.133-0.133 0.315-0.133t0.315 0.133l3.715 3.715 3.715-3.715q0.133-0.133 0.315-0.133t0.315 0.133l1.161 1.154q0.133 0.133 0.133 0.318t-0.133 0.318z"
-        />
-      ) : (
-        <path
-          style={{ fill }}
-          d="M13.527 9.318l-5.244 5.244q-0.134 0.134-0.318 0.134t-0.318-0.134l-1.173-1.173q-0.134-0.134-0.134-0.318t0.134-0.318l3.753-3.753-3.753-3.753q-0.134-0.134-0.134-0.318t0.134-0.318l1.173-1.173q0.134-0.134 0.318-0.134t0.318 0.134l5.244 5.244q0.134 0.134 0.134 0.318t-0.134 0.318z"
-        />
-      )}
-    </svg>
-  );
+export default function OpenCloseIcon({ open, ...props }: Props) {
+  return open ? <ChevronDownIcon {...props} /> : <ChevronRightIcon {...props} />;
 }
index df95089855fa93ecbcb73c946a930e9cfaa15b0f..28ea4d6c93c29ef878d3c2f32d446398ba8d7831 100644 (file)
@@ -186,3 +186,31 @@ export function getCurrentLocale() {
     DEFAULT_LANGUAGE
   );
 }
+
+export function getShortMonthName(index: number) {
+  const months = [
+    'Jan',
+    'Feb',
+    'Mar',
+    'Apr',
+    'May',
+    'Jun',
+    'Jul',
+    'Aug',
+    'Sep',
+    'Oct',
+    'Nov',
+    'Dec'
+  ];
+  return translate(months[index]);
+}
+
+export function getWeekDayName(index: number) {
+  const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+  return weekdays[index] ? translate(weekdays[index]) : '';
+}
+
+export function getShortWeekDayName(index: number) {
+  const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+  return weekdays[index] ? translate(weekdays[index]) : '';
+}
index e495eb7da3a8fa578d6f48b12506b0b0e2fe79d4..5da77512078802badd45f0ba85dbcdb674fe72f8 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { isNil, omitBy } from 'lodash';
+import { isEqual, isNil, omitBy } from 'lodash';
 import { isValidDate, parseDate, toNotSoISOString, toShortNotSoISOString } from './dates';
 
 export interface RawQuery {
   [x: string]: any;
 }
 
-function arraysEqual(a: RawQuery, b: RawQuery): boolean {
-  if (a.length !== b.length) {
-    return false;
-  }
-  for (let i = 0; i < a.length; i++) {
-    if (a[i] !== b[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
 export function queriesEqual(a: RawQuery, b: RawQuery): boolean {
   const keysA = Object.keys(a);
   const keysB = Object.keys(b);
@@ -44,12 +32,7 @@ export function queriesEqual(a: RawQuery, b: RawQuery): boolean {
     return false;
   }
 
-  return keysA.every(
-    key =>
-      Array.isArray(a[key]) && Array.isArray(b[key])
-        ? arraysEqual(a[key], b[key])
-        : a[key] === b[key]
-  );
+  return keysA.every(key => isEqual(a[key], b[key]));
 }
 
 export function cleanQuery(query: RawQuery): RawQuery {
diff --git a/server/sonar-web/src/main/js/libs/third-party/jquery-ui.js b/server/sonar-web/src/main/js/libs/third-party/jquery-ui.js
deleted file mode 100755 (executable)
index b58a90f..0000000
+++ /dev/null
@@ -1,7444 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-/*! jQuery UI - v1.10.4 - 2014-03-31
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.resizable.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.tabs.js
-* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
-
-(function( $, undefined ) {
-
-var uuid = 0,
-       runiqueId = /^ui-id-\d+$/;
-
-// $.ui might exist from components with no dependencies, e.g., $.ui.position
-$.ui = $.ui || {};
-
-$.extend( $.ui, {
-       version: "1.10.4",
-
-       keyCode: {
-               BACKSPACE: 8,
-               COMMA: 188,
-               DELETE: 46,
-               DOWN: 40,
-               END: 35,
-               ENTER: 13,
-               ESCAPE: 27,
-               HOME: 36,
-               LEFT: 37,
-               NUMPAD_ADD: 107,
-               NUMPAD_DECIMAL: 110,
-               NUMPAD_DIVIDE: 111,
-               NUMPAD_ENTER: 108,
-               NUMPAD_MULTIPLY: 106,
-               NUMPAD_SUBTRACT: 109,
-               PAGE_DOWN: 34,
-               PAGE_UP: 33,
-               PERIOD: 190,
-               RIGHT: 39,
-               SPACE: 32,
-               TAB: 9,
-               UP: 38
-       }
-});
-
-// plugins
-$.fn.extend({
-       focus: (function( orig ) {
-               return function( delay, fn ) {
-                       return typeof delay === "number" ?
-                               this.each(function() {
-                                       var elem = this;
-                                       setTimeout(function() {
-                                               $( elem ).focus();
-                                               if ( fn ) {
-                                                       fn.call( elem );
-                                               }
-                                       }, delay );
-                               }) :
-                               orig.apply( this, arguments );
-               };
-       })( $.fn.focus ),
-
-       scrollParent: function() {
-               var scrollParent;
-               if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
-                       scrollParent = this.parents().filter(function() {
-                               return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
-                       }).eq(0);
-               } else {
-                       scrollParent = this.parents().filter(function() {
-                               return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
-                       }).eq(0);
-               }
-
-               return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
-       },
-
-       zIndex: function( zIndex ) {
-               if ( zIndex !== undefined ) {
-                       return this.css( "zIndex", zIndex );
-               }
-
-               if ( this.length ) {
-                       var elem = $( this[ 0 ] ), position, value;
-                       while ( elem.length && elem[ 0 ] !== document ) {
-                               // Ignore z-index if position is set to a value where z-index is ignored by the browser
-                               // This makes behavior of this function consistent across browsers
-                               // WebKit always returns auto if the element is positioned
-                               position = elem.css( "position" );
-                               if ( position === "absolute" || position === "relative" || position === "fixed" ) {
-                                       // IE returns 0 when zIndex is not specified
-                                       // other browsers return a string
-                                       // we ignore the case of nested elements with an explicit value of 0
-                                       // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
-                                       value = parseInt( elem.css( "zIndex" ), 10 );
-                                       if ( !isNaN( value ) && value !== 0 ) {
-                                               return value;
-                                       }
-                               }
-                               elem = elem.parent();
-                       }
-               }
-
-               return 0;
-       },
-
-       uniqueId: function() {
-               return this.each(function() {
-                       if ( !this.id ) {
-                               this.id = "ui-id-" + (++uuid);
-                       }
-               });
-       },
-
-       removeUniqueId: function() {
-               return this.each(function() {
-                       if ( runiqueId.test( this.id ) ) {
-                               $( this ).removeAttr( "id" );
-                       }
-               });
-       }
-});
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
-       var map, mapName, img,
-               nodeName = element.nodeName.toLowerCase();
-       if ( "area" === nodeName ) {
-               map = element.parentNode;
-               mapName = map.name;
-               if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
-                       return false;
-               }
-               img = $( "img[usemap=#" + mapName + "]" )[0];
-               return !!img && visible( img );
-       }
-       return ( /input|select|textarea|button|object/.test( nodeName ) ?
-               !element.disabled :
-               "a" === nodeName ?
-                       element.href || isTabIndexNotNaN :
-                       isTabIndexNotNaN) &&
-               // the element and all of its ancestors must be visible
-               visible( element );
-}
-
-function visible( element ) {
-       return $.expr.filters.visible( element ) &&
-               !$( element ).parents().addBack().filter(function() {
-                       return $.css( this, "visibility" ) === "hidden";
-               }).length;
-}
-
-$.extend( $.expr[ ":" ], {
-       data: $.expr.createPseudo ?
-               $.expr.createPseudo(function( dataName ) {
-                       return function( elem ) {
-                               return !!$.data( elem, dataName );
-                       };
-               }) :
-               // support: jQuery <1.8
-               function( elem, i, match ) {
-                       return !!$.data( elem, match[ 3 ] );
-               },
-
-       focusable: function( element ) {
-               return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
-       },
-
-       tabbable: function( element ) {
-               var tabIndex = $.attr( element, "tabindex" ),
-                       isTabIndexNaN = isNaN( tabIndex );
-               return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
-       }
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
-       $.each( [ "Width", "Height" ], function( i, name ) {
-               var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
-                       type = name.toLowerCase(),
-                       orig = {
-                               innerWidth: $.fn.innerWidth,
-                               innerHeight: $.fn.innerHeight,
-                               outerWidth: $.fn.outerWidth,
-                               outerHeight: $.fn.outerHeight
-                       };
-
-               function reduce( elem, size, border, margin ) {
-                       $.each( side, function() {
-                               size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
-                               if ( border ) {
-                                       size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
-                               }
-                               if ( margin ) {
-                                       size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
-                               }
-                       });
-                       return size;
-               }
-
-               $.fn[ "inner" + name ] = function( size ) {
-                       if ( size === undefined ) {
-                               return orig[ "inner" + name ].call( this );
-                       }
-
-                       return this.each(function() {
-                               $( this ).css( type, reduce( this, size ) + "px" );
-                       });
-               };
-
-               $.fn[ "outer" + name] = function( size, margin ) {
-                       if ( typeof size !== "number" ) {
-                               return orig[ "outer" + name ].call( this, size );
-                       }
-
-                       return this.each(function() {
-                               $( this).css( type, reduce( this, size, true, margin ) + "px" );
-                       });
-               };
-       });
-}
-
-// support: jQuery <1.8
-if ( !$.fn.addBack ) {
-       $.fn.addBack = function( selector ) {
-               return this.add( selector == null ?
-                       this.prevObject : this.prevObject.filter( selector )
-               );
-       };
-}
-
-// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
-if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
-       $.fn.removeData = (function( removeData ) {
-               return function( key ) {
-                       if ( arguments.length ) {
-                               return removeData.call( this, $.camelCase( key ) );
-                       } else {
-                               return removeData.call( this );
-                       }
-               };
-       })( $.fn.removeData );
-}
-
-
-
-
-
-// deprecated
-$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
-
-$.support.selectstart = "onselectstart" in document.createElement( "div" );
-$.fn.extend({
-       disableSelection: function() {
-               return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
-                       ".ui-disableSelection", function( event ) {
-                               event.preventDefault();
-                       });
-       },
-
-       enableSelection: function() {
-               return this.unbind( ".ui-disableSelection" );
-       }
-});
-
-$.extend( $.ui, {
-       // $.ui.plugin is deprecated. Use $.widget() extensions instead.
-       plugin: {
-               add: function( module, option, set ) {
-                       var i,
-                               proto = $.ui[ module ].prototype;
-                       for ( i in set ) {
-                               proto.plugins[ i ] = proto.plugins[ i ] || [];
-                               proto.plugins[ i ].push( [ option, set[ i ] ] );
-                       }
-               },
-               call: function( instance, name, args ) {
-                       var i,
-                               set = instance.plugins[ name ];
-                       if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
-                               return;
-                       }
-
-                       for ( i = 0; i < set.length; i++ ) {
-                               if ( instance.options[ set[ i ][ 0 ] ] ) {
-                                       set[ i ][ 1 ].apply( instance.element, args );
-                               }
-                       }
-               }
-       },
-
-       // only used by resizable
-       hasScroll: function( el, a ) {
-
-               //If overflow is hidden, the element might have extra content, but the user wants to hide it
-               if ( $( el ).css( "overflow" ) === "hidden") {
-                       return false;
-               }
-
-               var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
-                       has = false;
-
-               if ( el[ scroll ] > 0 ) {
-                       return true;
-               }
-
-               // TODO: determine which cases actually cause this to happen
-               // if the element doesn't have the scroll set, see if it's possible to
-               // set the scroll
-               el[ scroll ] = 1;
-               has = ( el[ scroll ] > 0 );
-               el[ scroll ] = 0;
-               return has;
-       }
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-var uuid = 0,
-       slice = Array.prototype.slice,
-       _cleanData = $.cleanData;
-$.cleanData = function( elems ) {
-       for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-               try {
-                       $( elem ).triggerHandler( "remove" );
-               // http://bugs.jquery.com/ticket/8235
-               } catch( e ) {}
-       }
-       _cleanData( elems );
-};
-
-$.widget = function( name, base, prototype ) {
-       var fullName, existingConstructor, constructor, basePrototype,
-               // proxiedPrototype allows the provided prototype to remain unmodified
-               // so that it can be used as a mixin for multiple widgets (#8876)
-               proxiedPrototype = {},
-               namespace = name.split( "." )[ 0 ];
-
-       name = name.split( "." )[ 1 ];
-       fullName = namespace + "-" + name;
-
-       if ( !prototype ) {
-               prototype = base;
-               base = $.Widget;
-       }
-
-       // create selector for plugin
-       $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
-               return !!$.data( elem, fullName );
-       };
-
-       $[ namespace ] = $[ namespace ] || {};
-       existingConstructor = $[ namespace ][ name ];
-       constructor = $[ namespace ][ name ] = function( options, element ) {
-               // allow instantiation without "new" keyword
-               if ( !this._createWidget ) {
-                       return new constructor( options, element );
-               }
-
-               // allow instantiation without initializing for simple inheritance
-               // must use "new" keyword (the code above always passes args)
-               if ( arguments.length ) {
-                       this._createWidget( options, element );
-               }
-       };
-       // extend with the existing constructor to carry over any static properties
-       $.extend( constructor, existingConstructor, {
-               version: prototype.version,
-               // copy the object used to create the prototype in case we need to
-               // redefine the widget later
-               _proto: $.extend( {}, prototype ),
-               // track widgets that inherit from this widget in case this widget is
-               // redefined after a widget inherits from it
-               _childConstructors: []
-       });
-
-       basePrototype = new base();
-       // we need to make the options hash a property directly on the new instance
-       // otherwise we'll modify the options hash on the prototype that we're
-       // inheriting from
-       basePrototype.options = $.widget.extend( {}, basePrototype.options );
-       $.each( prototype, function( prop, value ) {
-               if ( !$.isFunction( value ) ) {
-                       proxiedPrototype[ prop ] = value;
-                       return;
-               }
-               proxiedPrototype[ prop ] = (function() {
-                       var _super = function() {
-                                       return base.prototype[ prop ].apply( this, arguments );
-                               },
-                               _superApply = function( args ) {
-                                       return base.prototype[ prop ].apply( this, args );
-                               };
-                       return function() {
-                               var __super = this._super,
-                                       __superApply = this._superApply,
-                                       returnValue;
-
-                               this._super = _super;
-                               this._superApply = _superApply;
-
-                               returnValue = value.apply( this, arguments );
-
-                               this._super = __super;
-                               this._superApply = __superApply;
-
-                               return returnValue;
-                       };
-               })();
-       });
-       constructor.prototype = $.widget.extend( basePrototype, {
-               // TODO: remove support for widgetEventPrefix
-               // always use the name + a colon as the prefix, e.g., draggable:start
-               // don't prefix for widgets that aren't DOM-based
-               widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
-       }, proxiedPrototype, {
-               constructor: constructor,
-               namespace: namespace,
-               widgetName: name,
-               widgetFullName: fullName
-       });
-
-       // If this widget is being redefined then we need to find all widgets that
-       // are inheriting from it and redefine all of them so that they inherit from
-       // the new version of this widget. We're essentially trying to replace one
-       // level in the prototype chain.
-       if ( existingConstructor ) {
-               $.each( existingConstructor._childConstructors, function( i, child ) {
-                       var childPrototype = child.prototype;
-
-                       // redefine the child widget using the same prototype that was
-                       // originally used, but inherit from the new version of the base
-                       $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
-               });
-               // remove the list of existing child constructors from the old constructor
-               // so the old child constructors can be garbage collected
-               delete existingConstructor._childConstructors;
-       } else {
-               base._childConstructors.push( constructor );
-       }
-
-       $.widget.bridge( name, constructor );
-};
-
-$.widget.extend = function( target ) {
-       var input = slice.call( arguments, 1 ),
-               inputIndex = 0,
-               inputLength = input.length,
-               key,
-               value;
-       for ( ; inputIndex < inputLength; inputIndex++ ) {
-               for ( key in input[ inputIndex ] ) {
-                       value = input[ inputIndex ][ key ];
-                       if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
-                               // Clone objects
-                               if ( $.isPlainObject( value ) ) {
-                                       target[ key ] = $.isPlainObject( target[ key ] ) ?
-                                               $.widget.extend( {}, target[ key ], value ) :
-                                               // Don't extend strings, arrays, etc. with objects
-                                               $.widget.extend( {}, value );
-                               // Copy everything else by reference
-                               } else {
-                                       target[ key ] = value;
-                               }
-                       }
-               }
-       }
-       return target;
-};
-
-$.widget.bridge = function( name, object ) {
-       var fullName = object.prototype.widgetFullName || name;
-       $.fn[ name ] = function( options ) {
-               var isMethodCall = typeof options === "string",
-                       args = slice.call( arguments, 1 ),
-                       returnValue = this;
-
-               // allow multiple hashes to be passed on start
-               options = !isMethodCall && args.length ?
-                       $.widget.extend.apply( null, [ options ].concat(args) ) :
-                       options;
-
-               if ( isMethodCall ) {
-                       this.each(function() {
-                               var methodValue,
-                                       instance = $.data( this, fullName );
-                               if ( !instance ) {
-                                       return $.error( "cannot call methods on " + name + " prior to initialization; " +
-                                               "attempted to call method '" + options + "'" );
-                               }
-                               if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
-                                       return $.error( "no such method '" + options + "' for " + name + " widget instance" );
-                               }
-                               methodValue = instance[ options ].apply( instance, args );
-                               if ( methodValue !== instance && methodValue !== undefined ) {
-                                       returnValue = methodValue && methodValue.jquery ?
-                                               returnValue.pushStack( methodValue.get() ) :
-                                               methodValue;
-                                       return false;
-                               }
-                       });
-               } else {
-                       this.each(function() {
-                               var instance = $.data( this, fullName );
-                               if ( instance ) {
-                                       instance.option( options || {} )._init();
-                               } else {
-                                       $.data( this, fullName, new object( options, this ) );
-                               }
-                       });
-               }
-
-               return returnValue;
-       };
-};
-
-$.Widget = function( /* options, element */ ) {};
-$.Widget._childConstructors = [];
-
-$.Widget.prototype = {
-       widgetName: "widget",
-       widgetEventPrefix: "",
-       defaultElement: "<div>",
-       options: {
-               disabled: false,
-
-               // callbacks
-               create: null
-       },
-       _createWidget: function( options, element ) {
-               element = $( element || this.defaultElement || this )[ 0 ];
-               this.element = $( element );
-               this.uuid = uuid++;
-               this.eventNamespace = "." + this.widgetName + this.uuid;
-               this.options = $.widget.extend( {},
-                       this.options,
-                       this._getCreateOptions(),
-                       options );
-
-               this.bindings = $();
-               this.hoverable = $();
-               this.focusable = $();
-
-               if ( element !== this ) {
-                       $.data( element, this.widgetFullName, this );
-                       this._on( true, this.element, {
-                               remove: function( event ) {
-                                       if ( event.target === element ) {
-                                               this.destroy();
-                                       }
-                               }
-                       });
-                       this.document = $( element.style ?
-                               // element within the document
-                               element.ownerDocument :
-                               // element is window or document
-                               element.document || element );
-                       this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
-               }
-
-               this._create();
-               this._trigger( "create", null, this._getCreateEventData() );
-               this._init();
-       },
-       _getCreateOptions: $.noop,
-       _getCreateEventData: $.noop,
-       _create: $.noop,
-       _init: $.noop,
-
-       destroy: function() {
-               this._destroy();
-               // we can probably remove the unbind calls in 2.0
-               // all event bindings should go through this._on()
-               this.element
-                       .unbind( this.eventNamespace )
-                       // 1.9 BC for #7810
-                       // TODO remove dual storage
-                       .removeData( this.widgetName )
-                       .removeData( this.widgetFullName )
-                       // support: jquery <1.6.3
-                       // http://bugs.jquery.com/ticket/9413
-                       .removeData( $.camelCase( this.widgetFullName ) );
-               this.widget()
-                       .unbind( this.eventNamespace )
-                       .removeAttr( "aria-disabled" )
-                       .removeClass(
-                               this.widgetFullName + "-disabled " +
-                               "ui-state-disabled" );
-
-               // clean up events and states
-               this.bindings.unbind( this.eventNamespace );
-               this.hoverable.removeClass( "ui-state-hover" );
-               this.focusable.removeClass( "ui-state-focus" );
-       },
-       _destroy: $.noop,
-
-       widget: function() {
-               return this.element;
-       },
-
-       option: function( key, value ) {
-               var options = key,
-                       parts,
-                       curOption,
-                       i;
-
-               if ( arguments.length === 0 ) {
-                       // don't return a reference to the internal hash
-                       return $.widget.extend( {}, this.options );
-               }
-
-               if ( typeof key === "string" ) {
-                       // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
-                       options = {};
-                       parts = key.split( "." );
-                       key = parts.shift();
-                       if ( parts.length ) {
-                               curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
-                               for ( i = 0; i < parts.length - 1; i++ ) {
-                                       curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
-                                       curOption = curOption[ parts[ i ] ];
-                               }
-                               key = parts.pop();
-                               if ( arguments.length === 1 ) {
-                                       return curOption[ key ] === undefined ? null : curOption[ key ];
-                               }
-                               curOption[ key ] = value;
-                       } else {
-                               if ( arguments.length === 1 ) {
-                                       return this.options[ key ] === undefined ? null : this.options[ key ];
-                               }
-                               options[ key ] = value;
-                       }
-               }
-
-               this._setOptions( options );
-
-               return this;
-       },
-       _setOptions: function( options ) {
-               var key;
-
-               for ( key in options ) {
-                       this._setOption( key, options[ key ] );
-               }
-
-               return this;
-       },
-       _setOption: function( key, value ) {
-               this.options[ key ] = value;
-
-               if ( key === "disabled" ) {
-                       this.widget()
-                               .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
-                               .attr( "aria-disabled", value );
-                       this.hoverable.removeClass( "ui-state-hover" );
-                       this.focusable.removeClass( "ui-state-focus" );
-               }
-
-               return this;
-       },
-
-       enable: function() {
-               return this._setOption( "disabled", false );
-       },
-       disable: function() {
-               return this._setOption( "disabled", true );
-       },
-
-       _on: function( suppressDisabledCheck, element, handlers ) {
-               var delegateElement,
-                       instance = this;
-
-               // no suppressDisabledCheck flag, shuffle arguments
-               if ( typeof suppressDisabledCheck !== "boolean" ) {
-                       handlers = element;
-                       element = suppressDisabledCheck;
-                       suppressDisabledCheck = false;
-               }
-
-               // no element argument, shuffle and use this.element
-               if ( !handlers ) {
-                       handlers = element;
-                       element = this.element;
-                       delegateElement = this.widget();
-               } else {
-                       // accept selectors, DOM elements
-                       element = delegateElement = $( element );
-                       this.bindings = this.bindings.add( element );
-               }
-
-               $.each( handlers, function( event, handler ) {
-                       function handlerProxy() {
-                               // allow widgets to customize the disabled handling
-                               // - disabled as an array instead of boolean
-                               // - disabled class as method for disabling individual parts
-                               if ( !suppressDisabledCheck &&
-                                               ( instance.options.disabled === true ||
-                                                       $( this ).hasClass( "ui-state-disabled" ) ) ) {
-                                       return;
-                               }
-                               return ( typeof handler === "string" ? instance[ handler ] : handler )
-                                       .apply( instance, arguments );
-                       }
-
-                       // copy the guid so direct unbinding works
-                       if ( typeof handler !== "string" ) {
-                               handlerProxy.guid = handler.guid =
-                                       handler.guid || handlerProxy.guid || $.guid++;
-                       }
-
-                       var match = event.match( /^(\w+)\s*(.*)$/ ),
-                               eventName = match[1] + instance.eventNamespace,
-                               selector = match[2];
-                       if ( selector ) {
-                               delegateElement.delegate( selector, eventName, handlerProxy );
-                       } else {
-                               element.bind( eventName, handlerProxy );
-                       }
-               });
-       },
-
-       _off: function( element, eventName ) {
-               eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
-               element.unbind( eventName ).undelegate( eventName );
-       },
-
-       _delay: function( handler, delay ) {
-               function handlerProxy() {
-                       return ( typeof handler === "string" ? instance[ handler ] : handler )
-                               .apply( instance, arguments );
-               }
-               var instance = this;
-               return setTimeout( handlerProxy, delay || 0 );
-       },
-
-       _hoverable: function( element ) {
-               this.hoverable = this.hoverable.add( element );
-               this._on( element, {
-                       mouseenter: function( event ) {
-                               $( event.currentTarget ).addClass( "ui-state-hover" );
-                       },
-                       mouseleave: function( event ) {
-                               $( event.currentTarget ).removeClass( "ui-state-hover" );
-                       }
-               });
-       },
-
-       _focusable: function( element ) {
-               this.focusable = this.focusable.add( element );
-               this._on( element, {
-                       focusin: function( event ) {
-                               $( event.currentTarget ).addClass( "ui-state-focus" );
-                       },
-                       focusout: function( event ) {
-                               $( event.currentTarget ).removeClass( "ui-state-focus" );
-                       }
-               });
-       },
-
-       _trigger: function( type, event, data ) {
-               var prop, orig,
-                       callback = this.options[ type ];
-
-               data = data || {};
-               event = $.Event( event );
-               event.type = ( type === this.widgetEventPrefix ?
-                       type :
-                       this.widgetEventPrefix + type ).toLowerCase();
-               // the original event may come from any element
-               // so we need to reset the target on the new event
-               event.target = this.element[ 0 ];
-
-               // copy original event properties over to the new event
-               orig = event.originalEvent;
-               if ( orig ) {
-                       for ( prop in orig ) {
-                               if ( !( prop in event ) ) {
-                                       event[ prop ] = orig[ prop ];
-                               }
-                       }
-               }
-
-               this.element.trigger( event, data );
-               return !( $.isFunction( callback ) &&
-                       callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
-                       event.isDefaultPrevented() );
-       }
-};
-
-$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
-       $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
-               if ( typeof options === "string" ) {
-                       options = { effect: options };
-               }
-               var hasOptions,
-                       effectName = !options ?
-                               method :
-                               options === true || typeof options === "number" ?
-                                       defaultEffect :
-                                       options.effect || defaultEffect;
-               options = options || {};
-               if ( typeof options === "number" ) {
-                       options = { duration: options };
-               }
-               hasOptions = !$.isEmptyObject( options );
-               options.complete = callback;
-               if ( options.delay ) {
-                       element.delay( options.delay );
-               }
-               if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
-                       element[ method ]( options );
-               } else if ( effectName !== method && element[ effectName ] ) {
-                       element[ effectName ]( options.duration, options.easing, callback );
-               } else {
-                       element.queue(function( next ) {
-                               $( this )[ method ]();
-                               if ( callback ) {
-                                       callback.call( element[ 0 ] );
-                               }
-                               next();
-                       });
-               }
-       };
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-var mouseHandled = false;
-$( document ).mouseup( function() {
-       mouseHandled = false;
-});
-
-$.widget("ui.mouse", {
-       version: "1.10.4",
-       options: {
-               cancel: "input,textarea,button,select,option",
-               distance: 1,
-               delay: 0
-       },
-       _mouseInit: function() {
-               var that = this;
-
-               this.element
-                       .bind("mousedown."+this.widgetName, function(event) {
-                               return that._mouseDown(event);
-                       })
-                       .bind("click."+this.widgetName, function(event) {
-                               if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
-                                       $.removeData(event.target, that.widgetName + ".preventClickEvent");
-                                       event.stopImmediatePropagation();
-                                       return false;
-                               }
-                       });
-
-               this.started = false;
-       },
-
-       // TODO: make sure destroying one instance of mouse doesn't mess with
-       // other instances of mouse
-       _mouseDestroy: function() {
-               this.element.unbind("."+this.widgetName);
-               if ( this._mouseMoveDelegate ) {
-                       $(document)
-                               .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
-                               .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
-               }
-       },
-
-       _mouseDown: function(event) {
-               // don't let more than one widget handle mouseStart
-               if( mouseHandled ) { return; }
-
-               // we may have missed mouseup (out of window)
-               (this._mouseStarted && this._mouseUp(event));
-
-               this._mouseDownEvent = event;
-
-               var that = this,
-                       btnIsLeft = (event.which === 1),
-                       // event.target.nodeName works around a bug in IE 8 with
-                       // disabled inputs (#7620)
-                       elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
-               if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
-                       return true;
-               }
-
-               this.mouseDelayMet = !this.options.delay;
-               if (!this.mouseDelayMet) {
-                       this._mouseDelayTimer = setTimeout(function() {
-                               that.mouseDelayMet = true;
-                       }, this.options.delay);
-               }
-
-               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-                       this._mouseStarted = (this._mouseStart(event) !== false);
-                       if (!this._mouseStarted) {
-                               event.preventDefault();
-                               return true;
-                       }
-               }
-
-               // Click event may never have fired (Gecko & Opera)
-               if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
-                       $.removeData(event.target, this.widgetName + ".preventClickEvent");
-               }
-
-               // these delegates are required to keep context
-               this._mouseMoveDelegate = function(event) {
-                       return that._mouseMove(event);
-               };
-               this._mouseUpDelegate = function(event) {
-                       return that._mouseUp(event);
-               };
-               $(document)
-                       .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
-                       .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
-
-               event.preventDefault();
-
-               mouseHandled = true;
-               return true;
-       },
-
-       _mouseMove: function(event) {
-               // IE mouseup check - mouseup happened when mouse was out of window
-               if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
-                       return this._mouseUp(event);
-               }
-
-               if (this._mouseStarted) {
-                       this._mouseDrag(event);
-                       return event.preventDefault();
-               }
-
-               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-                       this._mouseStarted =
-                               (this._mouseStart(this._mouseDownEvent, event) !== false);
-                       (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
-               }
-
-               return !this._mouseStarted;
-       },
-
-       _mouseUp: function(event) {
-               $(document)
-                       .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
-                       .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
-
-               if (this._mouseStarted) {
-                       this._mouseStarted = false;
-
-                       if (event.target === this._mouseDownEvent.target) {
-                               $.data(event.target, this.widgetName + ".preventClickEvent", true);
-                       }
-
-                       this._mouseStop(event);
-               }
-
-               return false;
-       },
-
-       _mouseDistanceMet: function(event) {
-               return (Math.max(
-                               Math.abs(this._mouseDownEvent.pageX - event.pageX),
-                               Math.abs(this._mouseDownEvent.pageY - event.pageY)
-                       ) >= this.options.distance
-               );
-       },
-
-       _mouseDelayMet: function(/* event */) {
-               return this.mouseDelayMet;
-       },
-
-       // These are placeholder methods, to be overriden by extending plugin
-       _mouseStart: function(/* event */) {},
-       _mouseDrag: function(/* event */) {},
-       _mouseStop: function(/* event */) {},
-       _mouseCapture: function(/* event */) { return true; }
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.ui = $.ui || {};
-
-var cachedScrollbarWidth,
-       max = Math.max,
-       abs = Math.abs,
-       round = Math.round,
-       rhorizontal = /left|center|right/,
-       rvertical = /top|center|bottom/,
-       roffset = /[\+\-]\d+(\.[\d]+)?%?/,
-       rposition = /^\w+/,
-       rpercent = /%$/,
-       _position = $.fn.position;
-
-function getOffsets( offsets, width, height ) {
-       return [
-               parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
-               parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
-       ];
-}
-
-function parseCss( element, property ) {
-       return parseInt( $.css( element, property ), 10 ) || 0;
-}
-
-function getDimensions( elem ) {
-       var raw = elem[0];
-       if ( raw.nodeType === 9 ) {
-               return {
-                       width: elem.width(),
-                       height: elem.height(),
-                       offset: { top: 0, left: 0 }
-               };
-       }
-       if ( $.isWindow( raw ) ) {
-               return {
-                       width: elem.width(),
-                       height: elem.height(),
-                       offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
-               };
-       }
-       if ( raw.preventDefault ) {
-               return {
-                       width: 0,
-                       height: 0,
-                       offset: { top: raw.pageY, left: raw.pageX }
-               };
-       }
-       return {
-               width: elem.outerWidth(),
-               height: elem.outerHeight(),
-               offset: elem.offset()
-       };
-}
-
-$.position = {
-       scrollbarWidth: function() {
-               if ( cachedScrollbarWidth !== undefined ) {
-                       return cachedScrollbarWidth;
-               }
-               var w1, w2,
-                       div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
-                       innerDiv = div.children()[0];
-
-               $( "body" ).append( div );
-               w1 = innerDiv.offsetWidth;
-               div.css( "overflow", "scroll" );
-
-               w2 = innerDiv.offsetWidth;
-
-               if ( w1 === w2 ) {
-                       w2 = div[0].clientWidth;
-               }
-
-               div.remove();
-
-               return (cachedScrollbarWidth = w1 - w2);
-       },
-       getScrollInfo: function( within ) {
-               var overflowX = within.isWindow || within.isDocument ? "" :
-                               within.element.css( "overflow-x" ),
-                       overflowY = within.isWindow || within.isDocument ? "" :
-                               within.element.css( "overflow-y" ),
-                       hasOverflowX = overflowX === "scroll" ||
-                               ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
-                       hasOverflowY = overflowY === "scroll" ||
-                               ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
-               return {
-                       width: hasOverflowY ? $.position.scrollbarWidth() : 0,
-                       height: hasOverflowX ? $.position.scrollbarWidth() : 0
-               };
-       },
-       getWithinInfo: function( element ) {
-               var withinElement = $( element || window ),
-                       isWindow = $.isWindow( withinElement[0] ),
-                       isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
-               return {
-                       element: withinElement,
-                       isWindow: isWindow,
-                       isDocument: isDocument,
-                       offset: withinElement.offset() || { left: 0, top: 0 },
-                       scrollLeft: withinElement.scrollLeft(),
-                       scrollTop: withinElement.scrollTop(),
-                       width: isWindow ? withinElement.width() : withinElement.outerWidth(),
-                       height: isWindow ? withinElement.height() : withinElement.outerHeight()
-               };
-       }
-};
-
-$.fn.position = function( options ) {
-       if ( !options || !options.of ) {
-               return _position.apply( this, arguments );
-       }
-
-       // make a copy, we don't want to modify arguments
-       options = $.extend( {}, options );
-
-       var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
-               target = $( options.of ),
-               within = $.position.getWithinInfo( options.within ),
-               scrollInfo = $.position.getScrollInfo( within ),
-               collision = ( options.collision || "flip" ).split( " " ),
-               offsets = {};
-
-       dimensions = getDimensions( target );
-       if ( target[0].preventDefault ) {
-               // force left top to allow flipping
-               options.at = "left top";
-       }
-       targetWidth = dimensions.width;
-       targetHeight = dimensions.height;
-       targetOffset = dimensions.offset;
-       // clone to reuse original targetOffset later
-       basePosition = $.extend( {}, targetOffset );
-
-       // force my and at to have valid horizontal and vertical positions
-       // if a value is missing or invalid, it will be converted to center
-       $.each( [ "my", "at" ], function() {
-               var pos = ( options[ this ] || "" ).split( " " ),
-                       horizontalOffset,
-                       verticalOffset;
-
-               if ( pos.length === 1) {
-                       pos = rhorizontal.test( pos[ 0 ] ) ?
-                               pos.concat( [ "center" ] ) :
-                               rvertical.test( pos[ 0 ] ) ?
-                                       [ "center" ].concat( pos ) :
-                                       [ "center", "center" ];
-               }
-               pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
-               pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
-
-               // calculate offsets
-               horizontalOffset = roffset.exec( pos[ 0 ] );
-               verticalOffset = roffset.exec( pos[ 1 ] );
-               offsets[ this ] = [
-                       horizontalOffset ? horizontalOffset[ 0 ] : 0,
-                       verticalOffset ? verticalOffset[ 0 ] : 0
-               ];
-
-               // reduce to just the positions without the offsets
-               options[ this ] = [
-                       rposition.exec( pos[ 0 ] )[ 0 ],
-                       rposition.exec( pos[ 1 ] )[ 0 ]
-               ];
-       });
-
-       // normalize collision option
-       if ( collision.length === 1 ) {
-               collision[ 1 ] = collision[ 0 ];
-       }
-
-       if ( options.at[ 0 ] === "right" ) {
-               basePosition.left += targetWidth;
-       } else if ( options.at[ 0 ] === "center" ) {
-               basePosition.left += targetWidth / 2;
-       }
-
-       if ( options.at[ 1 ] === "bottom" ) {
-               basePosition.top += targetHeight;
-       } else if ( options.at[ 1 ] === "center" ) {
-               basePosition.top += targetHeight / 2;
-       }
-
-       atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
-       basePosition.left += atOffset[ 0 ];
-       basePosition.top += atOffset[ 1 ];
-
-       return this.each(function() {
-               var collisionPosition, using,
-                       elem = $( this ),
-                       elemWidth = elem.outerWidth(),
-                       elemHeight = elem.outerHeight(),
-                       marginLeft = parseCss( this, "marginLeft" ),
-                       marginTop = parseCss( this, "marginTop" ),
-                       collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
-                       collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
-                       position = $.extend( {}, basePosition ),
-                       myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
-
-               if ( options.my[ 0 ] === "right" ) {
-                       position.left -= elemWidth;
-               } else if ( options.my[ 0 ] === "center" ) {
-                       position.left -= elemWidth / 2;
-               }
-
-               if ( options.my[ 1 ] === "bottom" ) {
-                       position.top -= elemHeight;
-               } else if ( options.my[ 1 ] === "center" ) {
-                       position.top -= elemHeight / 2;
-               }
-
-               position.left += myOffset[ 0 ];
-               position.top += myOffset[ 1 ];
-
-               // if the browser doesn't support fractions, then round for consistent results
-               if ( !$.support.offsetFractions ) {
-                       position.left = round( position.left );
-                       position.top = round( position.top );
-               }
-
-               collisionPosition = {
-                       marginLeft: marginLeft,
-                       marginTop: marginTop
-               };
-
-               $.each( [ "left", "top" ], function( i, dir ) {
-                       if ( $.ui.position[ collision[ i ] ] ) {
-                               $.ui.position[ collision[ i ] ][ dir ]( position, {
-                                       targetWidth: targetWidth,
-                                       targetHeight: targetHeight,
-                                       elemWidth: elemWidth,
-                                       elemHeight: elemHeight,
-                                       collisionPosition: collisionPosition,
-                                       collisionWidth: collisionWidth,
-                                       collisionHeight: collisionHeight,
-                                       offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
-                                       my: options.my,
-                                       at: options.at,
-                                       within: within,
-                                       elem : elem
-                               });
-                       }
-               });
-
-               if ( options.using ) {
-                       // adds feedback as second argument to using callback, if present
-                       using = function( props ) {
-                               var left = targetOffset.left - position.left,
-                                       right = left + targetWidth - elemWidth,
-                                       top = targetOffset.top - position.top,
-                                       bottom = top + targetHeight - elemHeight,
-                                       feedback = {
-                                               target: {
-                                                       element: target,
-                                                       left: targetOffset.left,
-                                                       top: targetOffset.top,
-                                                       width: targetWidth,
-                                                       height: targetHeight
-                                               },
-                                               element: {
-                                                       element: elem,
-                                                       left: position.left,
-                                                       top: position.top,
-                                                       width: elemWidth,
-                                                       height: elemHeight
-                                               },
-                                               horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
-                                               vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
-                                       };
-                               if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
-                                       feedback.horizontal = "center";
-                               }
-                               if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
-                                       feedback.vertical = "middle";
-                               }
-                               if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
-                                       feedback.important = "horizontal";
-                               } else {
-                                       feedback.important = "vertical";
-                               }
-                               options.using.call( this, props, feedback );
-                       };
-               }
-
-               elem.offset( $.extend( position, { using: using } ) );
-       });
-};
-
-$.ui.position = {
-       fit: {
-               left: function( position, data ) {
-                       var within = data.within,
-                               withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
-                               outerWidth = within.width,
-                               collisionPosLeft = position.left - data.collisionPosition.marginLeft,
-                               overLeft = withinOffset - collisionPosLeft,
-                               overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
-                               newOverRight;
-
-                       // element is wider than within
-                       if ( data.collisionWidth > outerWidth ) {
-                               // element is initially over the left side of within
-                               if ( overLeft > 0 && overRight <= 0 ) {
-                                       newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
-                                       position.left += overLeft - newOverRight;
-                               // element is initially over right side of within
-                               } else if ( overRight > 0 && overLeft <= 0 ) {
-                                       position.left = withinOffset;
-                               // element is initially over both left and right sides of within
-                               } else {
-                                       if ( overLeft > overRight ) {
-                                               position.left = withinOffset + outerWidth - data.collisionWidth;
-                                       } else {
-                                               position.left = withinOffset;
-                                       }
-                               }
-                       // too far left -> align with left edge
-                       } else if ( overLeft > 0 ) {
-                               position.left += overLeft;
-                       // too far right -> align with right edge
-                       } else if ( overRight > 0 ) {
-                               position.left -= overRight;
-                       // adjust based on position and margin
-                       } else {
-                               position.left = max( position.left - collisionPosLeft, position.left );
-                       }
-               },
-               top: function( position, data ) {
-                       var within = data.within,
-                               withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
-                               outerHeight = data.within.height,
-                               collisionPosTop = position.top - data.collisionPosition.marginTop,
-                               overTop = withinOffset - collisionPosTop,
-                               overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
-                               newOverBottom;
-
-                       // element is taller than within
-                       if ( data.collisionHeight > outerHeight ) {
-                               // element is initially over the top of within
-                               if ( overTop > 0 && overBottom <= 0 ) {
-                                       newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
-                                       position.top += overTop - newOverBottom;
-                               // element is initially over bottom of within
-                               } else if ( overBottom > 0 && overTop <= 0 ) {
-                                       position.top = withinOffset;
-                               // element is initially over both top and bottom of within
-                               } else {
-                                       if ( overTop > overBottom ) {
-                                               position.top = withinOffset + outerHeight - data.collisionHeight;
-                                       } else {
-                                               position.top = withinOffset;
-                                       }
-                               }
-                       // too far up -> align with top
-                       } else if ( overTop > 0 ) {
-                               position.top += overTop;
-                       // too far down -> align with bottom edge
-                       } else if ( overBottom > 0 ) {
-                               position.top -= overBottom;
-                       // adjust based on position and margin
-                       } else {
-                               position.top = max( position.top - collisionPosTop, position.top );
-                       }
-               }
-       },
-       flip: {
-               left: function( position, data ) {
-                       var within = data.within,
-                               withinOffset = within.offset.left + within.scrollLeft,
-                               outerWidth = within.width,
-                               offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
-                               collisionPosLeft = position.left - data.collisionPosition.marginLeft,
-                               overLeft = collisionPosLeft - offsetLeft,
-                               overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
-                               myOffset = data.my[ 0 ] === "left" ?
-                                       -data.elemWidth :
-                                       data.my[ 0 ] === "right" ?
-                                               data.elemWidth :
-                                               0,
-                               atOffset = data.at[ 0 ] === "left" ?
-                                       data.targetWidth :
-                                       data.at[ 0 ] === "right" ?
-                                               -data.targetWidth :
-                                               0,
-                               offset = -2 * data.offset[ 0 ],
-                               newOverRight,
-                               newOverLeft;
-
-                       if ( overLeft < 0 ) {
-                               newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
-                               if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
-                                       position.left += myOffset + atOffset + offset;
-                               }
-                       }
-                       else if ( overRight > 0 ) {
-                               newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
-                               if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
-                                       position.left += myOffset + atOffset + offset;
-                               }
-                       }
-               },
-               top: function( position, data ) {
-                       var within = data.within,
-                               withinOffset = within.offset.top + within.scrollTop,
-                               outerHeight = within.height,
-                               offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
-                               collisionPosTop = position.top - data.collisionPosition.marginTop,
-                               overTop = collisionPosTop - offsetTop,
-                               overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
-                               top = data.my[ 1 ] === "top",
-                               myOffset = top ?
-                                       -data.elemHeight :
-                                       data.my[ 1 ] === "bottom" ?
-                                               data.elemHeight :
-                                               0,
-                               atOffset = data.at[ 1 ] === "top" ?
-                                       data.targetHeight :
-                                       data.at[ 1 ] === "bottom" ?
-                                               -data.targetHeight :
-                                               0,
-                               offset = -2 * data.offset[ 1 ],
-                               newOverTop,
-                               newOverBottom;
-                       if ( overTop < 0 ) {
-                               newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
-                               if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
-                                       position.top += myOffset + atOffset + offset;
-                               }
-                       }
-                       else if ( overBottom > 0 ) {
-                               newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
-                               if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
-                                       position.top += myOffset + atOffset + offset;
-                               }
-                       }
-               }
-       },
-       flipfit: {
-               left: function() {
-                       $.ui.position.flip.left.apply( this, arguments );
-                       $.ui.position.fit.left.apply( this, arguments );
-               },
-               top: function() {
-                       $.ui.position.flip.top.apply( this, arguments );
-                       $.ui.position.fit.top.apply( this, arguments );
-               }
-       }
-};
-
-// fraction support test
-(function () {
-       var testElement, testElementParent, testElementStyle, offsetLeft, i,
-               body = document.getElementsByTagName( "body" )[ 0 ],
-               div = document.createElement( "div" );
-
-       //Create a "fake body" for testing based on method used in jQuery.support
-       testElement = document.createElement( body ? "div" : "body" );
-       testElementStyle = {
-               visibility: "hidden",
-               width: 0,
-               height: 0,
-               border: 0,
-               margin: 0,
-               background: "none"
-       };
-       if ( body ) {
-               $.extend( testElementStyle, {
-                       position: "absolute",
-                       left: "-1000px",
-                       top: "-1000px"
-               });
-       }
-       for ( i in testElementStyle ) {
-               testElement.style[ i ] = testElementStyle[ i ];
-       }
-       testElement.appendChild( div );
-       testElementParent = body || document.documentElement;
-       testElementParent.insertBefore( testElement, testElementParent.firstChild );
-
-       div.style.cssText = "position: absolute; left: 10.7432222px;";
-
-       offsetLeft = $( div ).offset().left;
-       $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
-
-       testElement.innerHTML = "";
-       testElementParent.removeChild( testElement );
-})();
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-$.widget("ui.draggable", $.ui.mouse, {
-       version: "1.10.4",
-       widgetEventPrefix: "drag",
-       options: {
-               addClasses: true,
-               appendTo: "parent",
-               axis: false,
-               connectToSortable: false,
-               containment: false,
-               cursor: "auto",
-               cursorAt: false,
-               grid: false,
-               handle: false,
-               helper: "original",
-               iframeFix: false,
-               opacity: false,
-               refreshPositions: false,
-               revert: false,
-               revertDuration: 500,
-               scope: "default",
-               scroll: true,
-               scrollSensitivity: 20,
-               scrollSpeed: 20,
-               snap: false,
-               snapMode: "both",
-               snapTolerance: 20,
-               stack: false,
-               zIndex: false,
-
-               // callbacks
-               drag: null,
-               start: null,
-               stop: null
-       },
-       _create: function() {
-
-               if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
-                       this.element[0].style.position = "relative";
-               }
-               if (this.options.addClasses){
-                       this.element.addClass("ui-draggable");
-               }
-               if (this.options.disabled){
-                       this.element.addClass("ui-draggable-disabled");
-               }
-
-               this._mouseInit();
-
-       },
-
-       _destroy: function() {
-               this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
-               this._mouseDestroy();
-       },
-
-       _mouseCapture: function(event) {
-
-               var o = this.options;
-
-               // among others, prevent a drag on a resizable-handle
-               if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
-                       return false;
-               }
-
-               //Quit if we're not on a valid handle
-               this.handle = this._getHandle(event);
-               if (!this.handle) {
-                       return false;
-               }
-
-               $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
-                       $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
-                       .css({
-                               width: this.offsetWidth+"px", height: this.offsetHeight+"px",
-                               position: "absolute", opacity: "0.001", zIndex: 1000
-                       })
-                       .css($(this).offset())
-                       .appendTo("body");
-               });
-
-               return true;
-
-       },
-
-       _mouseStart: function(event) {
-
-               var o = this.options;
-
-               //Create and append the visible helper
-               this.helper = this._createHelper(event);
-
-               this.helper.addClass("ui-draggable-dragging");
-
-               //Cache the helper size
-               this._cacheHelperProportions();
-
-               //If ddmanager is used for droppables, set the global draggable
-               if($.ui.ddmanager) {
-                       $.ui.ddmanager.current = this;
-               }
-
-               /*
-                * - Position generation -
-                * This block generates everything position related - it's the core of draggables.
-                */
-
-               //Cache the margins of the original element
-               this._cacheMargins();
-
-               //Store the helper's css position
-               this.cssPosition = this.helper.css( "position" );
-               this.scrollParent = this.helper.scrollParent();
-               this.offsetParent = this.helper.offsetParent();
-               this.offsetParentCssPosition = this.offsetParent.css( "position" );
-
-               //The element's absolute position on the page minus margins
-               this.offset = this.positionAbs = this.element.offset();
-               this.offset = {
-                       top: this.offset.top - this.margins.top,
-                       left: this.offset.left - this.margins.left
-               };
-
-               //Reset scroll cache
-               this.offset.scroll = false;
-
-               $.extend(this.offset, {
-                       click: { //Where the click happened, relative to the element
-                               left: event.pageX - this.offset.left,
-                               top: event.pageY - this.offset.top
-                       },
-                       parent: this._getParentOffset(),
-                       relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
-               });
-
-               //Generate the original position
-               this.originalPosition = this.position = this._generatePosition(event);
-               this.originalPageX = event.pageX;
-               this.originalPageY = event.pageY;
-
-               //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
-               (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
-
-               //Set a containment if given in the options
-               this._setContainment();
-
-               //Trigger event + callbacks
-               if(this._trigger("start", event) === false) {
-                       this._clear();
-                       return false;
-               }
-
-               //Recache the helper size
-               this._cacheHelperProportions();
-
-               //Prepare the droppable offsets
-               if ($.ui.ddmanager && !o.dropBehaviour) {
-                       $.ui.ddmanager.prepareOffsets(this, event);
-               }
-
-
-               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
-
-               //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
-               if ( $.ui.ddmanager ) {
-                       $.ui.ddmanager.dragStart(this, event);
-               }
-
-               return true;
-       },
-
-       _mouseDrag: function(event, noPropagation) {
-               // reset any necessary cached properties (see #5009)
-               if ( this.offsetParentCssPosition === "fixed" ) {
-                       this.offset.parent = this._getParentOffset();
-               }
-
-               //Compute the helpers position
-               this.position = this._generatePosition(event);
-               this.positionAbs = this._convertPositionTo("absolute");
-
-               //Call plugins and callbacks and use the resulting position if something is returned
-               if (!noPropagation) {
-                       var ui = this._uiHash();
-                       if(this._trigger("drag", event, ui) === false) {
-                               this._mouseUp({});
-                               return false;
-                       }
-                       this.position = ui.position;
-               }
-
-               if(!this.options.axis || this.options.axis !== "y") {
-                       this.helper[0].style.left = this.position.left+"px";
-               }
-               if(!this.options.axis || this.options.axis !== "x") {
-                       this.helper[0].style.top = this.position.top+"px";
-               }
-               if($.ui.ddmanager) {
-                       $.ui.ddmanager.drag(this, event);
-               }
-
-               return false;
-       },
-
-       _mouseStop: function(event) {
-
-               //If we are using droppables, inform the manager about the drop
-               var that = this,
-                       dropped = false;
-               if ($.ui.ddmanager && !this.options.dropBehaviour) {
-                       dropped = $.ui.ddmanager.drop(this, event);
-               }
-
-               //if a drop comes from outside (a sortable)
-               if(this.dropped) {
-                       dropped = this.dropped;
-                       this.dropped = false;
-               }
-
-               //if the original element is no longer in the DOM don't bother to continue (see #8269)
-               if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
-                       return false;
-               }
-
-               if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
-                       $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
-                               if(that._trigger("stop", event) !== false) {
-                                       that._clear();
-                               }
-                       });
-               } else {
-                       if(this._trigger("stop", event) !== false) {
-                               this._clear();
-                       }
-               }
-
-               return false;
-       },
-
-       _mouseUp: function(event) {
-               //Remove frame helpers
-               $("div.ui-draggable-iframeFix").each(function() {
-                       this.parentNode.removeChild(this);
-               });
-
-               //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
-               if( $.ui.ddmanager ) {
-                       $.ui.ddmanager.dragStop(this, event);
-               }
-
-               return $.ui.mouse.prototype._mouseUp.call(this, event);
-       },
-
-       cancel: function() {
-
-               if(this.helper.is(".ui-draggable-dragging")) {
-                       this._mouseUp({});
-               } else {
-                       this._clear();
-               }
-
-               return this;
-
-       },
-
-       _getHandle: function(event) {
-               return this.options.handle ?
-                       !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
-                       true;
-       },
-
-       _createHelper: function(event) {
-
-               var o = this.options,
-                       helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
-
-               if(!helper.parents("body").length) {
-                       helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
-               }
-
-               if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
-                       helper.css("position", "absolute");
-               }
-
-               return helper;
-
-       },
-
-       _adjustOffsetFromHelper: function(obj) {
-               if (typeof obj === "string") {
-                       obj = obj.split(" ");
-               }
-               if ($.isArray(obj)) {
-                       obj = {left: +obj[0], top: +obj[1] || 0};
-               }
-               if ("left" in obj) {
-                       this.offset.click.left = obj.left + this.margins.left;
-               }
-               if ("right" in obj) {
-                       this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
-               }
-               if ("top" in obj) {
-                       this.offset.click.top = obj.top + this.margins.top;
-               }
-               if ("bottom" in obj) {
-                       this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
-               }
-       },
-
-       _getParentOffset: function() {
-
-               //Get the offsetParent and cache its position
-               var po = this.offsetParent.offset();
-
-               // This is a special case where we need to modify a offset calculated on start, since the following happened:
-               // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
-               // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
-               //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-               if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
-                       po.left += this.scrollParent.scrollLeft();
-                       po.top += this.scrollParent.scrollTop();
-               }
-
-               //This needs to be actually done for all browsers, since pageX/pageY includes this information
-               //Ugly IE fix
-               if((this.offsetParent[0] === document.body) ||
-                       (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
-                       po = { top: 0, left: 0 };
-               }
-
-               return {
-                       top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
-                       left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
-               };
-
-       },
-
-       _getRelativeOffset: function() {
-
-               if(this.cssPosition === "relative") {
-                       var p = this.element.position();
-                       return {
-                               top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
-                               left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
-                       };
-               } else {
-                       return { top: 0, left: 0 };
-               }
-
-       },
-
-       _cacheMargins: function() {
-               this.margins = {
-                       left: (parseInt(this.element.css("marginLeft"),10) || 0),
-                       top: (parseInt(this.element.css("marginTop"),10) || 0),
-                       right: (parseInt(this.element.css("marginRight"),10) || 0),
-                       bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
-               };
-       },
-
-       _cacheHelperProportions: function() {
-               this.helperProportions = {
-                       width: this.helper.outerWidth(),
-                       height: this.helper.outerHeight()
-               };
-       },
-
-       _setContainment: function() {
-
-               var over, c, ce,
-                       o = this.options;
-
-               if ( !o.containment ) {
-                       this.containment = null;
-                       return;
-               }
-
-               if ( o.containment === "window" ) {
-                       this.containment = [
-                               $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
-                               $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
-                               $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
-                               $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
-                       ];
-                       return;
-               }
-
-               if ( o.containment === "document") {
-                       this.containment = [
-                               0,
-                               0,
-                               $( document ).width() - this.helperProportions.width - this.margins.left,
-                               ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
-                       ];
-                       return;
-               }
-
-               if ( o.containment.constructor === Array ) {
-                       this.containment = o.containment;
-                       return;
-               }
-
-               if ( o.containment === "parent" ) {
-                       o.containment = this.helper[ 0 ].parentNode;
-               }
-
-               c = $( o.containment );
-               ce = c[ 0 ];
-
-               if( !ce ) {
-                       return;
-               }
-
-               over = c.css( "overflow" ) !== "hidden";
-
-               this.containment = [
-                       ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
-                       ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
-                       ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
-                       ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom
-               ];
-               this.relative_container = c;
-       },
-
-       _convertPositionTo: function(d, pos) {
-
-               if(!pos) {
-                       pos = this.position;
-               }
-
-               var mod = d === "absolute" ? 1 : -1,
-                       scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
-
-               //Cache the scroll
-               if (!this.offset.scroll) {
-                       this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
-               }
-
-               return {
-                       top: (
-                               pos.top +                                                                                                                               // The absolute mouse position
-                               this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
-                               this.offset.parent.top * mod -                                                                          // The offsetParent's offset without borders (offset + border)
-                               ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
-                       ),
-                       left: (
-                               pos.left +                                                                                                                              // The absolute mouse position
-                               this.offset.relative.left * mod +                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
-                               this.offset.parent.left * mod   -                                                                               // The offsetParent's offset without borders (offset + border)
-                               ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
-                       )
-               };
-
-       },
-
-       _generatePosition: function(event) {
-
-               var containment, co, top, left,
-                       o = this.options,
-                       scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
-                       pageX = event.pageX,
-                       pageY = event.pageY;
-
-               //Cache the scroll
-               if (!this.offset.scroll) {
-                       this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
-               }
-
-               /*
-                * - Position constraining -
-                * Constrain the position to a mix of grid, containment.
-                */
-
-               // If we are not dragging yet, we won't check for options
-               if ( this.originalPosition ) {
-                       if ( this.containment ) {
-                               if ( this.relative_container ){
-                                       co = this.relative_container.offset();
-                                       containment = [
-                                               this.containment[ 0 ] + co.left,
-                                               this.containment[ 1 ] + co.top,
-                                               this.containment[ 2 ] + co.left,
-                                               this.containment[ 3 ] + co.top
-                                       ];
-                               }
-                               else {
-                                       containment = this.containment;
-                               }
-
-                               if(event.pageX - this.offset.click.left < containment[0]) {
-                                       pageX = containment[0] + this.offset.click.left;
-                               }
-                               if(event.pageY - this.offset.click.top < containment[1]) {
-                                       pageY = containment[1] + this.offset.click.top;
-                               }
-                               if(event.pageX - this.offset.click.left > containment[2]) {
-                                       pageX = containment[2] + this.offset.click.left;
-                               }
-                               if(event.pageY - this.offset.click.top > containment[3]) {
-                                       pageY = containment[3] + this.offset.click.top;
-                               }
-                       }
-
-                       if(o.grid) {
-                               //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
-                               top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
-                               pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
-
-                               left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
-                               pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
-                       }
-
-               }
-
-               return {
-                       top: (
-                               pageY -                                                                                                                                 // The absolute mouse position
-                               this.offset.click.top   -                                                                                               // Click offset (relative to the element)
-                               this.offset.relative.top -                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
-                               this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
-                               ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
-                       ),
-                       left: (
-                               pageX -                                                                                                                                 // The absolute mouse position
-                               this.offset.click.left -                                                                                                // Click offset (relative to the element)
-                               this.offset.relative.left -                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
-                               this.offset.parent.left +                                                                                               // The offsetParent's offset without borders (offset + border)
-                               ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
-                       )
-               };
-
-       },
-
-       _clear: function() {
-               this.helper.removeClass("ui-draggable-dragging");
-               if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
-                       this.helper.remove();
-               }
-               this.helper = null;
-               this.cancelHelperRemoval = false;
-       },
-
-       // From now on bulk stuff - mainly helpers
-
-       _trigger: function(type, event, ui) {
-               ui = ui || this._uiHash();
-               $.ui.plugin.call(this, type, [event, ui]);
-               //The absolute position has to be recalculated after plugins
-               if(type === "drag") {
-                       this.positionAbs = this._convertPositionTo("absolute");
-               }
-               return $.Widget.prototype._trigger.call(this, type, event, ui);
-       },
-
-       plugins: {},
-
-       _uiHash: function() {
-               return {
-                       helper: this.helper,
-                       position: this.position,
-                       originalPosition: this.originalPosition,
-                       offset: this.positionAbs
-               };
-       }
-
-});
-
-$.ui.plugin.add("draggable", "connectToSortable", {
-       start: function(event, ui) {
-
-               var inst = $(this).data("ui-draggable"), o = inst.options,
-                       uiSortable = $.extend({}, ui, { item: inst.element });
-               inst.sortables = [];
-               $(o.connectToSortable).each(function() {
-                       var sortable = $.data(this, "ui-sortable");
-                       if (sortable && !sortable.options.disabled) {
-                               inst.sortables.push({
-                                       instance: sortable,
-                                       shouldRevert: sortable.options.revert
-                               });
-                               sortable.refreshPositions();    // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
-                               sortable._trigger("activate", event, uiSortable);
-                       }
-               });
-
-       },
-       stop: function(event, ui) {
-
-               //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
-               var inst = $(this).data("ui-draggable"),
-                       uiSortable = $.extend({}, ui, { item: inst.element });
-
-               $.each(inst.sortables, function() {
-                       if(this.instance.isOver) {
-
-                               this.instance.isOver = 0;
-
-                               inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
-                               this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
-
-                               //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
-                               if(this.shouldRevert) {
-                                       this.instance.options.revert = this.shouldRevert;
-                               }
-
-                               //Trigger the stop of the sortable
-                               this.instance._mouseStop(event);
-
-                               this.instance.options.helper = this.instance.options._helper;
-
-                               //If the helper has been the original item, restore properties in the sortable
-                               if(inst.options.helper === "original") {
-                                       this.instance.currentItem.css({ top: "auto", left: "auto" });
-                               }
-
-                       } else {
-                               this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
-                               this.instance._trigger("deactivate", event, uiSortable);
-                       }
-
-               });
-
-       },
-       drag: function(event, ui) {
-
-               var inst = $(this).data("ui-draggable"), that = this;
-
-               $.each(inst.sortables, function() {
-
-                       var innermostIntersecting = false,
-                               thisSortable = this;
-
-                       //Copy over some variables to allow calling the sortable's native _intersectsWith
-                       this.instance.positionAbs = inst.positionAbs;
-                       this.instance.helperProportions = inst.helperProportions;
-                       this.instance.offset.click = inst.offset.click;
-
-                       if(this.instance._intersectsWith(this.instance.containerCache)) {
-                               innermostIntersecting = true;
-                               $.each(inst.sortables, function () {
-                                       this.instance.positionAbs = inst.positionAbs;
-                                       this.instance.helperProportions = inst.helperProportions;
-                                       this.instance.offset.click = inst.offset.click;
-                                       if (this !== thisSortable &&
-                                               this.instance._intersectsWith(this.instance.containerCache) &&
-                                               $.contains(thisSortable.instance.element[0], this.instance.element[0])
-                                       ) {
-                                               innermostIntersecting = false;
-                                       }
-                                       return innermostIntersecting;
-                               });
-                       }
-
-
-                       if(innermostIntersecting) {
-                               //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
-                               if(!this.instance.isOver) {
-
-                                       this.instance.isOver = 1;
-                                       //Now we fake the start of dragging for the sortable instance,
-                                       //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
-                                       //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
-                                       this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
-                                       this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
-                                       this.instance.options.helper = function() { return ui.helper[0]; };
-
-                                       event.target = this.instance.currentItem[0];
-                                       this.instance._mouseCapture(event, true);
-                                       this.instance._mouseStart(event, true, true);
-
-                                       //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
-                                       this.instance.offset.click.top = inst.offset.click.top;
-                                       this.instance.offset.click.left = inst.offset.click.left;
-                                       this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
-                                       this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
-
-                                       inst._trigger("toSortable", event);
-                                       inst.dropped = this.instance.element; //draggable revert needs that
-                                       //hack so receive/update callbacks work (mostly)
-                                       inst.currentItem = inst.element;
-                                       this.instance.fromOutside = inst;
-
-                               }
-
-                               //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
-                               if(this.instance.currentItem) {
-                                       this.instance._mouseDrag(event);
-                               }
-
-                       } else {
-
-                               //If it doesn't intersect with the sortable, and it intersected before,
-                               //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
-                               if(this.instance.isOver) {
-
-                                       this.instance.isOver = 0;
-                                       this.instance.cancelHelperRemoval = true;
-
-                                       //Prevent reverting on this forced stop
-                                       this.instance.options.revert = false;
-
-                                       // The out event needs to be triggered independently
-                                       this.instance._trigger("out", event, this.instance._uiHash(this.instance));
-
-                                       this.instance._mouseStop(event, true);
-                                       this.instance.options.helper = this.instance.options._helper;
-
-                                       //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
-                                       this.instance.currentItem.remove();
-                                       if(this.instance.placeholder) {
-                                               this.instance.placeholder.remove();
-                                       }
-
-                                       inst._trigger("fromSortable", event);
-                                       inst.dropped = false; //draggable revert needs that
-                               }
-
-                       }
-
-               });
-
-       }
-});
-
-$.ui.plugin.add("draggable", "cursor", {
-       start: function() {
-               var t = $("body"), o = $(this).data("ui-draggable").options;
-               if (t.css("cursor")) {
-                       o._cursor = t.css("cursor");
-               }
-               t.css("cursor", o.cursor);
-       },
-       stop: function() {
-               var o = $(this).data("ui-draggable").options;
-               if (o._cursor) {
-                       $("body").css("cursor", o._cursor);
-               }
-       }
-});
-
-$.ui.plugin.add("draggable", "opacity", {
-       start: function(event, ui) {
-               var t = $(ui.helper), o = $(this).data("ui-draggable").options;
-               if(t.css("opacity")) {
-                       o._opacity = t.css("opacity");
-               }
-               t.css("opacity", o.opacity);
-       },
-       stop: function(event, ui) {
-               var o = $(this).data("ui-draggable").options;
-               if(o._opacity) {
-                       $(ui.helper).css("opacity", o._opacity);
-               }
-       }
-});
-
-$.ui.plugin.add("draggable", "scroll", {
-       start: function() {
-               var i = $(this).data("ui-draggable");
-               if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
-                       i.overflowOffset = i.scrollParent.offset();
-               }
-       },
-       drag: function( event ) {
-
-               var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
-
-               if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
-
-                       if(!o.axis || o.axis !== "x") {
-                               if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
-                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
-                               } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
-                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
-                               }
-                       }
-
-                       if(!o.axis || o.axis !== "y") {
-                               if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
-                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
-                               } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
-                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
-                               }
-                       }
-
-               } else {
-
-                       if(!o.axis || o.axis !== "x") {
-                               if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
-                                       scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-                               } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
-                                       scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-                               }
-                       }
-
-                       if(!o.axis || o.axis !== "y") {
-                               if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-                               } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-                               }
-                       }
-
-               }
-
-               if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
-                       $.ui.ddmanager.prepareOffsets(i, event);
-               }
-
-       }
-});
-
-$.ui.plugin.add("draggable", "snap", {
-       start: function() {
-
-               var i = $(this).data("ui-draggable"),
-                       o = i.options;
-
-               i.snapElements = [];
-
-               $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
-                       var $t = $(this),
-                               $o = $t.offset();
-                       if(this !== i.element[0]) {
-                               i.snapElements.push({
-                                       item: this,
-                                       width: $t.outerWidth(), height: $t.outerHeight(),
-                                       top: $o.top, left: $o.left
-                               });
-                       }
-               });
-
-       },
-       drag: function(event, ui) {
-
-               var ts, bs, ls, rs, l, r, t, b, i, first,
-                       inst = $(this).data("ui-draggable"),
-                       o = inst.options,
-                       d = o.snapTolerance,
-                       x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
-                       y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
-
-               for (i = inst.snapElements.length - 1; i >= 0; i--){
-
-                       l = inst.snapElements[i].left;
-                       r = l + inst.snapElements[i].width;
-                       t = inst.snapElements[i].top;
-                       b = t + inst.snapElements[i].height;
-
-                       if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
-                               if(inst.snapElements[i].snapping) {
-                                       (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-                               }
-                               inst.snapElements[i].snapping = false;
-                               continue;
-                       }
-
-                       if(o.snapMode !== "inner") {
-                               ts = Math.abs(t - y2) <= d;
-                               bs = Math.abs(b - y1) <= d;
-                               ls = Math.abs(l - x2) <= d;
-                               rs = Math.abs(r - x1) <= d;
-                               if(ts) {
-                                       ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-                               }
-                               if(bs) {
-                                       ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
-                               }
-                               if(ls) {
-                                       ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
-                               }
-                               if(rs) {
-                                       ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
-                               }
-                       }
-
-                       first = (ts || bs || ls || rs);
-
-                       if(o.snapMode !== "outer") {
-                               ts = Math.abs(t - y1) <= d;
-                               bs = Math.abs(b - y2) <= d;
-                               ls = Math.abs(l - x1) <= d;
-                               rs = Math.abs(r - x2) <= d;
-                               if(ts) {
-                                       ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
-                               }
-                               if(bs) {
-                                       ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-                               }
-                               if(ls) {
-                                       ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
-                               }
-                               if(rs) {
-                                       ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
-                               }
-                       }
-
-                       if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
-                               (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-                       }
-                       inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
-
-               }
-
-       }
-});
-
-$.ui.plugin.add("draggable", "stack", {
-       start: function() {
-               var min,
-                       o = this.data("ui-draggable").options,
-                       group = $.makeArray($(o.stack)).sort(function(a,b) {
-                               return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
-                       });
-
-               if (!group.length) { return; }
-
-               min = parseInt($(group[0]).css("zIndex"), 10) || 0;
-               $(group).each(function(i) {
-                       $(this).css("zIndex", min + i);
-               });
-               this.css("zIndex", (min + group.length));
-       }
-});
-
-$.ui.plugin.add("draggable", "zIndex", {
-       start: function(event, ui) {
-               var t = $(ui.helper), o = $(this).data("ui-draggable").options;
-               if(t.css("zIndex")) {
-                       o._zIndex = t.css("zIndex");
-               }
-               t.css("zIndex", o.zIndex);
-       },
-       stop: function(event, ui) {
-               var o = $(this).data("ui-draggable").options;
-               if(o._zIndex) {
-                       $(ui.helper).css("zIndex", o._zIndex);
-               }
-       }
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-function num(v) {
-       return parseInt(v, 10) || 0;
-}
-
-function isNumber(value) {
-       return !isNaN(parseInt(value, 10));
-}
-
-$.widget("ui.resizable", $.ui.mouse, {
-       version: "1.10.4",
-       widgetEventPrefix: "resize",
-       options: {
-               alsoResize: false,
-               animate: false,
-               animateDuration: "slow",
-               animateEasing: "swing",
-               aspectRatio: false,
-               autoHide: false,
-               containment: false,
-               ghost: false,
-               grid: false,
-               handles: "e,s,se",
-               helper: false,
-               maxHeight: null,
-               maxWidth: null,
-               minHeight: 10,
-               minWidth: 10,
-               // See #7960
-               zIndex: 90,
-
-               // callbacks
-               resize: null,
-               start: null,
-               stop: null
-       },
-       _create: function() {
-
-               var n, i, handle, axis, hname,
-                       that = this,
-                       o = this.options;
-               this.element.addClass("ui-resizable");
-
-               $.extend(this, {
-                       _aspectRatio: !!(o.aspectRatio),
-                       aspectRatio: o.aspectRatio,
-                       originalElement: this.element,
-                       _proportionallyResizeElements: [],
-                       _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
-               });
-
-               //Wrap the element if it cannot hold child nodes
-               if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
-
-                       //Create a wrapper element and set the wrapper to the new current internal element
-                       this.element.wrap(
-                               $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
-                                       position: this.element.css("position"),
-                                       width: this.element.outerWidth(),
-                                       height: this.element.outerHeight(),
-                                       top: this.element.css("top"),
-                                       left: this.element.css("left")
-                               })
-                       );
-
-                       //Overwrite the original this.element
-                       this.element = this.element.parent().data(
-                               "ui-resizable", this.element.data("ui-resizable")
-                       );
-
-                       this.elementIsWrapper = true;
-
-                       //Move margins to the wrapper
-                       this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
-                       this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
-
-                       //Prevent Safari textarea resize
-                       this.originalResizeStyle = this.originalElement.css("resize");
-                       this.originalElement.css("resize", "none");
-
-                       //Push the actual element to our proportionallyResize internal array
-                       this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
-
-                       // avoid IE jump (hard set the margin)
-                       this.originalElement.css({ margin: this.originalElement.css("margin") });
-
-                       // fix handlers offset
-                       this._proportionallyResize();
-
-               }
-
-               this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
-               if(this.handles.constructor === String) {
-
-                       if ( this.handles === "all") {
-                               this.handles = "n,e,s,w,se,sw,ne,nw";
-                       }
-
-                       n = this.handles.split(",");
-                       this.handles = {};
-
-                       for(i = 0; i < n.length; i++) {
-
-                               handle = $.trim(n[i]);
-                               hname = "ui-resizable-"+handle;
-                               axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
-
-                               // Apply zIndex to all handles - see #7960
-                               axis.css({ zIndex: o.zIndex });
-
-                               //TODO : What's going on here?
-                               if ("se" === handle) {
-                                       axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
-                               }
-
-                               //Insert into internal handles object and append to element
-                               this.handles[handle] = ".ui-resizable-"+handle;
-                               this.element.append(axis);
-                       }
-
-               }
-
-               this._renderAxis = function(target) {
-
-                       var i, axis, padPos, padWrapper;
-
-                       target = target || this.element;
-
-                       for(i in this.handles) {
-
-                               if(this.handles[i].constructor === String) {
-                                       this.handles[i] = $(this.handles[i], this.element).show();
-                               }
-
-                               //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
-                               if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
-
-                                       axis = $(this.handles[i], this.element);
-
-                                       //Checking the correct pad and border
-                                       padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
-
-                                       //The padding type i have to apply...
-                                       padPos = [ "padding",
-                                               /ne|nw|n/.test(i) ? "Top" :
-                                               /se|sw|s/.test(i) ? "Bottom" :
-                                               /^e$/.test(i) ? "Right" : "Left" ].join("");
-
-                                       target.css(padPos, padWrapper);
-
-                                       this._proportionallyResize();
-
-                               }
-
-                               //TODO: What's that good for? There's not anything to be executed left
-                               if(!$(this.handles[i]).length) {
-                                       continue;
-                               }
-                       }
-               };
-
-               //TODO: make renderAxis a prototype function
-               this._renderAxis(this.element);
-
-               this._handles = $(".ui-resizable-handle", this.element)
-                       .disableSelection();
-
-               //Matching axis name
-               this._handles.mouseover(function() {
-                       if (!that.resizing) {
-                               if (this.className) {
-                                       axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
-                               }
-                               //Axis, default = se
-                               that.axis = axis && axis[1] ? axis[1] : "se";
-                       }
-               });
-
-               //If we want to auto hide the elements
-               if (o.autoHide) {
-                       this._handles.hide();
-                       $(this.element)
-                               .addClass("ui-resizable-autohide")
-                               .mouseenter(function() {
-                                       if (o.disabled) {
-                                               return;
-                                       }
-                                       $(this).removeClass("ui-resizable-autohide");
-                                       that._handles.show();
-                               })
-                               .mouseleave(function(){
-                                       if (o.disabled) {
-                                               return;
-                                       }
-                                       if (!that.resizing) {
-                                               $(this).addClass("ui-resizable-autohide");
-                                               that._handles.hide();
-                                       }
-                               });
-               }
-
-               //Initialize the mouse interaction
-               this._mouseInit();
-
-       },
-
-       _destroy: function() {
-
-               this._mouseDestroy();
-
-               var wrapper,
-                       _destroy = function(exp) {
-                               $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
-                                       .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
-                       };
-
-               //TODO: Unwrap at same DOM position
-               if (this.elementIsWrapper) {
-                       _destroy(this.element);
-                       wrapper = this.element;
-                       this.originalElement.css({
-                               position: wrapper.css("position"),
-                               width: wrapper.outerWidth(),
-                               height: wrapper.outerHeight(),
-                               top: wrapper.css("top"),
-                               left: wrapper.css("left")
-                       }).insertAfter( wrapper );
-                       wrapper.remove();
-               }
-
-               this.originalElement.css("resize", this.originalResizeStyle);
-               _destroy(this.originalElement);
-
-               return this;
-       },
-
-       _mouseCapture: function(event) {
-               var i, handle,
-                       capture = false;
-
-               for (i in this.handles) {
-                       handle = $(this.handles[i])[0];
-                       if (handle === event.target || $.contains(handle, event.target)) {
-                               capture = true;
-                       }
-               }
-
-               return !this.options.disabled && capture;
-       },
-
-       _mouseStart: function(event) {
-
-               var curleft, curtop, cursor,
-                       o = this.options,
-                       iniPos = this.element.position(),
-                       el = this.element;
-
-               this.resizing = true;
-
-               // bugfix for http://dev.jquery.com/ticket/1749
-               if ( (/absolute/).test( el.css("position") ) ) {
-                       el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
-               } else if (el.is(".ui-draggable")) {
-                       el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
-               }
-
-               this._renderProxy();
-
-               curleft = num(this.helper.css("left"));
-               curtop = num(this.helper.css("top"));
-
-               if (o.containment) {
-                       curleft += $(o.containment).scrollLeft() || 0;
-                       curtop += $(o.containment).scrollTop() || 0;
-               }
-
-               //Store needed variables
-               this.offset = this.helper.offset();
-               this.position = { left: curleft, top: curtop };
-               this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() };
-               this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-               this.originalPosition = { left: curleft, top: curtop };
-               this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
-               this.originalMousePosition = { left: event.pageX, top: event.pageY };
-
-               //Aspect Ratio
-               this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
-
-               cursor = $(".ui-resizable-" + this.axis).css("cursor");
-               $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
-
-               el.addClass("ui-resizable-resizing");
-               this._propagate("start", event);
-               return true;
-       },
-
-       _mouseDrag: function(event) {
-
-               //Increase performance, avoid regex
-               var data,
-                       el = this.helper, props = {},
-                       smp = this.originalMousePosition,
-                       a = this.axis,
-                       prevTop = this.position.top,
-                       prevLeft = this.position.left,
-                       prevWidth = this.size.width,
-                       prevHeight = this.size.height,
-                       dx = (event.pageX-smp.left)||0,
-                       dy = (event.pageY-smp.top)||0,
-                       trigger = this._change[a];
-
-               if (!trigger) {
-                       return false;
-               }
-
-               // Calculate the attrs that will be change
-               data = trigger.apply(this, [event, dx, dy]);
-
-               // Put this in the mouseDrag handler since the user can start pressing shift while resizing
-               this._updateVirtualBoundaries(event.shiftKey);
-               if (this._aspectRatio || event.shiftKey) {
-                       data = this._updateRatio(data, event);
-               }
-
-               data = this._respectSize(data, event);
-
-               this._updateCache(data);
-
-               // plugins callbacks need to be called first
-               this._propagate("resize", event);
-
-               if (this.position.top !== prevTop) {
-                       props.top = this.position.top + "px";
-               }
-               if (this.position.left !== prevLeft) {
-                       props.left = this.position.left + "px";
-               }
-               if (this.size.width !== prevWidth) {
-                       props.width = this.size.width + "px";
-               }
-               if (this.size.height !== prevHeight) {
-                       props.height = this.size.height + "px";
-               }
-               el.css(props);
-
-               if (!this._helper && this._proportionallyResizeElements.length) {
-                       this._proportionallyResize();
-               }
-
-               // Call the user callback if the element was resized
-               if ( ! $.isEmptyObject(props) ) {
-                       this._trigger("resize", event, this.ui());
-               }
-
-               return false;
-       },
-
-       _mouseStop: function(event) {
-
-               this.resizing = false;
-               var pr, ista, soffseth, soffsetw, s, left, top,
-                       o = this.options, that = this;
-
-               if(this._helper) {
-
-                       pr = this._proportionallyResizeElements;
-                       ista = pr.length && (/textarea/i).test(pr[0].nodeName);
-                       soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
-                       soffsetw = ista ? 0 : that.sizeDiff.width;
-
-                       s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
-                       left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
-                       top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
-
-                       if (!o.animate) {
-                               this.element.css($.extend(s, { top: top, left: left }));
-                       }
-
-                       that.helper.height(that.size.height);
-                       that.helper.width(that.size.width);
-
-                       if (this._helper && !o.animate) {
-                               this._proportionallyResize();
-                       }
-               }
-
-               $("body").css("cursor", "auto");
-
-               this.element.removeClass("ui-resizable-resizing");
-
-               this._propagate("stop", event);
-
-               if (this._helper) {
-                       this.helper.remove();
-               }
-
-               return false;
-
-       },
-
-       _updateVirtualBoundaries: function(forceAspectRatio) {
-               var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
-                       o = this.options;
-
-               b = {
-                       minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
-                       maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
-                       minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
-                       maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
-               };
-
-               if(this._aspectRatio || forceAspectRatio) {
-                       // We want to create an enclosing box whose aspect ration is the requested one
-                       // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
-                       pMinWidth = b.minHeight * this.aspectRatio;
-                       pMinHeight = b.minWidth / this.aspectRatio;
-                       pMaxWidth = b.maxHeight * this.aspectRatio;
-                       pMaxHeight = b.maxWidth / this.aspectRatio;
-
-                       if(pMinWidth > b.minWidth) {
-                               b.minWidth = pMinWidth;
-                       }
-                       if(pMinHeight > b.minHeight) {
-                               b.minHeight = pMinHeight;
-                       }
-                       if(pMaxWidth < b.maxWidth) {
-                               b.maxWidth = pMaxWidth;
-                       }
-                       if(pMaxHeight < b.maxHeight) {
-                               b.maxHeight = pMaxHeight;
-                       }
-               }
-               this._vBoundaries = b;
-       },
-
-       _updateCache: function(data) {
-               this.offset = this.helper.offset();
-               if (isNumber(data.left)) {
-                       this.position.left = data.left;
-               }
-               if (isNumber(data.top)) {
-                       this.position.top = data.top;
-               }
-               if (isNumber(data.height)) {
-                       this.size.height = data.height;
-               }
-               if (isNumber(data.width)) {
-                       this.size.width = data.width;
-               }
-       },
-
-       _updateRatio: function( data ) {
-
-               var cpos = this.position,
-                       csize = this.size,
-                       a = this.axis;
-
-               if (isNumber(data.height)) {
-                       data.width = (data.height * this.aspectRatio);
-               } else if (isNumber(data.width)) {
-                       data.height = (data.width / this.aspectRatio);
-               }
-
-               if (a === "sw") {
-                       data.left = cpos.left + (csize.width - data.width);
-                       data.top = null;
-               }
-               if (a === "nw") {
-                       data.top = cpos.top + (csize.height - data.height);
-                       data.left = cpos.left + (csize.width - data.width);
-               }
-
-               return data;
-       },
-
-       _respectSize: function( data ) {
-
-               var o = this._vBoundaries,
-                       a = this.axis,
-                       ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
-                       isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
-                       dw = this.originalPosition.left + this.originalSize.width,
-                       dh = this.position.top + this.size.height,
-                       cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
-               if (isminw) {
-                       data.width = o.minWidth;
-               }
-               if (isminh) {
-                       data.height = o.minHeight;
-               }
-               if (ismaxw) {
-                       data.width = o.maxWidth;
-               }
-               if (ismaxh) {
-                       data.height = o.maxHeight;
-               }
-
-               if (isminw && cw) {
-                       data.left = dw - o.minWidth;
-               }
-               if (ismaxw && cw) {
-                       data.left = dw - o.maxWidth;
-               }
-               if (isminh && ch) {
-                       data.top = dh - o.minHeight;
-               }
-               if (ismaxh && ch) {
-                       data.top = dh - o.maxHeight;
-               }
-
-               // fixing jump error on top/left - bug #2330
-               if (!data.width && !data.height && !data.left && data.top) {
-                       data.top = null;
-               } else if (!data.width && !data.height && !data.top && data.left) {
-                       data.left = null;
-               }
-
-               return data;
-       },
-
-       _proportionallyResize: function() {
-
-               if (!this._proportionallyResizeElements.length) {
-                       return;
-               }
-
-               var i, j, borders, paddings, prel,
-                       element = this.helper || this.element;
-
-               for ( i=0; i < this._proportionallyResizeElements.length; i++) {
-
-                       prel = this._proportionallyResizeElements[i];
-
-                       if (!this.borderDif) {
-                               this.borderDif = [];
-                               borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
-                               paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
-
-                               for ( j = 0; j < borders.length; j++ ) {
-                                       this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
-                               }
-                       }
-
-                       prel.css({
-                               height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
-                               width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
-                       });
-
-               }
-
-       },
-
-       _renderProxy: function() {
-
-               var el = this.element, o = this.options;
-               this.elementOffset = el.offset();
-
-               if(this._helper) {
-
-                       this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
-
-                       this.helper.addClass(this._helper).css({
-                               width: this.element.outerWidth() - 1,
-                               height: this.element.outerHeight() - 1,
-                               position: "absolute",
-                               left: this.elementOffset.left +"px",
-                               top: this.elementOffset.top +"px",
-                               zIndex: ++o.zIndex //TODO: Don't modify option
-                       });
-
-                       this.helper
-                               .appendTo("body")
-                               .disableSelection();
-
-               } else {
-                       this.helper = this.element;
-               }
-
-       },
-
-       _change: {
-               e: function(event, dx) {
-                       return { width: this.originalSize.width + dx };
-               },
-               w: function(event, dx) {
-                       var cs = this.originalSize, sp = this.originalPosition;
-                       return { left: sp.left + dx, width: cs.width - dx };
-               },
-               n: function(event, dx, dy) {
-                       var cs = this.originalSize, sp = this.originalPosition;
-                       return { top: sp.top + dy, height: cs.height - dy };
-               },
-               s: function(event, dx, dy) {
-                       return { height: this.originalSize.height + dy };
-               },
-               se: function(event, dx, dy) {
-                       return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-               },
-               sw: function(event, dx, dy) {
-                       return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-               },
-               ne: function(event, dx, dy) {
-                       return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-               },
-               nw: function(event, dx, dy) {
-                       return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-               }
-       },
-
-       _propagate: function(n, event) {
-               $.ui.plugin.call(this, n, [event, this.ui()]);
-               (n !== "resize" && this._trigger(n, event, this.ui()));
-       },
-
-       plugins: {},
-
-       ui: function() {
-               return {
-                       originalElement: this.originalElement,
-                       element: this.element,
-                       helper: this.helper,
-                       position: this.position,
-                       size: this.size,
-                       originalSize: this.originalSize,
-                       originalPosition: this.originalPosition
-               };
-       }
-
-});
-
-/*
- * Resizable Extensions
- */
-
-$.ui.plugin.add("resizable", "animate", {
-
-       stop: function( event ) {
-               var that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       pr = that._proportionallyResizeElements,
-                       ista = pr.length && (/textarea/i).test(pr[0].nodeName),
-                       soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
-                       soffsetw = ista ? 0 : that.sizeDiff.width,
-                       style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
-                       left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
-                       top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
-
-               that.element.animate(
-                       $.extend(style, top && left ? { top: top, left: left } : {}), {
-                               duration: o.animateDuration,
-                               easing: o.animateEasing,
-                               step: function() {
-
-                                       var data = {
-                                               width: parseInt(that.element.css("width"), 10),
-                                               height: parseInt(that.element.css("height"), 10),
-                                               top: parseInt(that.element.css("top"), 10),
-                                               left: parseInt(that.element.css("left"), 10)
-                                       };
-
-                                       if (pr && pr.length) {
-                                               $(pr[0]).css({ width: data.width, height: data.height });
-                                       }
-
-                                       // propagating resize, and updating values for each animation step
-                                       that._updateCache(data);
-                                       that._propagate("resize", event);
-
-                               }
-                       }
-               );
-       }
-
-});
-
-$.ui.plugin.add("resizable", "containment", {
-
-       start: function() {
-               var element, p, co, ch, cw, width, height,
-                       that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       el = that.element,
-                       oc = o.containment,
-                       ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
-
-               if (!ce) {
-                       return;
-               }
-
-               that.containerElement = $(ce);
-
-               if (/document/.test(oc) || oc === document) {
-                       that.containerOffset = { left: 0, top: 0 };
-                       that.containerPosition = { left: 0, top: 0 };
-
-                       that.parentData = {
-                               element: $(document), left: 0, top: 0,
-                               width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
-                       };
-               }
-
-               // i'm a node, so compute top, left, right, bottom
-               else {
-                       element = $(ce);
-                       p = [];
-                       $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
-
-                       that.containerOffset = element.offset();
-                       that.containerPosition = element.position();
-                       that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
-
-                       co = that.containerOffset;
-                       ch = that.containerSize.height;
-                       cw = that.containerSize.width;
-                       width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
-                       height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
-
-                       that.parentData = {
-                               element: ce, left: co.left, top: co.top, width: width, height: height
-                       };
-               }
-       },
-
-       resize: function( event ) {
-               var woset, hoset, isParent, isOffsetRelative,
-                       that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       co = that.containerOffset, cp = that.position,
-                       pRatio = that._aspectRatio || event.shiftKey,
-                       cop = { top:0, left:0 }, ce = that.containerElement;
-
-               if (ce[0] !== document && (/static/).test(ce.css("position"))) {
-                       cop = co;
-               }
-
-               if (cp.left < (that._helper ? co.left : 0)) {
-                       that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
-                       if (pRatio) {
-                               that.size.height = that.size.width / that.aspectRatio;
-                       }
-                       that.position.left = o.helper ? co.left : 0;
-               }
-
-               if (cp.top < (that._helper ? co.top : 0)) {
-                       that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
-                       if (pRatio) {
-                               that.size.width = that.size.height * that.aspectRatio;
-                       }
-                       that.position.top = that._helper ? co.top : 0;
-               }
-
-               that.offset.left = that.parentData.left+that.position.left;
-               that.offset.top = that.parentData.top+that.position.top;
-
-               woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
-               hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
-
-               isParent = that.containerElement.get(0) === that.element.parent().get(0);
-               isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
-
-               if ( isParent && isOffsetRelative ) {
-                       woset -= Math.abs( that.parentData.left );
-               }
-
-               if (woset + that.size.width >= that.parentData.width) {
-                       that.size.width = that.parentData.width - woset;
-                       if (pRatio) {
-                               that.size.height = that.size.width / that.aspectRatio;
-                       }
-               }
-
-               if (hoset + that.size.height >= that.parentData.height) {
-                       that.size.height = that.parentData.height - hoset;
-                       if (pRatio) {
-                               that.size.width = that.size.height * that.aspectRatio;
-                       }
-               }
-       },
-
-       stop: function(){
-               var that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       co = that.containerOffset,
-                       cop = that.containerPosition,
-                       ce = that.containerElement,
-                       helper = $(that.helper),
-                       ho = helper.offset(),
-                       w = helper.outerWidth() - that.sizeDiff.width,
-                       h = helper.outerHeight() - that.sizeDiff.height;
-
-               if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
-                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-               }
-
-               if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
-                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-               }
-
-       }
-});
-
-$.ui.plugin.add("resizable", "alsoResize", {
-
-       start: function () {
-               var that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       _store = function (exp) {
-                               $(exp).each(function() {
-                                       var el = $(this);
-                                       el.data("ui-resizable-alsoresize", {
-                                               width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
-                                               left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
-                                       });
-                               });
-                       };
-
-               if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
-                       if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
-                       else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
-               }else{
-                       _store(o.alsoResize);
-               }
-       },
-
-       resize: function (event, ui) {
-               var that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       os = that.originalSize,
-                       op = that.originalPosition,
-                       delta = {
-                               height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
-                               top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
-                       },
-
-                       _alsoResize = function (exp, c) {
-                               $(exp).each(function() {
-                                       var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
-                                               css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
-
-                                       $.each(css, function (i, prop) {
-                                               var sum = (start[prop]||0) + (delta[prop]||0);
-                                               if (sum && sum >= 0) {
-                                                       style[prop] = sum || null;
-                                               }
-                                       });
-
-                                       el.css(style);
-                               });
-                       };
-
-               if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
-                       $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
-               }else{
-                       _alsoResize(o.alsoResize);
-               }
-       },
-
-       stop: function () {
-               $(this).removeData("resizable-alsoresize");
-       }
-});
-
-$.ui.plugin.add("resizable", "ghost", {
-
-       start: function() {
-
-               var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
-
-               that.ghost = that.originalElement.clone();
-               that.ghost
-                       .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
-                       .addClass("ui-resizable-ghost")
-                       .addClass(typeof o.ghost === "string" ? o.ghost : "");
-
-               that.ghost.appendTo(that.helper);
-
-       },
-
-       resize: function(){
-               var that = $(this).data("ui-resizable");
-               if (that.ghost) {
-                       that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
-               }
-       },
-
-       stop: function() {
-               var that = $(this).data("ui-resizable");
-               if (that.ghost && that.helper) {
-                       that.helper.get(0).removeChild(that.ghost.get(0));
-               }
-       }
-
-});
-
-$.ui.plugin.add("resizable", "grid", {
-
-       resize: function() {
-               var that = $(this).data("ui-resizable"),
-                       o = that.options,
-                       cs = that.size,
-                       os = that.originalSize,
-                       op = that.originalPosition,
-                       a = that.axis,
-                       grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
-                       gridX = (grid[0]||1),
-                       gridY = (grid[1]||1),
-                       ox = Math.round((cs.width - os.width) / gridX) * gridX,
-                       oy = Math.round((cs.height - os.height) / gridY) * gridY,
-                       newWidth = os.width + ox,
-                       newHeight = os.height + oy,
-                       isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
-                       isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
-                       isMinWidth = o.minWidth && (o.minWidth > newWidth),
-                       isMinHeight = o.minHeight && (o.minHeight > newHeight);
-
-               o.grid = grid;
-
-               if (isMinWidth) {
-                       newWidth = newWidth + gridX;
-               }
-               if (isMinHeight) {
-                       newHeight = newHeight + gridY;
-               }
-               if (isMaxWidth) {
-                       newWidth = newWidth - gridX;
-               }
-               if (isMaxHeight) {
-                       newHeight = newHeight - gridY;
-               }
-
-               if (/^(se|s|e)$/.test(a)) {
-                       that.size.width = newWidth;
-                       that.size.height = newHeight;
-               } else if (/^(ne)$/.test(a)) {
-                       that.size.width = newWidth;
-                       that.size.height = newHeight;
-                       that.position.top = op.top - oy;
-               } else if (/^(sw)$/.test(a)) {
-                       that.size.width = newWidth;
-                       that.size.height = newHeight;
-                       that.position.left = op.left - ox;
-               } else {
-                       if ( newHeight - gridY > 0 ) {
-                               that.size.height = newHeight;
-                               that.position.top = op.top - oy;
-                       } else {
-                               that.size.height = gridY;
-                               that.position.top = op.top + os.height - gridY;
-                       }
-                       if ( newWidth - gridX > 0 ) {
-                               that.size.width = newWidth;
-                               that.position.left = op.left - ox;
-                       } else {
-                               that.size.width = gridX;
-                               that.position.left = op.left + os.width - gridX;
-                       }
-               }
-       }
-
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-var lastActive,
-       baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
-       typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
-       formResetHandler = function() {
-               var form = $( this );
-               setTimeout(function() {
-                       form.find( ":ui-button" ).button( "refresh" );
-               }, 1 );
-       },
-       radioGroup = function( radio ) {
-               var name = radio.name,
-                       form = radio.form,
-                       radios = $( [] );
-               if ( name ) {
-                       name = name.replace( /'/g, "\\'" );
-                       if ( form ) {
-                               radios = $( form ).find( "[name='" + name + "']" );
-                       } else {
-                               radios = $( "[name='" + name + "']", radio.ownerDocument )
-                                       .filter(function() {
-                                               return !this.form;
-                                       });
-                       }
-               }
-               return radios;
-       };
-
-$.widget( "ui.button", {
-       version: "1.10.4",
-       defaultElement: "<button>",
-       options: {
-               disabled: null,
-               text: true,
-               label: null,
-               icons: {
-                       primary: null,
-                       secondary: null
-               }
-       },
-       _create: function() {
-               this.element.closest( "form" )
-                       .unbind( "reset" + this.eventNamespace )
-                       .bind( "reset" + this.eventNamespace, formResetHandler );
-
-               if ( typeof this.options.disabled !== "boolean" ) {
-                       this.options.disabled = !!this.element.prop( "disabled" );
-               } else {
-                       this.element.prop( "disabled", this.options.disabled );
-               }
-
-               this._determineButtonType();
-               this.hasTitle = !!this.buttonElement.attr( "title" );
-
-               var that = this,
-                       options = this.options,
-                       toggleButton = this.type === "checkbox" || this.type === "radio",
-                       activeClass = !toggleButton ? "ui-state-active" : "";
-
-               if ( options.label === null ) {
-                       options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
-               }
-
-               this._hoverable( this.buttonElement );
-
-               this.buttonElement
-                       .addClass( baseClasses )
-                       .attr( "role", "button" )
-                       .bind( "mouseenter" + this.eventNamespace, function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               if ( this === lastActive ) {
-                                       $( this ).addClass( "ui-state-active" );
-                               }
-                       })
-                       .bind( "mouseleave" + this.eventNamespace, function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).removeClass( activeClass );
-                       })
-                       .bind( "click" + this.eventNamespace, function( event ) {
-                               if ( options.disabled ) {
-                                       event.preventDefault();
-                                       event.stopImmediatePropagation();
-                               }
-                       });
-
-               // Can't use _focusable() because the element that receives focus
-               // and the element that gets the ui-state-focus class are different
-               this._on({
-                       focus: function() {
-                               this.buttonElement.addClass( "ui-state-focus" );
-                       },
-                       blur: function() {
-                               this.buttonElement.removeClass( "ui-state-focus" );
-                       }
-               });
-
-               if ( toggleButton ) {
-                       this.element.bind( "change" + this.eventNamespace, function() {
-                               that.refresh();
-                       });
-               }
-
-               if ( this.type === "checkbox" ) {
-                       this.buttonElement.bind( "click" + this.eventNamespace, function() {
-                               if ( options.disabled ) {
-                                       return false;
-                               }
-                       });
-               } else if ( this.type === "radio" ) {
-                       this.buttonElement.bind( "click" + this.eventNamespace, function() {
-                               if ( options.disabled ) {
-                                       return false;
-                               }
-                               $( this ).addClass( "ui-state-active" );
-                               that.buttonElement.attr( "aria-pressed", "true" );
-
-                               var radio = that.element[ 0 ];
-                               radioGroup( radio )
-                                       .not( radio )
-                                       .map(function() {
-                                               return $( this ).button( "widget" )[ 0 ];
-                                       })
-                                       .removeClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "false" );
-                       });
-               } else {
-                       this.buttonElement
-                               .bind( "mousedown" + this.eventNamespace, function() {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       $( this ).addClass( "ui-state-active" );
-                                       lastActive = this;
-                                       that.document.one( "mouseup", function() {
-                                               lastActive = null;
-                                       });
-                               })
-                               .bind( "mouseup" + this.eventNamespace, function() {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       $( this ).removeClass( "ui-state-active" );
-                               })
-                               .bind( "keydown" + this.eventNamespace, function(event) {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
-                                               $( this ).addClass( "ui-state-active" );
-                                       }
-                               })
-                               // see #8559, we bind to blur here in case the button element loses
-                               // focus between keydown and keyup, it would be left in an "active" state
-                               .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
-                                       $( this ).removeClass( "ui-state-active" );
-                               });
-
-                       if ( this.buttonElement.is("a") ) {
-                               this.buttonElement.keyup(function(event) {
-                                       if ( event.keyCode === $.ui.keyCode.SPACE ) {
-                                               // TODO pass through original event correctly (just as 2nd argument doesn't work)
-                                               $( this ).click();
-                                       }
-                               });
-                       }
-               }
-
-               // TODO: pull out $.Widget's handling for the disabled option into
-               // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
-               // be overridden by individual plugins
-               this._setOption( "disabled", options.disabled );
-               this._resetButton();
-       },
-
-       _determineButtonType: function() {
-               var ancestor, labelSelector, checked;
-
-               if ( this.element.is("[type=checkbox]") ) {
-                       this.type = "checkbox";
-               } else if ( this.element.is("[type=radio]") ) {
-                       this.type = "radio";
-               } else if ( this.element.is("input") ) {
-                       this.type = "input";
-               } else {
-                       this.type = "button";
-               }
-
-               if ( this.type === "checkbox" || this.type === "radio" ) {
-                       // we don't search against the document in case the element
-                       // is disconnected from the DOM
-                       ancestor = this.element.parents().last();
-                       labelSelector = "label[for='" + this.element.attr("id") + "']";
-                       this.buttonElement = ancestor.find( labelSelector );
-                       if ( !this.buttonElement.length ) {
-                               ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
-                               this.buttonElement = ancestor.filter( labelSelector );
-                               if ( !this.buttonElement.length ) {
-                                       this.buttonElement = ancestor.find( labelSelector );
-                               }
-                       }
-                       this.element.addClass( "ui-helper-hidden-accessible" );
-
-                       checked = this.element.is( ":checked" );
-                       if ( checked ) {
-                               this.buttonElement.addClass( "ui-state-active" );
-                       }
-                       this.buttonElement.prop( "aria-pressed", checked );
-               } else {
-                       this.buttonElement = this.element;
-               }
-       },
-
-       widget: function() {
-               return this.buttonElement;
-       },
-
-       _destroy: function() {
-               this.element
-                       .removeClass( "ui-helper-hidden-accessible" );
-               this.buttonElement
-                       .removeClass( baseClasses + " ui-state-active " + typeClasses )
-                       .removeAttr( "role" )
-                       .removeAttr( "aria-pressed" )
-                       .html( this.buttonElement.find(".ui-button-text").html() );
-
-               if ( !this.hasTitle ) {
-                       this.buttonElement.removeAttr( "title" );
-               }
-       },
-
-       _setOption: function( key, value ) {
-               this._super( key, value );
-               if ( key === "disabled" ) {
-                       this.element.prop( "disabled", !!value );
-                       if ( value ) {
-                               this.buttonElement.removeClass( "ui-state-focus" );
-                       }
-                       return;
-               }
-               this._resetButton();
-       },
-
-       refresh: function() {
-               //See #8237 & #8828
-               var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
-
-               if ( isDisabled !== this.options.disabled ) {
-                       this._setOption( "disabled", isDisabled );
-               }
-               if ( this.type === "radio" ) {
-                       radioGroup( this.element[0] ).each(function() {
-                               if ( $( this ).is( ":checked" ) ) {
-                                       $( this ).button( "widget" )
-                                               .addClass( "ui-state-active" )
-                                               .attr( "aria-pressed", "true" );
-                               } else {
-                                       $( this ).button( "widget" )
-                                               .removeClass( "ui-state-active" )
-                                               .attr( "aria-pressed", "false" );
-                               }
-                       });
-               } else if ( this.type === "checkbox" ) {
-                       if ( this.element.is( ":checked" ) ) {
-                               this.buttonElement
-                                       .addClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "true" );
-                       } else {
-                               this.buttonElement
-                                       .removeClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "false" );
-                       }
-               }
-       },
-
-       _resetButton: function() {
-               if ( this.type === "input" ) {
-                       if ( this.options.label ) {
-                               this.element.val( this.options.label );
-                       }
-                       return;
-               }
-               var buttonElement = this.buttonElement.removeClass( typeClasses ),
-                       buttonText = $( "<span></span>", this.document[0] )
-                               .addClass( "ui-button-text" )
-                               .html( this.options.label )
-                               .appendTo( buttonElement.empty() )
-                               .text(),
-                       icons = this.options.icons,
-                       multipleIcons = icons.primary && icons.secondary,
-                       buttonClasses = [];
-
-               if ( icons.primary || icons.secondary ) {
-                       if ( this.options.text ) {
-                               buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
-                       }
-
-                       if ( icons.primary ) {
-                               buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
-                       }
-
-                       if ( icons.secondary ) {
-                               buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
-                       }
-
-                       if ( !this.options.text ) {
-                               buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
-
-                               if ( !this.hasTitle ) {
-                                       buttonElement.attr( "title", $.trim( buttonText ) );
-                               }
-                       }
-               } else {
-                       buttonClasses.push( "ui-button-text-only" );
-               }
-               buttonElement.addClass( buttonClasses.join( " " ) );
-       }
-});
-
-$.widget( "ui.buttonset", {
-       version: "1.10.4",
-       options: {
-               items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
-       },
-
-       _create: function() {
-               this.element.addClass( "ui-buttonset" );
-       },
-
-       _init: function() {
-               this.refresh();
-       },
-
-       _setOption: function( key, value ) {
-               if ( key === "disabled" ) {
-                       this.buttons.button( "option", key, value );
-               }
-
-               this._super( key, value );
-       },
-
-       refresh: function() {
-               var rtl = this.element.css( "direction" ) === "rtl";
-
-               this.buttons = this.element.find( this.options.items )
-                       .filter( ":ui-button" )
-                               .button( "refresh" )
-                       .end()
-                       .not( ":ui-button" )
-                               .button()
-                       .end()
-                       .map(function() {
-                               return $( this ).button( "widget" )[ 0 ];
-                       })
-                               .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
-                               .filter( ":first" )
-                                       .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
-                               .end()
-                               .filter( ":last" )
-                                       .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
-                               .end()
-                       .end();
-       },
-
-       _destroy: function() {
-               this.element.removeClass( "ui-buttonset" );
-               this.buttons
-                       .map(function() {
-                               return $( this ).button( "widget" )[ 0 ];
-                       })
-                               .removeClass( "ui-corner-left ui-corner-right" )
-                       .end()
-                       .button( "destroy" );
-       }
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-$.extend($.ui, { datepicker: { version: "1.10.4" } });
-
-var PROP_NAME = "datepicker",
-       instActive;
-
-/* Date picker manager.
-   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
-   Settings for (groups of) date pickers are maintained in an instance object,
-   allowing multiple different settings on the same page. */
-
-function Datepicker() {
-       this._curInst = null; // The current instance in use
-       this._keyEvent = false; // If the last event was a key event
-       this._disabledInputs = []; // List of date picker inputs that have been disabled
-       this._datepickerShowing = false; // True if the popup picker is showing , false if not
-       this._inDialog = false; // True if showing within a "dialog", false if not
-       this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
-       this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
-       this._appendClass = "ui-datepicker-append"; // The name of the append marker class
-       this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
-       this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
-       this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
-       this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
-       this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
-       this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
-       this.regional = []; // Available regional settings, indexed by language code
-       this.regional[""] = { // Default regional settings
-               closeText: "Done", // Display text for close link
-               prevText: "Prev", // Display text for previous month link
-               nextText: "Next", // Display text for next month link
-               currentText: "Today", // Display text for current month link
-               monthNames: ["January","February","March","April","May","June",
-                       "July","August","September","October","November","December"], // Names of months for drop-down and formatting
-               monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
-               dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
-               dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
-               dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
-               weekHeader: "Wk", // Column header for week of the year
-               dateFormat: "mm/dd/yy", // See format options on parseDate
-               firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
-               isRTL: false, // True if right-to-left language, false if left-to-right
-               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
-               yearSuffix: "" // Additional text to append to the year in the month headers
-       };
-       this._defaults = { // Global defaults for all the date picker instances
-               showOn: "focus", // "focus" for popup on focus,
-                       // "button" for trigger button, or "both" for either
-               showAnim: "fadeIn", // Name of jQuery animation for popup
-               showOptions: {}, // Options for enhanced animations
-               defaultDate: null, // Used when field is blank: actual date,
-                       // +/-number for offset from today, null for today
-               appendText: "", // Display text following the input box, e.g. showing the format
-               buttonText: "...", // Text for trigger button
-               buttonImage: "", // URL for trigger button image
-               buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
-               hideIfNoPrevNext: false, // True to hide next/previous month links
-                       // if not applicable, false to just disable them
-               navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
-               gotoCurrent: false, // True if today link goes back to current selection instead
-               changeMonth: false, // True if month can be selected directly, false if only prev/next
-               changeYear: false, // True if year can be selected directly, false if only prev/next
-               yearRange: "c-10:c+10", // Range of years to display in drop-down,
-                       // either relative to today's year (-nn:+nn), relative to currently displayed year
-                       // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
-               showOtherMonths: false, // True to show dates in other months, false to leave blank
-               selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
-               showWeek: false, // True to show week of the year, false to not show it
-               calculateWeek: this.iso8601Week, // How to calculate the week of the year,
-                       // takes a Date and returns the number of the week for it
-               shortYearCutoff: "+10", // Short year values < this are in the current century,
-                       // > this are in the previous century,
-                       // string value starting with "+" for current year + value
-               minDate: null, // The earliest selectable date, or null for no limit
-               maxDate: null, // The latest selectable date, or null for no limit
-               duration: "fast", // Duration of display/closure
-               beforeShowDay: null, // Function that takes a date and returns an array with
-                       // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
-                       // [2] = cell title (optional), e.g. $.datepicker.noWeekends
-               beforeShow: null, // Function that takes an input field and
-                       // returns a set of custom settings for the date picker
-               onSelect: null, // Define a callback function when a date is selected
-               onChangeMonthYear: null, // Define a callback function when the month or year is changed
-               onClose: null, // Define a callback function when the datepicker is closed
-               numberOfMonths: 1, // Number of months to show at a time
-               showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
-               stepMonths: 1, // Number of months to step back/forward
-               stepBigMonths: 12, // Number of months to step back/forward for the big links
-               altField: "", // Selector for an alternate field to store selected dates into
-               altFormat: "", // The date format to use for the alternate field
-               constrainInput: true, // The input is constrained by the current date format
-               showButtonPanel: false, // True to show button panel, false to not show it
-               autoSize: false, // True to size the input for the date format, false to leave as is
-               disabled: false // The initial disabled state
-       };
-       $.extend(this._defaults, this.regional[""]);
-       this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
-  this.dpDiv.on('click', function(e) { e.stopPropagation(); });
-}
-
-$.extend(Datepicker.prototype, {
-       /* Class name added to elements to indicate already configured with a date picker. */
-       markerClassName: "hasDatepicker",
-
-       //Keep track of the maximum number of rows displayed (see #7043)
-       maxRows: 4,
-
-       // TODO rename to "widget" when switching to widget factory
-       _widgetDatepicker: function() {
-               return this.dpDiv;
-       },
-
-       /* Override the default settings for all instances of the date picker.
-        * @param  settings  object - the new settings to use as defaults (anonymous object)
-        * @return the manager object
-        */
-       setDefaults: function(settings) {
-               extendRemove(this._defaults, settings || {});
-               return this;
-       },
-
-       /* Attach the date picker to a jQuery selection.
-        * @param  target       element - the target input field or division or span
-        * @param  settings  object - the new settings to use for this date picker instance (anonymous)
-        */
-       _attachDatepicker: function(target, settings) {
-               var nodeName, inline, inst;
-               nodeName = target.nodeName.toLowerCase();
-               inline = (nodeName === "div" || nodeName === "span");
-               if (!target.id) {
-                       this.uuid += 1;
-                       target.id = "dp" + this.uuid;
-               }
-               inst = this._newInst($(target), inline);
-               inst.settings = $.extend({}, settings || {});
-               if (nodeName === "input") {
-                       this._connectDatepicker(target, inst);
-               } else if (inline) {
-                       this._inlineDatepicker(target, inst);
-               }
-       },
-
-       /* Create a new instance object. */
-       _newInst: function(target, inline) {
-               var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
-               return {id: id, input: target, // associated target
-                       selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
-                       drawMonth: 0, drawYear: 0, // month being drawn
-                       inline: inline, // is datepicker inline or not
-                       dpDiv: (!inline ? this.dpDiv : // presentation div
-                       bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
-       },
-
-       /* Attach the date picker to an input field. */
-       _connectDatepicker: function(target, inst) {
-               var input = $(target);
-               inst.append = $([]);
-               inst.trigger = $([]);
-               if (input.hasClass(this.markerClassName)) {
-                       return;
-               }
-               this._attachments(input, inst);
-               input.addClass(this.markerClassName).keydown(this._doKeyDown).
-                       keypress(this._doKeyPress).keyup(this._doKeyUp);
-               this._autoSize(inst);
-               $.data(target, PROP_NAME, inst);
-               //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
-               if( inst.settings.disabled ) {
-                       this._disableDatepicker( target );
-               }
-       },
-
-       /* Make attachments based on settings. */
-       _attachments: function(input, inst) {
-               var showOn, buttonText, buttonImage,
-                       appendText = this._get(inst, "appendText"),
-                       isRTL = this._get(inst, "isRTL");
-
-               if (inst.append) {
-                       inst.append.remove();
-               }
-               if (appendText) {
-                       inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
-                       input[isRTL ? "before" : "after"](inst.append);
-               }
-
-               input.unbind("focus", this._showDatepicker);
-
-               if (inst.trigger) {
-                       inst.trigger.remove();
-               }
-
-               showOn = this._get(inst, "showOn");
-               if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
-                       input.focus(this._showDatepicker);
-               }
-               if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
-                       buttonText = this._get(inst, "buttonText");
-                       buttonImage = this._get(inst, "buttonImage");
-                       inst.trigger = $(this._get(inst, "buttonImageOnly") ?
-                               $("<img/>").addClass(this._triggerClass).
-                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
-                               $("<button type='button'></button>").addClass(this._triggerClass).
-                                       html(!buttonImage ? buttonText : $("<img/>").attr(
-                                       { src:buttonImage, alt:buttonText, title:buttonText })));
-                       input[isRTL ? "before" : "after"](inst.trigger);
-                       inst.trigger.click(function() {
-                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
-                                       $.datepicker._hideDatepicker();
-                               } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
-                                       $.datepicker._hideDatepicker();
-                                       $.datepicker._showDatepicker(input[0]);
-                               } else {
-                                       $.datepicker._showDatepicker(input[0]);
-                               }
-                               return false;
-                       });
-               }
-       },
-
-       /* Apply the maximum length for the date format. */
-       _autoSize: function(inst) {
-               if (this._get(inst, "autoSize") && !inst.inline) {
-                       var findMax, max, maxI, i,
-                               date = new Date(2009, 12 - 1, 20), // Ensure double digits
-                               dateFormat = this._get(inst, "dateFormat");
-
-                       if (dateFormat.match(/[DM]/)) {
-                               findMax = function(names) {
-                                       max = 0;
-                                       maxI = 0;
-                                       for (i = 0; i < names.length; i++) {
-                                               if (names[i].length > max) {
-                                                       max = names[i].length;
-                                                       maxI = i;
-                                               }
-                                       }
-                                       return maxI;
-                               };
-                               date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
-                                       "monthNames" : "monthNamesShort"))));
-                               date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
-                                       "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
-                       }
-                       inst.input.attr("size", this._formatDate(inst, date).length);
-               }
-       },
-
-       /* Attach an inline date picker to a div. */
-       _inlineDatepicker: function(target, inst) {
-               var divSpan = $(target);
-               if (divSpan.hasClass(this.markerClassName)) {
-                       return;
-               }
-               divSpan.addClass(this.markerClassName).append(inst.dpDiv);
-               $.data(target, PROP_NAME, inst);
-               this._setDate(inst, this._getDefaultDate(inst), true);
-               this._updateDatepicker(inst);
-               this._updateAlternate(inst);
-               //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
-               if( inst.settings.disabled ) {
-                       this._disableDatepicker( target );
-               }
-               // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
-               // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
-               inst.dpDiv.css( "display", "block" );
-       },
-
-       /* Pop-up the date picker in a "dialog" box.
-        * @param  input element - ignored
-        * @param  date string or Date - the initial date to display
-        * @param  onSelect  function - the function to call when a date is selected
-        * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
-        * @param  pos int[2] - coordinates for the dialog's position within the screen or
-        *                                      event - with x/y coordinates or
-        *                                      leave empty for default (screen centre)
-        * @return the manager object
-        */
-       _dialogDatepicker: function(input, date, onSelect, settings, pos) {
-               var id, browserWidth, browserHeight, scrollX, scrollY,
-                       inst = this._dialogInst; // internal instance
-
-               if (!inst) {
-                       this.uuid += 1;
-                       id = "dp" + this.uuid;
-                       this._dialogInput = $("<input type='text' id='" + id +
-                               "' style='position: absolute; top: -100px; width: 0px;'/>");
-                       this._dialogInput.keydown(this._doKeyDown);
-                       $("body").append(this._dialogInput);
-                       inst = this._dialogInst = this._newInst(this._dialogInput, false);
-                       inst.settings = {};
-                       $.data(this._dialogInput[0], PROP_NAME, inst);
-               }
-               extendRemove(inst.settings, settings || {});
-               date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
-               this._dialogInput.val(date);
-
-               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
-               if (!this._pos) {
-                       browserWidth = document.documentElement.clientWidth;
-                       browserHeight = document.documentElement.clientHeight;
-                       scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
-                       scrollY = document.documentElement.scrollTop || document.body.scrollTop;
-                       this._pos = // should use actual width/height below
-                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
-               }
-
-               // move input on screen for focus, but hidden behind dialog
-               this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
-               inst.settings.onSelect = onSelect;
-               this._inDialog = true;
-               this.dpDiv.addClass(this._dialogClass);
-               this._showDatepicker(this._dialogInput[0]);
-               if ($.blockUI) {
-                       $.blockUI(this.dpDiv);
-               }
-               $.data(this._dialogInput[0], PROP_NAME, inst);
-               return this;
-       },
-
-       /* Detach a datepicker from its control.
-        * @param  target       element - the target input field or division or span
-        */
-       _destroyDatepicker: function(target) {
-               var nodeName,
-                       $target = $(target),
-                       inst = $.data(target, PROP_NAME);
-
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-
-               nodeName = target.nodeName.toLowerCase();
-               $.removeData(target, PROP_NAME);
-               if (nodeName === "input") {
-                       inst.append.remove();
-                       inst.trigger.remove();
-                       $target.removeClass(this.markerClassName).
-                               unbind("focus", this._showDatepicker).
-                               unbind("keydown", this._doKeyDown).
-                               unbind("keypress", this._doKeyPress).
-                               unbind("keyup", this._doKeyUp);
-               } else if (nodeName === "div" || nodeName === "span") {
-                       $target.removeClass(this.markerClassName).empty();
-               }
-       },
-
-       /* Enable the date picker to a jQuery selection.
-        * @param  target       element - the target input field or division or span
-        */
-       _enableDatepicker: function(target) {
-               var nodeName, inline,
-                       $target = $(target),
-                       inst = $.data(target, PROP_NAME);
-
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-
-               nodeName = target.nodeName.toLowerCase();
-               if (nodeName === "input") {
-                       target.disabled = false;
-                       inst.trigger.filter("button").
-                               each(function() { this.disabled = false; }).end().
-                               filter("img").css({opacity: "1.0", cursor: ""});
-               } else if (nodeName === "div" || nodeName === "span") {
-                       inline = $target.children("." + this._inlineClass);
-                       inline.children().removeClass("ui-state-disabled");
-                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-                               prop("disabled", false);
-               }
-               this._disabledInputs = $.map(this._disabledInputs,
-                       function(value) { return (value === target ? null : value); }); // delete entry
-       },
-
-       /* Disable the date picker to a jQuery selection.
-        * @param  target       element - the target input field or division or span
-        */
-       _disableDatepicker: function(target) {
-               var nodeName, inline,
-                       $target = $(target),
-                       inst = $.data(target, PROP_NAME);
-
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-
-               nodeName = target.nodeName.toLowerCase();
-               if (nodeName === "input") {
-                       target.disabled = true;
-                       inst.trigger.filter("button").
-                               each(function() { this.disabled = true; }).end().
-                               filter("img").css({opacity: "0.5", cursor: "default"});
-               } else if (nodeName === "div" || nodeName === "span") {
-                       inline = $target.children("." + this._inlineClass);
-                       inline.children().addClass("ui-state-disabled");
-                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-                               prop("disabled", true);
-               }
-               this._disabledInputs = $.map(this._disabledInputs,
-                       function(value) { return (value === target ? null : value); }); // delete entry
-               this._disabledInputs[this._disabledInputs.length] = target;
-       },
-
-       /* Is the first field in a jQuery collection disabled as a datepicker?
-        * @param  target       element - the target input field or division or span
-        * @return boolean - true if disabled, false if enabled
-        */
-       _isDisabledDatepicker: function(target) {
-               if (!target) {
-                       return false;
-               }
-               for (var i = 0; i < this._disabledInputs.length; i++) {
-                       if (this._disabledInputs[i] === target) {
-                               return true;
-                       }
-               }
-               return false;
-       },
-
-       /* Retrieve the instance data for the target control.
-        * @param  target  element - the target input field or division or span
-        * @return  object - the associated instance data
-        * @throws  error if a jQuery problem getting data
-        */
-       _getInst: function(target) {
-               try {
-                       return $.data(target, PROP_NAME);
-               }
-               catch (err) {
-                       throw "Missing instance data for this datepicker";
-               }
-       },
-
-       /* Update or retrieve the settings for a date picker attached to an input field or division.
-        * @param  target  element - the target input field or division or span
-        * @param  name object - the new settings to update or
-        *                              string - the name of the setting to change or retrieve,
-        *                              when retrieving also "all" for all instance settings or
-        *                              "defaults" for all global defaults
-        * @param  value   any - the new value for the setting
-        *                              (omit if above is an object or to retrieve a value)
-        */
-       _optionDatepicker: function(target, name, value) {
-               var settings, date, minDate, maxDate,
-                       inst = this._getInst(target);
-
-               if (arguments.length === 2 && typeof name === "string") {
-                       return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
-                               (inst ? (name === "all" ? $.extend({}, inst.settings) :
-                               this._get(inst, name)) : null));
-               }
-
-               settings = name || {};
-               if (typeof name === "string") {
-                       settings = {};
-                       settings[name] = value;
-               }
-
-               if (inst) {
-                       if (this._curInst === inst) {
-                               this._hideDatepicker();
-                       }
-
-                       date = this._getDateDatepicker(target, true);
-                       minDate = this._getMinMaxDate(inst, "min");
-                       maxDate = this._getMinMaxDate(inst, "max");
-                       extendRemove(inst.settings, settings);
-                       // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
-                       if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
-                               inst.settings.minDate = this._formatDate(inst, minDate);
-                       }
-                       if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
-                               inst.settings.maxDate = this._formatDate(inst, maxDate);
-                       }
-                       if ( "disabled" in settings ) {
-                               if ( settings.disabled ) {
-                                       this._disableDatepicker(target);
-                               } else {
-                                       this._enableDatepicker(target);
-                               }
-                       }
-                       this._attachments($(target), inst);
-                       this._autoSize(inst);
-                       this._setDate(inst, date);
-                       this._updateAlternate(inst);
-                       this._updateDatepicker(inst);
-               }
-       },
-
-       // change method deprecated
-       _changeDatepicker: function(target, name, value) {
-               this._optionDatepicker(target, name, value);
-       },
-
-       /* Redraw the date picker attached to an input field or division.
-        * @param  target  element - the target input field or division or span
-        */
-       _refreshDatepicker: function(target) {
-               var inst = this._getInst(target);
-               if (inst) {
-                       this._updateDatepicker(inst);
-               }
-       },
-
-       /* Set the dates for a jQuery selection.
-        * @param  target element - the target input field or division or span
-        * @param  date Date - the new date
-        */
-       _setDateDatepicker: function(target, date) {
-               var inst = this._getInst(target);
-               if (inst) {
-                       this._setDate(inst, date);
-                       this._updateDatepicker(inst);
-                       this._updateAlternate(inst);
-               }
-       },
-
-       /* Get the date(s) for the first entry in a jQuery selection.
-        * @param  target element - the target input field or division or span
-        * @param  noDefault boolean - true if no default date is to be used
-        * @return Date - the current date
-        */
-       _getDateDatepicker: function(target, noDefault) {
-               var inst = this._getInst(target);
-               if (inst && !inst.inline) {
-                       this._setDateFromField(inst, noDefault);
-               }
-               return (inst ? this._getDate(inst) : null);
-       },
-
-       /* Handle keystrokes. */
-       _doKeyDown: function(event) {
-               var onSelect, dateStr, sel,
-                       inst = $.datepicker._getInst(event.target),
-                       handled = true,
-                       isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
-
-               inst._keyEvent = true;
-               if ($.datepicker._datepickerShowing) {
-                       switch (event.keyCode) {
-                               case 9: $.datepicker._hideDatepicker();
-                                               handled = false;
-                                               break; // hide on tab out
-                               case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
-                                                                       $.datepicker._currentClass + ")", inst.dpDiv);
-                                               if (sel[0]) {
-                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
-                                               }
-
-                                               onSelect = $.datepicker._get(inst, "onSelect");
-                                               if (onSelect) {
-                                                       dateStr = $.datepicker._formatDate(inst);
-
-                                                       // trigger custom callback
-                                                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
-                                               } else {
-                                                       $.datepicker._hideDatepicker();
-                                               }
-
-                                               return false; // don't submit the form
-                               case 27: $.datepicker._hideDatepicker();
-                                               break; // hide on escape
-                               case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                       -$.datepicker._get(inst, "stepBigMonths") :
-                                                       -$.datepicker._get(inst, "stepMonths")), "M");
-                                               break; // previous month/year on page up/+ ctrl
-                               case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                       +$.datepicker._get(inst, "stepBigMonths") :
-                                                       +$.datepicker._get(inst, "stepMonths")), "M");
-                                               break; // next month/year on page down/+ ctrl
-                               case 35: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._clearDate(event.target);
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // clear on ctrl or command +end
-                               case 36: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._gotoToday(event.target);
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // current on ctrl or command +home
-                               case 37: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               // -1 day on ctrl or command +left
-                                               if (event.originalEvent.altKey) {
-                                                       $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                               -$.datepicker._get(inst, "stepBigMonths") :
-                                                               -$.datepicker._get(inst, "stepMonths")), "M");
-                                               }
-                                               // next month/year on alt +left on Mac
-                                               break;
-                               case 38: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._adjustDate(event.target, -7, "D");
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // -1 week on ctrl or command +up
-                               case 39: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               // +1 day on ctrl or command +right
-                                               if (event.originalEvent.altKey) {
-                                                       $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                               +$.datepicker._get(inst, "stepBigMonths") :
-                                                               +$.datepicker._get(inst, "stepMonths")), "M");
-                                               }
-                                               // next month/year on alt +right
-                                               break;
-                               case 40: if (event.ctrlKey || event.metaKey) {
-                                                       $.datepicker._adjustDate(event.target, +7, "D");
-                                               }
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // +1 week on ctrl or command +down
-                               default: handled = false;
-                       }
-               } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
-                       $.datepicker._showDatepicker(this);
-               } else {
-                       handled = false;
-               }
-
-               if (handled) {
-                       event.preventDefault();
-                       event.stopPropagation();
-               }
-       },
-
-       /* Filter entered characters - based on date format. */
-       _doKeyPress: function(event) {
-               var chars, chr,
-                       inst = $.datepicker._getInst(event.target);
-
-               if ($.datepicker._get(inst, "constrainInput")) {
-                       chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
-                       chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
-                       return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
-               }
-       },
-
-       /* Synchronise manual entry and field/alternate field. */
-       _doKeyUp: function(event) {
-               var date,
-                       inst = $.datepicker._getInst(event.target);
-
-               if (inst.input.val() !== inst.lastVal) {
-                       try {
-                               date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
-                                       (inst.input ? inst.input.val() : null),
-                                       $.datepicker._getFormatConfig(inst));
-
-                               if (date) { // only if valid
-                                       $.datepicker._setDateFromField(inst);
-                                       $.datepicker._updateAlternate(inst);
-                                       $.datepicker._updateDatepicker(inst);
-                               }
-                       }
-                       catch (err) {
-                       }
-               }
-               return true;
-       },
-
-       /* Pop-up the date picker for a given input field.
-        * If false returned from beforeShow event handler do not show.
-        * @param  input  element - the input field attached to the date picker or
-        *                                      event - if triggered by focus
-        */
-       _showDatepicker: function(input) {
-               input = input.target || input;
-               if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
-                       input = $("input", input.parentNode)[0];
-               }
-
-               if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
-                       return;
-               }
-
-               var inst, beforeShow, beforeShowSettings, isFixed,
-                       offset, showAnim, duration;
-
-               inst = $.datepicker._getInst(input);
-               if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
-                       $.datepicker._curInst.dpDiv.stop(true, true);
-                       if ( inst && $.datepicker._datepickerShowing ) {
-                               $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
-                       }
-               }
-
-               beforeShow = $.datepicker._get(inst, "beforeShow");
-               beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
-               if(beforeShowSettings === false){
-                       return;
-               }
-               extendRemove(inst.settings, beforeShowSettings);
-
-               inst.lastVal = null;
-               $.datepicker._lastInput = input;
-               $.datepicker._setDateFromField(inst);
-
-               if ($.datepicker._inDialog) { // hide cursor
-                       input.value = "";
-               }
-               if (!$.datepicker._pos) { // position below input
-                       $.datepicker._pos = $.datepicker._findPos(input);
-                       $.datepicker._pos[1] += input.offsetHeight; // add the height
-               }
-
-               isFixed = false;
-               $(input).parents().each(function() {
-                       isFixed |= $(this).css("position") === "fixed";
-                       return !isFixed;
-               });
-
-               offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
-               $.datepicker._pos = null;
-               //to avoid flashes on Firefox
-               inst.dpDiv.empty();
-               // determine sizing offscreen
-               inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
-               $.datepicker._updateDatepicker(inst);
-               // fix width for dynamic number of date pickers
-               // and adjust position before showing
-               offset = $.datepicker._checkOffset(inst, offset, isFixed);
-               inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
-                       "static" : (isFixed ? "fixed" : "absolute")), display: "none",
-                       left: offset.left + "px", top: offset.top + "px"});
-
-               if (!inst.inline) {
-                       showAnim = $.datepicker._get(inst, "showAnim");
-                       duration = $.datepicker._get(inst, "duration");
-                       inst.dpDiv.zIndex($(input).zIndex()+1);
-                       $.datepicker._datepickerShowing = true;
-
-                       if ( $.effects && $.effects.effect[ showAnim ] ) {
-                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
-                       } else {
-                               inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
-                       }
-
-                       if ( $.datepicker._shouldFocusInput( inst ) ) {
-                               inst.input.focus();
-                       }
-
-                       $.datepicker._curInst = inst;
-               }
-       },
-
-       /* Generate the date picker content. */
-       _updateDatepicker: function(inst) {
-               this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
-               instActive = inst; // for delegate hover events
-               inst.dpDiv.empty().append(this._generateHTML(inst));
-               this._attachHandlers(inst);
-               inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
-
-               var origyearshtml,
-                       numMonths = this._getNumberOfMonths(inst),
-                       cols = numMonths[1],
-                       width = 17;
-
-               inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
-               if (cols > 1) {
-                       inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
-               }
-               inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
-                       "Class"]("ui-datepicker-multi");
-               inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
-                       "Class"]("ui-datepicker-rtl");
-
-               if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
-                       inst.input.focus();
-               }
-
-               // deffered render of the years select (to avoid flashes on Firefox)
-               if( inst.yearshtml ){
-                       origyearshtml = inst.yearshtml;
-                       setTimeout(function(){
-                               //assure that inst.yearshtml didn't change.
-                               if( origyearshtml === inst.yearshtml && inst.yearshtml ){
-                                       inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
-                               }
-                               origyearshtml = inst.yearshtml = null;
-                       }, 0);
-               }
-       },
-
-       // #6694 - don't focus the input if it's already focused
-       // this breaks the change event in IE
-       // Support: IE and jQuery <1.9
-       _shouldFocusInput: function( inst ) {
-               return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
-       },
-
-       /* Check positioning to remain on screen. */
-       _checkOffset: function(inst, offset, isFixed) {
-               var dpWidth = inst.dpDiv.outerWidth(),
-                       dpHeight = inst.dpDiv.outerHeight(),
-                       inputWidth = inst.input ? inst.input.outerWidth() : 0,
-                       inputHeight = inst.input ? inst.input.outerHeight() : 0,
-                       viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
-                       viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
-
-               offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
-               offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
-               offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
-
-               // now check if datepicker is showing outside window viewport - move to a better place if so.
-               offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
-                       Math.abs(offset.left + dpWidth - viewWidth) : 0);
-               offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
-                       Math.abs(dpHeight + inputHeight) : 0);
-
-               return offset;
-       },
-
-       /* Find an object's position on the screen. */
-       _findPos: function(obj) {
-               var position,
-                       inst = this._getInst(obj),
-                       isRTL = this._get(inst, "isRTL");
-
-               while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
-                       obj = obj[isRTL ? "previousSibling" : "nextSibling"];
-               }
-
-               position = $(obj).offset();
-               return [position.left, position.top];
-       },
-
-       /* Hide the date picker from view.
-        * @param  input  element - the input field attached to the date picker
-        */
-       _hideDatepicker: function(input) {
-               var showAnim, duration, postProcess, onClose,
-                       inst = this._curInst;
-
-               if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
-                       return;
-               }
-
-               if (this._datepickerShowing) {
-                       showAnim = this._get(inst, "showAnim");
-                       duration = this._get(inst, "duration");
-                       postProcess = function() {
-                               $.datepicker._tidyDialog(inst);
-                       };
-
-                       // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
-                       if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
-                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
-                       } else {
-                               inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
-                                       (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
-                       }
-
-                       if (!showAnim) {
-                               postProcess();
-                       }
-                       this._datepickerShowing = false;
-
-                       onClose = this._get(inst, "onClose");
-                       if (onClose) {
-                               onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
-                       }
-
-                       this._lastInput = null;
-                       if (this._inDialog) {
-                               this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
-                               if ($.blockUI) {
-                                       $.unblockUI();
-                                       $("body").append(this.dpDiv);
-                               }
-                       }
-                       this._inDialog = false;
-               }
-       },
-
-       /* Tidy up after a dialog display. */
-       _tidyDialog: function(inst) {
-               inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
-       },
-
-       /* Close date picker if clicked elsewhere. */
-       _checkExternalClick: function(event) {
-               if (!$.datepicker._curInst) {
-                       return;
-               }
-
-               var $target = $(event.target),
-                       inst = $.datepicker._getInst($target[0]);
-
-               if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
-                               $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
-                               !$target.hasClass($.datepicker.markerClassName) &&
-                               !$target.closest("." + $.datepicker._triggerClass).length &&
-                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
-                       ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
-                               $.datepicker._hideDatepicker();
-               }
-       },
-
-       /* Adjust one of the date sub-fields. */
-       _adjustDate: function(id, offset, period) {
-               var target = $(id),
-                       inst = this._getInst(target[0]);
-
-               if (this._isDisabledDatepicker(target[0])) {
-                       return;
-               }
-               this._adjustInstDate(inst, offset +
-                       (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
-                       period);
-               this._updateDatepicker(inst);
-       },
-
-       /* Action for current link. */
-       _gotoToday: function(id) {
-               var date,
-                       target = $(id),
-                       inst = this._getInst(target[0]);
-
-               if (this._get(inst, "gotoCurrent") && inst.currentDay) {
-                       inst.selectedDay = inst.currentDay;
-                       inst.drawMonth = inst.selectedMonth = inst.currentMonth;
-                       inst.drawYear = inst.selectedYear = inst.currentYear;
-               } else {
-                       date = new Date();
-                       inst.selectedDay = date.getDate();
-                       inst.drawMonth = inst.selectedMonth = date.getMonth();
-                       inst.drawYear = inst.selectedYear = date.getFullYear();
-               }
-               this._notifyChange(inst);
-               this._adjustDate(target);
-       },
-
-       /* Action for selecting a new month/year. */
-       _selectMonthYear: function(id, select, period) {
-               var target = $(id),
-                       inst = this._getInst(target[0]);
-
-               inst["selected" + (period === "M" ? "Month" : "Year")] =
-               inst["draw" + (period === "M" ? "Month" : "Year")] =
-                       parseInt(select.options[select.selectedIndex].value,10);
-
-               this._notifyChange(inst);
-               this._adjustDate(target);
-       },
-
-       /* Action for selecting a day. */
-       _selectDay: function(id, month, year, td) {
-               var inst,
-                       target = $(id);
-
-               if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
-                       return;
-               }
-
-               inst = this._getInst(target[0]);
-               inst.selectedDay = inst.currentDay = $("a", td).html();
-               inst.selectedMonth = inst.currentMonth = month;
-               inst.selectedYear = inst.currentYear = year;
-               this._selectDate(id, this._formatDate(inst,
-                       inst.currentDay, inst.currentMonth, inst.currentYear));
-       },
-
-       /* Erase the input field and hide the date picker. */
-       _clearDate: function(id) {
-               var target = $(id);
-               this._selectDate(target, "");
-       },
-
-       /* Update the input field with the selected date. */
-       _selectDate: function(id, dateStr) {
-               var onSelect,
-                       target = $(id),
-                       inst = this._getInst(target[0]);
-
-               dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
-               if (inst.input) {
-                       inst.input.val(dateStr);
-               }
-               this._updateAlternate(inst);
-
-               onSelect = this._get(inst, "onSelect");
-               if (onSelect) {
-                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
-               } else if (inst.input) {
-                       inst.input.trigger("change"); // fire the change event
-               }
-
-               if (inst.inline){
-                       this._updateDatepicker(inst);
-               } else {
-                       this._hideDatepicker();
-                       this._lastInput = inst.input[0];
-                       if (typeof(inst.input[0]) !== "object") {
-                               inst.input.focus(); // restore focus
-                       }
-                       this._lastInput = null;
-               }
-       },
-
-       /* Update any alternate field to synchronise with the main field. */
-       _updateAlternate: function(inst) {
-               var altFormat, date, dateStr,
-                       altField = this._get(inst, "altField");
-
-               if (altField) { // update alternate field too
-                       altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
-                       date = this._getDate(inst);
-                       dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
-                       $(altField).each(function() { $(this).val(dateStr); });
-               }
-       },
-
-       /* Set as beforeShowDay function to prevent selection of weekends.
-        * @param  date  Date - the date to customise
-        * @return [boolean, string] - is this date selectable?, what is its CSS class?
-        */
-       noWeekends: function(date) {
-               var day = date.getDay();
-               return [(day > 0 && day < 6), ""];
-       },
-
-       /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
-        * @param  date  Date - the date to get the week for
-        * @return  number - the number of the week within the year that contains this date
-        */
-       iso8601Week: function(date) {
-               var time,
-                       checkDate = new Date(date.getTime());
-
-               // Find Thursday of this week starting on Monday
-               checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
-
-               time = checkDate.getTime();
-               checkDate.setMonth(0); // Compare with Jan 1
-               checkDate.setDate(1);
-               return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
-       },
-
-       /* Parse a string value into a date object.
-        * See formatDate below for the possible formats.
-        *
-        * @param  format string - the expected format of the date
-        * @param  value string - the date in the above format
-        * @param  settings Object - attributes include:
-        *                                      shortYearCutoff  number - the cutoff year for determining the century (optional)
-        *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
-        *                                      dayNames                string[7] - names of the days from Sunday (optional)
-        *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
-        *                                      monthNames              string[12] - names of the months (optional)
-        * @return  Date - the extracted date value or null if value is blank
-        */
-       parseDate: function (format, value, settings) {
-               if (format == null || value == null) {
-                       throw "Invalid arguments";
-               }
-
-               value = (typeof value === "object" ? value.toString() : value + "");
-               if (value === "") {
-                       return null;
-               }
-
-               var iFormat, dim, extra,
-                       iValue = 0,
-                       shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
-                       shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
-                               new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
-                       dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
-                       dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
-                       monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
-                       monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
-                       year = -1,
-                       month = -1,
-                       day = -1,
-                       doy = -1,
-                       literal = false,
-                       date,
-                       // Check whether a format character is doubled
-                       lookAhead = function(match) {
-                               var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
-                               if (matches) {
-                                       iFormat++;
-                               }
-                               return matches;
-                       },
-                       // Extract a number from the string value
-                       getNumber = function(match) {
-                               var isDoubled = lookAhead(match),
-                                       size = (match === "@" ? 14 : (match === "!" ? 20 :
-                                       (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
-                                       digits = new RegExp("^\\d{1," + size + "}"),
-                                       num = value.substring(iValue).match(digits);
-                               if (!num) {
-                                       throw "Missing number at position " + iValue;
-                               }
-                               iValue += num[0].length;
-                               return parseInt(num[0], 10);
-                       },
-                       // Extract a name from the string value and convert to an index
-                       getName = function(match, shortNames, longNames) {
-                               var index = -1,
-                                       names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
-                                               return [ [k, v] ];
-                                       }).sort(function (a, b) {
-                                               return -(a[1].length - b[1].length);
-                                       });
-
-                               $.each(names, function (i, pair) {
-                                       var name = pair[1];
-                                       if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
-                                               index = pair[0];
-                                               iValue += name.length;
-                                               return false;
-                                       }
-                               });
-                               if (index !== -1) {
-                                       return index + 1;
-                               } else {
-                                       throw "Unknown name at position " + iValue;
-                               }
-                       },
-                       // Confirm that a literal character matches the string value
-                       checkLiteral = function() {
-                               if (value.charAt(iValue) !== format.charAt(iFormat)) {
-                                       throw "Unexpected literal at position " + iValue;
-                               }
-                               iValue++;
-                       };
-
-               for (iFormat = 0; iFormat < format.length; iFormat++) {
-                       if (literal) {
-                               if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
-                                       literal = false;
-                               } else {
-                                       checkLiteral();
-                               }
-                       } else {
-                               switch (format.charAt(iFormat)) {
-                                       case "d":
-                                               day = getNumber("d");
-                                               break;
-                                       case "D":
-                                               getName("D", dayNamesShort, dayNames);
-                                               break;
-                                       case "o":
-                                               doy = getNumber("o");
-                                               break;
-                                       case "m":
-                                               month = getNumber("m");
-                                               break;
-                                       case "M":
-                                               month = getName("M", monthNamesShort, monthNames);
-                                               break;
-                                       case "y":
-                                               year = getNumber("y");
-                                               break;
-                                       case "@":
-                                               date = new Date(getNumber("@"));
-                                               year = date.getFullYear();
-                                               month = date.getMonth() + 1;
-                                               day = date.getDate();
-                                               break;
-                                       case "!":
-                                               date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
-                                               year = date.getFullYear();
-                                               month = date.getMonth() + 1;
-                                               day = date.getDate();
-                                               break;
-                                       case "'":
-                                               if (lookAhead("'")){
-                                                       checkLiteral();
-                                               } else {
-                                                       literal = true;
-                                               }
-                                               break;
-                                       default:
-                                               checkLiteral();
-                               }
-                       }
-               }
-
-               if (iValue < value.length){
-                       extra = value.substr(iValue);
-                       if (!/^\s+/.test(extra)) {
-                               throw "Extra/unparsed characters found in date: " + extra;
-                       }
-               }
-
-               if (year === -1) {
-                       year = new Date().getFullYear();
-               } else if (year < 100) {
-                       year += new Date().getFullYear() - new Date().getFullYear() % 100 +
-                               (year <= shortYearCutoff ? 0 : -100);
-               }
-
-               if (doy > -1) {
-                       month = 1;
-                       day = doy;
-                       do {
-                               dim = this._getDaysInMonth(year, month - 1);
-                               if (day <= dim) {
-                                       break;
-                               }
-                               month++;
-                               day -= dim;
-                       } while (true);
-               }
-
-               date = this._daylightSavingAdjust(new Date(year, month - 1, day));
-               if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
-                       throw "Invalid date"; // E.g. 31/02/00
-               }
-               return date;
-       },
-
-       /* Standard date formats. */
-       ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
-       COOKIE: "D, dd M yy",
-       ISO_8601: "yy-mm-dd",
-       RFC_822: "D, d M y",
-       RFC_850: "DD, dd-M-y",
-       RFC_1036: "D, d M y",
-       RFC_1123: "D, d M yy",
-       RFC_2822: "D, d M yy",
-       RSS: "D, d M y", // RFC 822
-       TICKS: "!",
-       TIMESTAMP: "@",
-       W3C: "yy-mm-dd", // ISO 8601
-
-       _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
-               Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
-
-       /* Format a date object into a string value.
-        * The format can be combinations of the following:
-        * d  - day of month (no leading zero)
-        * dd - day of month (two digit)
-        * o  - day of year (no leading zeros)
-        * oo - day of year (three digit)
-        * D  - day name short
-        * DD - day name long
-        * m  - month of year (no leading zero)
-        * mm - month of year (two digit)
-        * M  - month name short
-        * MM - month name long
-        * y  - year (two digit)
-        * yy - year (four digit)
-        * @ - Unix timestamp (ms since 01/01/1970)
-        * ! - Windows ticks (100ns since 01/01/0001)
-        * "..." - literal text
-        * '' - single quote
-        *
-        * @param  format string - the desired format of the date
-        * @param  date Date - the date value to format
-        * @param  settings Object - attributes include:
-        *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
-        *                                      dayNames                string[7] - names of the days from Sunday (optional)
-        *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
-        *                                      monthNames              string[12] - names of the months (optional)
-        * @return  string - the date in the above format
-        */
-       formatDate: function (format, date, settings) {
-               if (!date) {
-                       return "";
-               }
-
-               var iFormat,
-                       dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
-                       dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
-                       monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
-                       monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
-                       // Check whether a format character is doubled
-                       lookAhead = function(match) {
-                               var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
-                               if (matches) {
-                                       iFormat++;
-                               }
-                               return matches;
-                       },
-                       // Format a number, with leading zero if necessary
-                       formatNumber = function(match, value, len) {
-                               var num = "" + value;
-                               if (lookAhead(match)) {
-                                       while (num.length < len) {
-                                               num = "0" + num;
-                                       }
-                               }
-                               return num;
-                       },
-                       // Format a name, short or long as requested
-                       formatName = function(match, value, shortNames, longNames) {
-                               return (lookAhead(match) ? longNames[value] : shortNames[value]);
-                       },
-                       output = "",
-                       literal = false;
-
-               if (date) {
-                       for (iFormat = 0; iFormat < format.length; iFormat++) {
-                               if (literal) {
-                                       if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
-                                               literal = false;
-                                       } else {
-                                               output += format.charAt(iFormat);
-                                       }
-                               } else {
-                                       switch (format.charAt(iFormat)) {
-                                               case "d":
-                                                       output += formatNumber("d", date.getDate(), 2);
-                                                       break;
-                                               case "D":
-                                                       output += formatName("D", date.getDay(), dayNamesShort, dayNames);
-                                                       break;
-                                               case "o":
-                                                       output += formatNumber("o",
-                                                               Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
-                                                       break;
-                                               case "m":
-                                                       output += formatNumber("m", date.getMonth() + 1, 2);
-                                                       break;
-                                               case "M":
-                                                       output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
-                                                       break;
-                                               case "y":
-                                                       output += (lookAhead("y") ? date.getFullYear() :
-                                                               (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
-                                                       break;
-                                               case "@":
-                                                       output += date.getTime();
-                                                       break;
-                                               case "!":
-                                                       output += date.getTime() * 10000 + this._ticksTo1970;
-                                                       break;
-                                               case "'":
-                                                       if (lookAhead("'")) {
-                                                               output += "'";
-                                                       } else {
-                                                               literal = true;
-                                                       }
-                                                       break;
-                                               default:
-                                                       output += format.charAt(iFormat);
-                                       }
-                               }
-                       }
-               }
-               return output;
-       },
-
-       /* Extract all possible characters from the date format. */
-       _possibleChars: function (format) {
-               var iFormat,
-                       chars = "",
-                       literal = false,
-                       // Check whether a format character is doubled
-                       lookAhead = function(match) {
-                               var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
-                               if (matches) {
-                                       iFormat++;
-                               }
-                               return matches;
-                       };
-
-               for (iFormat = 0; iFormat < format.length; iFormat++) {
-                       if (literal) {
-                               if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
-                                       literal = false;
-                               } else {
-                                       chars += format.charAt(iFormat);
-                               }
-                       } else {
-                               switch (format.charAt(iFormat)) {
-                                       case "d": case "m": case "y": case "@":
-                                               chars += "0123456789";
-                                               break;
-                                       case "D": case "M":
-                                               return null; // Accept anything
-                                       case "'":
-                                               if (lookAhead("'")) {
-                                                       chars += "'";
-                                               } else {
-                                                       literal = true;
-                                               }
-                                               break;
-                                       default:
-                                               chars += format.charAt(iFormat);
-                               }
-                       }
-               }
-               return chars;
-       },
-
-       /* Get a setting value, defaulting if necessary. */
-       _get: function(inst, name) {
-               return inst.settings[name] !== undefined ?
-                       inst.settings[name] : this._defaults[name];
-       },
-
-       /* Parse existing date and initialise date picker. */
-       _setDateFromField: function(inst, noDefault) {
-               if (inst.input.val() === inst.lastVal) {
-                       return;
-               }
-
-               var dateFormat = this._get(inst, "dateFormat"),
-                       dates = inst.lastVal = inst.input ? inst.input.val() : null,
-                       defaultDate = this._getDefaultDate(inst),
-                       date = defaultDate,
-                       settings = this._getFormatConfig(inst);
-
-               try {
-                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
-               } catch (event) {
-                       dates = (noDefault ? "" : dates);
-               }
-               inst.selectedDay = date.getDate();
-               inst.drawMonth = inst.selectedMonth = date.getMonth();
-               inst.drawYear = inst.selectedYear = date.getFullYear();
-               inst.currentDay = (dates ? date.getDate() : 0);
-               inst.currentMonth = (dates ? date.getMonth() : 0);
-               inst.currentYear = (dates ? date.getFullYear() : 0);
-               this._adjustInstDate(inst);
-       },
-
-       /* Retrieve the default date shown on opening. */
-       _getDefaultDate: function(inst) {
-               return this._restrictMinMax(inst,
-                       this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
-       },
-
-       /* A date may be specified as an exact value or a relative one. */
-       _determineDate: function(inst, date, defaultDate) {
-               var offsetNumeric = function(offset) {
-                               var date = new Date();
-                               date.setDate(date.getDate() + offset);
-                               return date;
-                       },
-                       offsetString = function(offset) {
-                               try {
-                                       return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
-                                               offset, $.datepicker._getFormatConfig(inst));
-                               }
-                               catch (e) {
-                                       // Ignore
-                               }
-
-                               var date = (offset.toLowerCase().match(/^c/) ?
-                                       $.datepicker._getDate(inst) : null) || new Date(),
-                                       year = date.getFullYear(),
-                                       month = date.getMonth(),
-                                       day = date.getDate(),
-                                       pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
-                                       matches = pattern.exec(offset);
-
-                               while (matches) {
-                                       switch (matches[2] || "d") {
-                                               case "d" : case "D" :
-                                                       day += parseInt(matches[1],10); break;
-                                               case "w" : case "W" :
-                                                       day += parseInt(matches[1],10) * 7; break;
-                                               case "m" : case "M" :
-                                                       month += parseInt(matches[1],10);
-                                                       day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-                                                       break;
-                                               case "y": case "Y" :
-                                                       year += parseInt(matches[1],10);
-                                                       day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-                                                       break;
-                                       }
-                                       matches = pattern.exec(offset);
-                               }
-                               return new Date(year, month, day);
-                       },
-                       newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
-                               (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
-
-               newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
-               if (newDate) {
-                       newDate.setHours(0);
-                       newDate.setMinutes(0);
-                       newDate.setSeconds(0);
-                       newDate.setMilliseconds(0);
-               }
-               return this._daylightSavingAdjust(newDate);
-       },
-
-       /* Handle switch to/from daylight saving.
-        * Hours may be non-zero on daylight saving cut-over:
-        * > 12 when midnight changeover, but then cannot generate
-        * midnight datetime, so jump to 1AM, otherwise reset.
-        * @param  date  (Date) the date to check
-        * @return  (Date) the corrected date
-        */
-       _daylightSavingAdjust: function(date) {
-               if (!date) {
-                       return null;
-               }
-               date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
-               return date;
-       },
-
-       /* Set the date(s) directly. */
-       _setDate: function(inst, date, noChange) {
-               var clear = !date,
-                       origMonth = inst.selectedMonth,
-                       origYear = inst.selectedYear,
-                       newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
-
-               inst.selectedDay = inst.currentDay = newDate.getDate();
-               inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
-               inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
-               if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
-                       this._notifyChange(inst);
-               }
-               this._adjustInstDate(inst);
-               if (inst.input) {
-                       inst.input.val(clear ? "" : this._formatDate(inst));
-               }
-       },
-
-       /* Retrieve the date(s) directly. */
-       _getDate: function(inst) {
-               var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
-                       this._daylightSavingAdjust(new Date(
-                       inst.currentYear, inst.currentMonth, inst.currentDay)));
-                       return startDate;
-       },
-
-       /* Attach the onxxx handlers.  These are declared statically so
-        * they work with static code transformers like Caja.
-        */
-       _attachHandlers: function(inst) {
-               var stepMonths = this._get(inst, "stepMonths"),
-                       id = "#" + inst.id.replace( /\\\\/g, "\\" );
-               inst.dpDiv.find("[data-handler]").map(function () {
-                       var handler = {
-                               prev: function () {
-                                       $.datepicker._adjustDate(id, -stepMonths, "M");
-                               },
-                               next: function () {
-                                       $.datepicker._adjustDate(id, +stepMonths, "M");
-                               },
-                               hide: function () {
-                                       $.datepicker._hideDatepicker();
-                               },
-                               today: function () {
-                                       $.datepicker._gotoToday(id);
-                               },
-                               selectDay: function () {
-                                       $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
-                                       return false;
-                               },
-                               selectMonth: function () {
-                                       $.datepicker._selectMonthYear(id, this, "M");
-                                       return false;
-                               },
-                               selectYear: function () {
-                                       $.datepicker._selectMonthYear(id, this, "Y");
-                                       return false;
-                               }
-                       };
-                       $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
-               });
-       },
-
-       /* Generate the HTML for the current state of the date picker. */
-       _generateHTML: function(inst) {
-               var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
-                       controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
-                       monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
-                       selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
-                       cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
-                       printDate, dRow, tbody, daySettings, otherMonth, unselectable,
-                       tempDate = new Date(),
-                       today = this._daylightSavingAdjust(
-                               new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
-                       isRTL = this._get(inst, "isRTL"),
-                       showButtonPanel = this._get(inst, "showButtonPanel"),
-                       hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
-                       navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
-                       numMonths = this._getNumberOfMonths(inst),
-                       showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
-                       stepMonths = this._get(inst, "stepMonths"),
-                       isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
-                       currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
-                               new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
-                       minDate = this._getMinMaxDate(inst, "min"),
-                       maxDate = this._getMinMaxDate(inst, "max"),
-                       drawMonth = inst.drawMonth - showCurrentAtPos,
-                       drawYear = inst.drawYear;
-
-               if (drawMonth < 0) {
-                       drawMonth += 12;
-                       drawYear--;
-               }
-               if (maxDate) {
-                       maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
-                               maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
-                       maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
-                       while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
-                               drawMonth--;
-                               if (drawMonth < 0) {
-                                       drawMonth = 11;
-                                       drawYear--;
-                               }
-                       }
-               }
-               inst.drawMonth = drawMonth;
-               inst.drawYear = drawYear;
-
-               prevText = this._get(inst, "prevText");
-               prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
-                       this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
-                       this._getFormatConfig(inst)));
-
-               prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
-                       "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
-                       " title='" + t(prevText) + "'><i class='icon-arrow-" + ( isRTL ? "right" : "left") + "'></i> " + t(prevText) + "</a>" :
-                       (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ t(prevText) +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + t(prevText) + "</span></a>"));
-
-               nextText = this._get(inst, "nextText");
-               nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
-                       this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
-                       this._getFormatConfig(inst)));
-
-               next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
-                       "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
-                       " title='" + t(nextText) + "'>" + t(nextText) + " <i class='icon-arrow-" + ( isRTL ? "left" : "right") + "'></i></a>" :
-                       (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ t(nextText) + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + t(nextText) + "</span></a>"));
-
-               currentText = this._get(inst, "currentText");
-               gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
-               currentText = (!navigationAsDateFormat ? currentText :
-                       this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
-
-               controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
-                       this._get(inst, "closeText") + "</button>" : "");
-
-               buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
-                       (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
-                       ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
-
-               firstDay = parseInt(this._get(inst, "firstDay"),10);
-               firstDay = (isNaN(firstDay) ? 0 : firstDay);
-
-               showWeek = this._get(inst, "showWeek");
-               dayNames = this._get(inst, "dayNames");
-               dayNamesMin = this._get(inst, "dayNamesMin");
-               monthNames = this._get(inst, "monthNames");
-               monthNamesShort = this._get(inst, "monthNamesShort");
-               beforeShowDay = this._get(inst, "beforeShowDay");
-               showOtherMonths = this._get(inst, "showOtherMonths");
-               selectOtherMonths = this._get(inst, "selectOtherMonths");
-               defaultDate = this._getDefaultDate(inst);
-               html = "";
-               dow;
-               for (row = 0; row < numMonths[0]; row++) {
-                       group = "";
-                       this.maxRows = 4;
-                       for (col = 0; col < numMonths[1]; col++) {
-                               selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
-                               cornerClass = " ui-corner-all";
-                               calender = "";
-                               if (isMultiMonth) {
-                                       calender += "<div class='ui-datepicker-group";
-                                       if (numMonths[1] > 1) {
-                                               switch (col) {
-                                                       case 0: calender += " ui-datepicker-group-first";
-                                                               cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
-                                                       case numMonths[1]-1: calender += " ui-datepicker-group-last";
-                                                               cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
-                                                       default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
-                                               }
-                                       }
-                                       calender += "'>";
-                               }
-                               calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
-                                       (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
-                                       (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
-                                       this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
-                                       row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
-                                       "</div><table class='ui-datepicker-calendar'><thead>" +
-                                       "<tr>";
-                               thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
-                               for (dow = 0; dow < 7; dow++) { // days of the week
-                                       day = (dow + firstDay) % 7;
-                                       thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
-                                               "<span title='" + t(dayNames[day]) + "'>" + t(dayNamesMin[day]) + "</span></th>";
-                               }
-                               calender += thead + "</tr></thead><tbody>";
-                               daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
-                               if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
-                                       inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
-                               }
-                               leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
-                               curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
-                               numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
-                               this.maxRows = numRows;
-                               printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
-                               for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
-                                       calender += "<tr>";
-                                       tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
-                                               this._get(inst, "calculateWeek")(printDate) + "</td>");
-                                       for (dow = 0; dow < 7; dow++) { // create date picker days
-                                               daySettings = (beforeShowDay ?
-                                                       beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
-                                               otherMonth = (printDate.getMonth() !== drawMonth);
-                                               unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
-                                                       (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
-                                               tbody += "<td class='" +
-                                                       ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
-                                                       (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
-                                                       ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
-                                                       (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
-                                                       // or defaultDate is current printedDate and defaultDate is selectedDate
-                                                       " " + this._dayOverClass : "") + // highlight selected day
-                                                       (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
-                                                       (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
-                                                       (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
-                                                       (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
-                                                       ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
-                                                       (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
-                                                       (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
-                                                       (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
-                                                       (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
-                                                       (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
-                                                       (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
-                                                       "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
-                                               printDate.setDate(printDate.getDate() + 1);
-                                               printDate = this._daylightSavingAdjust(printDate);
-                                       }
-                                       calender += tbody + "</tr>";
-                               }
-                               drawMonth++;
-                               if (drawMonth > 11) {
-                                       drawMonth = 0;
-                                       drawYear++;
-                               }
-                               calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
-                                                       ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
-                               group += calender;
-                       }
-                       html += group;
-               }
-               html += buttonPanel;
-               inst._keyEvent = false;
-               return html;
-       },
-
-       /* Generate the month and year header. */
-       _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
-                       secondary, monthNames, monthNamesShort) {
-
-               var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
-                       changeMonth = this._get(inst, "changeMonth"),
-                       changeYear = this._get(inst, "changeYear"),
-                       showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
-                       html = "<div class='ui-datepicker-title'>",
-                       monthHtml = "";
-
-               // month selection
-               if (secondary || !changeMonth) {
-                       monthHtml += "<span class='ui-datepicker-month'>" + t(monthNames[drawMonth]) + "</span>";
-               } else {
-                       inMinYear = (minDate && minDate.getFullYear() === drawYear);
-                       inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
-                       monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
-                       for ( month = 0; month < 12; month++) {
-                               if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
-                                       monthHtml += "<option value='" + month + "'" +
-                                               (month === drawMonth ? " selected='selected'" : "") +
-                                               ">" + t(monthNamesShort[month]) + "</option>";
-                               }
-                       }
-                       monthHtml += "</select>";
-               }
-
-               if (!showMonthAfterYear) {
-                       html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
-               }
-
-               // year selection
-               if ( !inst.yearshtml ) {
-                       inst.yearshtml = "";
-                       if (secondary || !changeYear) {
-                               html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
-                       } else {
-                               // determine range of years to display
-                               years = this._get(inst, "yearRange").split(":");
-                               thisYear = new Date().getFullYear();
-                               determineYear = function(value) {
-                                       var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
-                                               (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
-                                               parseInt(value, 10)));
-                                       return (isNaN(year) ? thisYear : year);
-                               };
-                               year = determineYear(years[0]);
-                               endYear = Math.max(year, determineYear(years[1] || ""));
-                               year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
-                               endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
-                               inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
-                               for (; year <= endYear; year++) {
-                                       inst.yearshtml += "<option value='" + year + "'" +
-                                               (year === drawYear ? " selected='selected'" : "") +
-                                               ">" + year + "</option>";
-                               }
-                               inst.yearshtml += "</select>";
-
-                               html += inst.yearshtml;
-                               inst.yearshtml = null;
-                       }
-               }
-
-               html += this._get(inst, "yearSuffix");
-               if (showMonthAfterYear) {
-                       html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
-               }
-               html += "</div>"; // Close datepicker_header
-               return html;
-       },
-
-       /* Adjust one of the date sub-fields. */
-       _adjustInstDate: function(inst, offset, period) {
-               var year = inst.drawYear + (period === "Y" ? offset : 0),
-                       month = inst.drawMonth + (period === "M" ? offset : 0),
-                       day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
-                       date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
-
-               inst.selectedDay = date.getDate();
-               inst.drawMonth = inst.selectedMonth = date.getMonth();
-               inst.drawYear = inst.selectedYear = date.getFullYear();
-               if (period === "M" || period === "Y") {
-                       this._notifyChange(inst);
-               }
-       },
-
-       /* Ensure a date is within any min/max bounds. */
-       _restrictMinMax: function(inst, date) {
-               var minDate = this._getMinMaxDate(inst, "min"),
-                       maxDate = this._getMinMaxDate(inst, "max"),
-                       newDate = (minDate && date < minDate ? minDate : date);
-               return (maxDate && newDate > maxDate ? maxDate : newDate);
-       },
-
-       /* Notify change of month/year. */
-       _notifyChange: function(inst) {
-               var onChange = this._get(inst, "onChangeMonthYear");
-               if (onChange) {
-                       onChange.apply((inst.input ? inst.input[0] : null),
-                               [inst.selectedYear, inst.selectedMonth + 1, inst]);
-               }
-       },
-
-       /* Determine the number of months to show. */
-       _getNumberOfMonths: function(inst) {
-               var numMonths = this._get(inst, "numberOfMonths");
-               return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
-       },
-
-       /* Determine the current maximum date - ensure no time components are set. */
-       _getMinMaxDate: function(inst, minMax) {
-               return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
-       },
-
-       /* Find the number of days in a given month. */
-       _getDaysInMonth: function(year, month) {
-               return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
-       },
-
-       /* Find the day of the week of the first of a month. */
-       _getFirstDayOfMonth: function(year, month) {
-               return new Date(year, month, 1).getDay();
-       },
-
-       /* Determines if we should allow a "next/prev" month display change. */
-       _canAdjustMonth: function(inst, offset, curYear, curMonth) {
-               var numMonths = this._getNumberOfMonths(inst),
-                       date = this._daylightSavingAdjust(new Date(curYear,
-                       curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
-
-               if (offset < 0) {
-                       date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
-               }
-               return this._isInRange(inst, date);
-       },
-
-       /* Is the given date in the accepted range? */
-       _isInRange: function(inst, date) {
-               var yearSplit, currentYear,
-                       minDate = this._getMinMaxDate(inst, "min"),
-                       maxDate = this._getMinMaxDate(inst, "max"),
-                       minYear = null,
-                       maxYear = null,
-                       years = this._get(inst, "yearRange");
-                       if (years){
-                               yearSplit = years.split(":");
-                               currentYear = new Date().getFullYear();
-                               minYear = parseInt(yearSplit[0], 10);
-                               maxYear = parseInt(yearSplit[1], 10);
-                               if ( yearSplit[0].match(/[+\-].*/) ) {
-                                       minYear += currentYear;
-                               }
-                               if ( yearSplit[1].match(/[+\-].*/) ) {
-                                       maxYear += currentYear;
-                               }
-                       }
-
-               return ((!minDate || date.getTime() >= minDate.getTime()) &&
-                       (!maxDate || date.getTime() <= maxDate.getTime()) &&
-                       (!minYear || date.getFullYear() >= minYear) &&
-                       (!maxYear || date.getFullYear() <= maxYear));
-       },
-
-       /* Provide the configuration settings for formatting/parsing. */
-       _getFormatConfig: function(inst) {
-               var shortYearCutoff = this._get(inst, "shortYearCutoff");
-               shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
-                       new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
-               return {shortYearCutoff: shortYearCutoff,
-                       dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
-                       monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
-       },
-
-       /* Format the given date for display. */
-       _formatDate: function(inst, day, month, year) {
-               if (!day) {
-                       inst.currentDay = inst.selectedDay;
-                       inst.currentMonth = inst.selectedMonth;
-                       inst.currentYear = inst.selectedYear;
-               }
-               var date = (day ? (typeof day === "object" ? day :
-                       this._daylightSavingAdjust(new Date(year, month, day))) :
-                       this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
-               return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
-       }
-});
-
-/*
- * Bind hover events for datepicker elements.
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
- * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
- */
-function bindHover(dpDiv) {
-       var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
-       return dpDiv.delegate(selector, "mouseout", function() {
-                       $(this).removeClass("ui-state-hover");
-                       if (this.className.indexOf("ui-datepicker-prev") !== -1) {
-                               $(this).removeClass("ui-datepicker-prev-hover");
-                       }
-                       if (this.className.indexOf("ui-datepicker-next") !== -1) {
-                               $(this).removeClass("ui-datepicker-next-hover");
-                       }
-               })
-               .delegate(selector, "mouseover", function(){
-                       if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
-                               $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
-                               $(this).addClass("ui-state-hover");
-                               if (this.className.indexOf("ui-datepicker-prev") !== -1) {
-                                       $(this).addClass("ui-datepicker-prev-hover");
-                               }
-                               if (this.className.indexOf("ui-datepicker-next") !== -1) {
-                                       $(this).addClass("ui-datepicker-next-hover");
-                               }
-                       }
-               });
-}
-
-/* jQuery extend now ignores nulls! */
-function extendRemove(target, props) {
-       $.extend(target, props);
-       for (var name in props) {
-               if (props[name] == null) {
-                       target[name] = props[name];
-               }
-       }
-       return target;
-}
-
-/* Invoke the datepicker functionality.
-   @param  options  string - a command, optionally followed by additional parameters or
-                                       Object - settings for attaching new datepicker functionality
-   @return  jQuery object */
-$.fn.datepicker = function(options){
-
-       /* Verify an empty collection wasn't passed - Fixes #6976 */
-       if ( !this.length ) {
-               return this;
-       }
-
-       /* Initialise the date picker. */
-       if (!$.datepicker.initialized) {
-               $(document).mousedown($.datepicker._checkExternalClick);
-               $.datepicker.initialized = true;
-       }
-
-       /* Append datepicker main container to body if not exist. */
-       if ($("#"+$.datepicker._mainDivId).length === 0) {
-               $("body").append($.datepicker.dpDiv);
-       }
-
-       var otherArgs = Array.prototype.slice.call(arguments, 1);
-       if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
-               return $.datepicker["_" + options + "Datepicker"].
-                       apply($.datepicker, [this[0]].concat(otherArgs));
-       }
-       if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
-               return $.datepicker["_" + options + "Datepicker"].
-                       apply($.datepicker, [this[0]].concat(otherArgs));
-       }
-       return this.each(function() {
-               typeof options === "string" ?
-                       $.datepicker["_" + options + "Datepicker"].
-                               apply($.datepicker, [this].concat(otherArgs)) :
-                       $.datepicker._attachDatepicker(this, options);
-       });
-};
-
-$.datepicker = new Datepicker(); // singleton instance
-$.datepicker.initialized = false;
-$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.10.4";
-
-})(jQuery);
-(function( $, undefined ) {
-
-var sizeRelatedOptions = {
-               buttons: true,
-               height: true,
-               maxHeight: true,
-               maxWidth: true,
-               minHeight: true,
-               minWidth: true,
-               width: true
-       },
-       resizableRelatedOptions = {
-               maxHeight: true,
-               maxWidth: true,
-               minHeight: true,
-               minWidth: true
-       };
-
-$.widget( "ui.dialog", {
-       version: "1.10.4",
-       options: {
-               appendTo: "body",
-               autoOpen: true,
-               buttons: [],
-               closeOnEscape: true,
-               closeText: "close",
-               dialogClass: "",
-               draggable: true,
-               hide: null,
-               height: "auto",
-               maxHeight: null,
-               maxWidth: null,
-               minHeight: 150,
-               minWidth: 150,
-               modal: false,
-               position: {
-                       my: "center",
-                       at: "center",
-                       of: window,
-                       collision: "fit",
-                       // Ensure the titlebar is always visible
-                       using: function( pos ) {
-                               var topOffset = $( this ).css( pos ).offset().top;
-                               if ( topOffset < 0 ) {
-                                       $( this ).css( "top", pos.top - topOffset );
-                               }
-                       }
-               },
-               resizable: true,
-               show: null,
-               title: null,
-               width: 300,
-
-               // callbacks
-               beforeClose: null,
-               close: null,
-               drag: null,
-               dragStart: null,
-               dragStop: null,
-               focus: null,
-               open: null,
-               resize: null,
-               resizeStart: null,
-               resizeStop: null
-       },
-
-       _create: function() {
-               this.originalCss = {
-                       display: this.element[0].style.display,
-                       width: this.element[0].style.width,
-                       minHeight: this.element[0].style.minHeight,
-                       maxHeight: this.element[0].style.maxHeight,
-                       height: this.element[0].style.height
-               };
-               this.originalPosition = {
-                       parent: this.element.parent(),
-                       index: this.element.parent().children().index( this.element )
-               };
-               this.originalTitle = this.element.attr("title");
-               this.options.title = this.options.title || this.originalTitle;
-
-               this._createWrapper();
-
-               this.element
-                       .show()
-                       .removeAttr("title")
-                       .addClass("ui-dialog-content ui-widget-content")
-                       .appendTo( this.uiDialog );
-
-               this._createTitlebar();
-               this._createButtonPane();
-
-               if ( this.options.draggable && $.fn.draggable ) {
-                       this._makeDraggable();
-               }
-               if ( this.options.resizable && $.fn.resizable ) {
-                       this._makeResizable();
-               }
-
-               this._isOpen = false;
-       },
-
-       _init: function() {
-               if ( this.options.autoOpen ) {
-                       this.open();
-               }
-       },
-
-       _appendTo: function() {
-               var element = this.options.appendTo;
-               if ( element && (element.jquery || element.nodeType) ) {
-                       return $( element );
-               }
-               return this.document.find( element || "body" ).eq( 0 );
-       },
-
-       _destroy: function() {
-               var next,
-                       originalPosition = this.originalPosition;
-
-               this._destroyOverlay();
-
-               this.element
-                       .removeUniqueId()
-                       .removeClass("ui-dialog-content ui-widget-content")
-                       .css( this.originalCss )
-                       // Without detaching first, the following becomes really slow
-                       .detach();
-
-               this.uiDialog.stop( true, true ).remove();
-
-               if ( this.originalTitle ) {
-                       this.element.attr( "title", this.originalTitle );
-               }
-
-               next = originalPosition.parent.children().eq( originalPosition.index );
-               // Don't try to place the dialog next to itself (#8613)
-               if ( next.length && next[0] !== this.element[0] ) {
-                       next.before( this.element );
-               } else {
-                       originalPosition.parent.append( this.element );
-               }
-       },
-
-       widget: function() {
-               return this.uiDialog;
-       },
-
-       disable: $.noop,
-       enable: $.noop,
-
-       close: function( event ) {
-               var activeElement,
-                       that = this;
-
-               if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
-                       return;
-               }
-
-               this._isOpen = false;
-               this._destroyOverlay();
-
-               if ( !this.opener.filter(":focusable").focus().length ) {
-
-                       // support: IE9
-                       // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
-                       try {
-                               activeElement = this.document[ 0 ].activeElement;
-
-                               // Support: IE9, IE10
-                               // If the <body> is blurred, IE will switch windows, see #4520
-                               if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
-
-                                       // Hiding a focused element doesn't trigger blur in WebKit
-                                       // so in case we have nothing to focus on, explicitly blur the active element
-                                       // https://bugs.webkit.org/show_bug.cgi?id=47182
-                                       $( activeElement ).blur();
-                               }
-                       } catch ( error ) {}
-               }
-
-               this._hide( this.uiDialog, this.options.hide, function() {
-                       that._trigger( "close", event );
-               });
-       },
-
-       isOpen: function() {
-               return this._isOpen;
-       },
-
-       moveToTop: function() {
-               this._moveToTop();
-       },
-
-       _moveToTop: function( event, silent ) {
-               var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
-               if ( moved && !silent ) {
-                       this._trigger( "focus", event );
-               }
-               return moved;
-       },
-
-       open: function() {
-               var that = this;
-               if ( this._isOpen ) {
-                       if ( this._moveToTop() ) {
-                               this._focusTabbable();
-                       }
-                       return;
-               }
-
-               this._isOpen = true;
-               this.opener = $( this.document[0].activeElement );
-
-               this._size();
-               this._position();
-               this._createOverlay();
-               this._moveToTop( null, true );
-               this._show( this.uiDialog, this.options.show, function() {
-                       that._focusTabbable();
-                       that._trigger("focus");
-               });
-
-               this._trigger("open");
-       },
-
-       _focusTabbable: function() {
-               // Set focus to the first match:
-               // 1. First element inside the dialog matching [autofocus]
-               // 2. Tabbable element inside the content element
-               // 3. Tabbable element inside the buttonpane
-               // 4. The close button
-               // 5. The dialog itself
-               var hasFocus = this.element.find("[autofocus]");
-               if ( !hasFocus.length ) {
-                       hasFocus = this.element.find(":tabbable");
-               }
-               if ( !hasFocus.length ) {
-                       hasFocus = this.uiDialogButtonPane.find(":tabbable");
-               }
-               if ( !hasFocus.length ) {
-                       hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
-               }
-               if ( !hasFocus.length ) {
-                       hasFocus = this.uiDialog;
-               }
-               hasFocus.eq( 0 ).focus();
-       },
-
-       _keepFocus: function( event ) {
-               function checkFocus() {
-                       var activeElement = this.document[0].activeElement,
-                               isActive = this.uiDialog[0] === activeElement ||
-                                       $.contains( this.uiDialog[0], activeElement );
-                       if ( !isActive ) {
-                               this._focusTabbable();
-                       }
-               }
-               event.preventDefault();
-               checkFocus.call( this );
-               // support: IE
-               // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
-               // so we check again later
-               this._delay( checkFocus );
-       },
-
-       _createWrapper: function() {
-               this.uiDialog = $("<div>")
-                       .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
-                               this.options.dialogClass )
-                       .hide()
-                       .attr({
-                               // Setting tabIndex makes the div focusable
-                               tabIndex: -1,
-                               role: "dialog"
-                       })
-                       .appendTo( this._appendTo() );
-
-               this._on( this.uiDialog, {
-                       keydown: function( event ) {
-                               if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
-                                               event.keyCode === $.ui.keyCode.ESCAPE ) {
-                                       event.preventDefault();
-                                       this.close( event );
-                                       return;
-                               }
-
-                               // prevent tabbing out of dialogs
-                               if ( event.keyCode !== $.ui.keyCode.TAB ) {
-                                       return;
-                               }
-                               var tabbables = this.uiDialog.find(":tabbable"),
-                                       first = tabbables.filter(":first"),
-                                       last  = tabbables.filter(":last");
-
-                               if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
-                                       first.focus( 1 );
-                                       event.preventDefault();
-                               } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
-                                       last.focus( 1 );
-                                       event.preventDefault();
-                               }
-                       },
-                       mousedown: function( event ) {
-                               if ( this._moveToTop( event ) ) {
-                                       this._focusTabbable();
-                               }
-                       }
-               });
-
-               // We assume that any existing aria-describedby attribute means
-               // that the dialog content is marked up properly
-               // otherwise we brute force the content as the description
-               if ( !this.element.find("[aria-describedby]").length ) {
-                       this.uiDialog.attr({
-                               "aria-describedby": this.element.uniqueId().attr("id")
-                       });
-               }
-       },
-
-       _createTitlebar: function() {
-               var uiDialogTitle;
-
-               this.uiDialogTitlebar = $("<div>")
-                       .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
-                       .prependTo( this.uiDialog );
-               this._on( this.uiDialogTitlebar, {
-                       mousedown: function( event ) {
-                               // Don't prevent click on close button (#8838)
-                               // Focusing a dialog that is partially scrolled out of view
-                               // causes the browser to scroll it into view, preventing the click event
-                               if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
-                                       // Dialog isn't getting focus when dragging (#8063)
-                                       this.uiDialog.focus();
-                               }
-                       }
-               });
-
-               // support: IE
-               // Use type="button" to prevent enter keypresses in textboxes from closing the
-               // dialog in IE (#9312)
-               this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
-                       .button({
-                               label: this.options.closeText,
-                               icons: {
-                                       primary: "ui-icon-closethick"
-                               },
-                               text: false
-                       })
-                       .addClass("ui-dialog-titlebar-close")
-                       .appendTo( this.uiDialogTitlebar );
-               this._on( this.uiDialogTitlebarClose, {
-                       click: function( event ) {
-                               event.preventDefault();
-                               this.close( event );
-                       }
-               });
-
-               uiDialogTitle = $("<span>")
-                       .uniqueId()
-                       .addClass("ui-dialog-title")
-                       .prependTo( this.uiDialogTitlebar );
-               this._title( uiDialogTitle );
-
-               this.uiDialog.attr({
-                       "aria-labelledby": uiDialogTitle.attr("id")
-               });
-       },
-
-       _title: function( title ) {
-               if ( !this.options.title ) {
-                       title.html("&#160;");
-               }
-               title.text( this.options.title );
-       },
-
-       _createButtonPane: function() {
-               this.uiDialogButtonPane = $("<div>")
-                       .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
-
-               this.uiButtonSet = $("<div>")
-                       .addClass("ui-dialog-buttonset")
-                       .appendTo( this.uiDialogButtonPane );
-
-               this._createButtons();
-       },
-
-       _createButtons: function() {
-               var that = this,
-                       buttons = this.options.buttons;
-
-               // if we already have a button pane, remove it
-               this.uiDialogButtonPane.remove();
-               this.uiButtonSet.empty();
-
-               if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
-                       this.uiDialog.removeClass("ui-dialog-buttons");
-                       return;
-               }
-
-               $.each( buttons, function( name, props ) {
-                       var click, buttonOptions;
-                       props = $.isFunction( props ) ?
-                               { click: props, text: name } :
-                               props;
-                       // Default to a non-submitting button
-                       props = $.extend( { type: "button" }, props );
-                       // Change the context for the click callback to be the main element
-                       click = props.click;
-                       props.click = function() {
-                               click.apply( that.element[0], arguments );
-                       };
-                       buttonOptions = {
-                               icons: props.icons,
-                               text: props.showText
-                       };
-                       delete props.icons;
-                       delete props.showText;
-                       $( "<button></button>", props )
-                               .button( buttonOptions )
-                               .appendTo( that.uiButtonSet );
-               });
-               this.uiDialog.addClass("ui-dialog-buttons");
-               this.uiDialogButtonPane.appendTo( this.uiDialog );
-       },
-
-       _makeDraggable: function() {
-               var that = this,
-                       options = this.options;
-
-               function filteredUi( ui ) {
-                       return {
-                               position: ui.position,
-                               offset: ui.offset
-                       };
-               }
-
-               this.uiDialog.draggable({
-                       cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
-                       handle: ".ui-dialog-titlebar",
-                       containment: "document",
-                       start: function( event, ui ) {
-                               $( this ).addClass("ui-dialog-dragging");
-                               that._blockFrames();
-                               that._trigger( "dragStart", event, filteredUi( ui ) );
-                       },
-                       drag: function( event, ui ) {
-                               that._trigger( "drag", event, filteredUi( ui ) );
-                       },
-                       stop: function( event, ui ) {
-                               options.position = [
-                                       ui.position.left - that.document.scrollLeft(),
-                                       ui.position.top - that.document.scrollTop()
-                               ];
-                               $( this ).removeClass("ui-dialog-dragging");
-                               that._unblockFrames();
-                               that._trigger( "dragStop", event, filteredUi( ui ) );
-                       }
-               });
-       },
-
-       _makeResizable: function() {
-               var that = this,
-                       options = this.options,
-                       handles = options.resizable,
-                       // .ui-resizable has position: relative defined in the stylesheet
-                       // but dialogs have to use absolute or fixed positioning
-                       position = this.uiDialog.css("position"),
-                       resizeHandles = typeof handles === "string" ?
-                               handles :
-                               "n,e,s,w,se,sw,ne,nw";
-
-               function filteredUi( ui ) {
-                       return {
-                               originalPosition: ui.originalPosition,
-                               originalSize: ui.originalSize,
-                               position: ui.position,
-                               size: ui.size
-                       };
-               }
-
-               this.uiDialog.resizable({
-                       cancel: ".ui-dialog-content",
-                       containment: "document",
-                       alsoResize: this.element,
-                       maxWidth: options.maxWidth,
-                       maxHeight: options.maxHeight,
-                       minWidth: options.minWidth,
-                       minHeight: this._minHeight(),
-                       handles: resizeHandles,
-                       start: function( event, ui ) {
-                               $( this ).addClass("ui-dialog-resizing");
-                               that._blockFrames();
-                               that._trigger( "resizeStart", event, filteredUi( ui ) );
-                       },
-                       resize: function( event, ui ) {
-                               that._trigger( "resize", event, filteredUi( ui ) );
-                       },
-                       stop: function( event, ui ) {
-                               options.height = $( this ).height();
-                               options.width = $( this ).width();
-                               $( this ).removeClass("ui-dialog-resizing");
-                               that._unblockFrames();
-                               that._trigger( "resizeStop", event, filteredUi( ui ) );
-                       }
-               })
-               .css( "position", position );
-       },
-
-       _minHeight: function() {
-               var options = this.options;
-
-               return options.height === "auto" ?
-                       options.minHeight :
-                       Math.min( options.minHeight, options.height );
-       },
-
-       _position: function() {
-               // Need to show the dialog to get the actual offset in the position plugin
-               var isVisible = this.uiDialog.is(":visible");
-               if ( !isVisible ) {
-                       this.uiDialog.show();
-               }
-               this.uiDialog.position( this.options.position );
-               if ( !isVisible ) {
-                       this.uiDialog.hide();
-               }
-       },
-
-       _setOptions: function( options ) {
-               var that = this,
-                       resize = false,
-                       resizableOptions = {};
-
-               $.each( options, function( key, value ) {
-                       that._setOption( key, value );
-
-                       if ( key in sizeRelatedOptions ) {
-                               resize = true;
-                       }
-                       if ( key in resizableRelatedOptions ) {
-                               resizableOptions[ key ] = value;
-                       }
-               });
-
-               if ( resize ) {
-                       this._size();
-                       this._position();
-               }
-               if ( this.uiDialog.is(":data(ui-resizable)") ) {
-                       this.uiDialog.resizable( "option", resizableOptions );
-               }
-       },
-
-       _setOption: function( key, value ) {
-               var isDraggable, isResizable,
-                       uiDialog = this.uiDialog;
-
-               if ( key === "dialogClass" ) {
-                       uiDialog
-                               .removeClass( this.options.dialogClass )
-                               .addClass( value );
-               }
-
-               if ( key === "disabled" ) {
-                       return;
-               }
-
-               this._super( key, value );
-
-               if ( key === "appendTo" ) {
-                       this.uiDialog.appendTo( this._appendTo() );
-               }
-
-               if ( key === "buttons" ) {
-                       this._createButtons();
-               }
-
-               if ( key === "closeText" ) {
-                       this.uiDialogTitlebarClose.button({
-                               // Ensure that we always pass a string
-                               label: "" + value
-                       });
-               }
-
-               if ( key === "draggable" ) {
-                       isDraggable = uiDialog.is(":data(ui-draggable)");
-                       if ( isDraggable && !value ) {
-                               uiDialog.draggable("destroy");
-                       }
-
-                       if ( !isDraggable && value ) {
-                               this._makeDraggable();
-                       }
-               }
-
-               if ( key === "position" ) {
-                       this._position();
-               }
-
-               if ( key === "resizable" ) {
-                       // currently resizable, becoming non-resizable
-                       isResizable = uiDialog.is(":data(ui-resizable)");
-                       if ( isResizable && !value ) {
-                               uiDialog.resizable("destroy");
-                       }
-
-                       // currently resizable, changing handles
-                       if ( isResizable && typeof value === "string" ) {
-                               uiDialog.resizable( "option", "handles", value );
-                       }
-
-                       // currently non-resizable, becoming resizable
-                       if ( !isResizable && value !== false ) {
-                               this._makeResizable();
-                       }
-               }
-
-               if ( key === "title" ) {
-                       this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
-               }
-       },
-
-       _size: function() {
-               // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
-               // divs will both have width and height set, so we need to reset them
-               var nonContentHeight, minContentHeight, maxContentHeight,
-                       options = this.options;
-
-               // Reset content sizing
-               this.element.show().css({
-                       width: "auto",
-                       minHeight: 0,
-                       maxHeight: "none",
-                       height: 0
-               });
-
-               if ( options.minWidth > options.width ) {
-                       options.width = options.minWidth;
-               }
-
-               // reset wrapper sizing
-               // determine the height of all the non-content elements
-               nonContentHeight = this.uiDialog.css({
-                               height: "auto",
-                               width: options.width
-                       })
-                       .outerHeight();
-               minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
-               maxContentHeight = typeof options.maxHeight === "number" ?
-                       Math.max( 0, options.maxHeight - nonContentHeight ) :
-                       "none";
-
-               if ( options.height === "auto" ) {
-                       this.element.css({
-                               minHeight: minContentHeight,
-                               maxHeight: maxContentHeight,
-                               height: "auto"
-                       });
-               } else {
-                       this.element.height( Math.max( 0, options.height - nonContentHeight ) );
-               }
-
-               if (this.uiDialog.is(":data(ui-resizable)") ) {
-                       this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
-               }
-       },
-
-       _blockFrames: function() {
-               this.iframeBlocks = this.document.find( "iframe" ).map(function() {
-                       var iframe = $( this );
-
-                       return $( "<div>" )
-                               .css({
-                                       position: "absolute",
-                                       width: iframe.outerWidth(),
-                                       height: iframe.outerHeight()
-                               })
-                               .appendTo( iframe.parent() )
-                               .offset( iframe.offset() )[0];
-               });
-       },
-
-       _unblockFrames: function() {
-               if ( this.iframeBlocks ) {
-                       this.iframeBlocks.remove();
-                       delete this.iframeBlocks;
-               }
-       },
-
-       _allowInteraction: function( event ) {
-               if ( $( event.target ).closest(".ui-dialog").length ) {
-                       return true;
-               }
-
-               // TODO: Remove hack when datepicker implements
-               // the .ui-front logic (#8989)
-               return !!$( event.target ).closest(".ui-datepicker").length;
-       },
-
-       _createOverlay: function() {
-               if ( !this.options.modal ) {
-                       return;
-               }
-
-               var that = this,
-                       widgetFullName = this.widgetFullName;
-               if ( !$.ui.dialog.overlayInstances ) {
-                       // Prevent use of anchors and inputs.
-                       // We use a delay in case the overlay is created from an
-                       // event that we're going to be cancelling. (#2804)
-                       this._delay(function() {
-                               // Handle .dialog().dialog("close") (#4065)
-                               if ( $.ui.dialog.overlayInstances ) {
-                                       this.document.bind( "focusin.dialog", function( event ) {
-                                               if ( !that._allowInteraction( event ) ) {
-                                                       event.preventDefault();
-                                                       $(".ui-dialog:visible:last .ui-dialog-content")
-                                                               .data( widgetFullName )._focusTabbable();
-                                               }
-                                       });
-                               }
-                       });
-               }
-
-               this.overlay = $("<div>")
-                       .addClass("ui-widget-overlay ui-front")
-                       .appendTo( this._appendTo() );
-               this._on( this.overlay, {
-                       mousedown: "_keepFocus"
-               });
-               $.ui.dialog.overlayInstances++;
-       },
-
-       _destroyOverlay: function() {
-               if ( !this.options.modal ) {
-                       return;
-               }
-
-               if ( this.overlay ) {
-                       $.ui.dialog.overlayInstances--;
-
-                       if ( !$.ui.dialog.overlayInstances ) {
-                               this.document.unbind( "focusin.dialog" );
-                       }
-                       this.overlay.remove();
-                       this.overlay = null;
-               }
-       }
-});
-
-$.ui.dialog.overlayInstances = 0;
-
-// DEPRECATED
-if ( $.uiBackCompat !== false ) {
-       // position option with array notation
-       // just override with old implementation
-       $.widget( "ui.dialog", $.ui.dialog, {
-               _position: function() {
-                       var position = this.options.position,
-                               myAt = [],
-                               offset = [ 0, 0 ],
-                               isVisible;
-
-                       if ( position ) {
-                               if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
-                                       myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
-                                       if ( myAt.length === 1 ) {
-                                               myAt[1] = myAt[0];
-                                       }
-
-                                       $.each( [ "left", "top" ], function( i, offsetPosition ) {
-                                               if ( +myAt[ i ] === myAt[ i ] ) {
-                                                       offset[ i ] = myAt[ i ];
-                                                       myAt[ i ] = offsetPosition;
-                                               }
-                                       });
-
-                                       position = {
-                                               my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
-                                                       myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
-                                               at: myAt.join(" ")
-                                       };
-                               }
-
-                               position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
-                       } else {
-                               position = $.ui.dialog.prototype.options.position;
-                       }
-
-                       // need to show the dialog to get the actual offset in the position plugin
-                       isVisible = this.uiDialog.is(":visible");
-                       if ( !isVisible ) {
-                               this.uiDialog.show();
-                       }
-                       this.uiDialog.position( position );
-                       if ( !isVisible ) {
-                               this.uiDialog.hide();
-                       }
-               }
-       });
-}
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-var tabId = 0,
-       rhash = /#.*$/;
-
-function getNextTabId() {
-       return ++tabId;
-}
-
-function isLocal( anchor ) {
-       // support: IE7
-       // IE7 doesn't normalize the href property when set via script (#9317)
-       anchor = anchor.cloneNode( false );
-
-       return anchor.hash.length > 1 &&
-               decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
-                       decodeURIComponent( location.href.replace( rhash, "" ) );
-}
-
-$.widget( "ui.tabs", {
-       version: "1.10.4",
-       delay: 300,
-       options: {
-               active: null,
-               collapsible: false,
-               event: "click",
-               heightStyle: "content",
-               hide: null,
-               show: null,
-
-               // callbacks
-               activate: null,
-               beforeActivate: null,
-               beforeLoad: null,
-               load: null
-       },
-
-       _create: function() {
-               var that = this,
-                       options = this.options;
-
-               this.running = false;
-
-               this.element
-                       .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
-                       .toggleClass( "ui-tabs-collapsible", options.collapsible )
-                       // Prevent users from focusing disabled tabs via click
-                       .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
-                               if ( $( this ).is( ".ui-state-disabled" ) ) {
-                                       event.preventDefault();
-                               }
-                       })
-                       // support: IE <9
-                       // Preventing the default action in mousedown doesn't prevent IE
-                       // from focusing the element, so if the anchor gets focused, blur.
-                       // We don't have to worry about focusing the previously focused
-                       // element since clicking on a non-focusable element should focus
-                       // the body anyway.
-                       .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
-                               if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
-                                       this.blur();
-                               }
-                       });
-
-               this._processTabs();
-               options.active = this._initialActive();
-
-               // Take disabling tabs via class attribute from HTML
-               // into account and update option properly.
-               if ( $.isArray( options.disabled ) ) {
-                       options.disabled = $.unique( options.disabled.concat(
-                               $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
-                                       return that.tabs.index( li );
-                               })
-                       ) ).sort();
-               }
-
-               // check for length avoids error when initializing empty list
-               if ( this.options.active !== false && this.anchors.length ) {
-                       this.active = this._findActive( options.active );
-               } else {
-                       this.active = $();
-               }
-
-               this._refresh();
-
-               if ( this.active.length ) {
-                       this.load( options.active );
-               }
-       },
-
-       _initialActive: function() {
-               var active = this.options.active,
-                       collapsible = this.options.collapsible,
-                       locationHash = location.hash.substring( 1 );
-
-               if ( active === null ) {
-                       // check the fragment identifier in the URL
-                       if ( locationHash ) {
-                               this.tabs.each(function( i, tab ) {
-                                       if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
-                                               active = i;
-                                               return false;
-                                       }
-                               });
-                       }
-
-                       // check for a tab marked active via a class
-                       if ( active === null ) {
-                               active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
-                       }
-
-                       // no active tab, set to false
-                       if ( active === null || active === -1 ) {
-                               active = this.tabs.length ? 0 : false;
-                       }
-               }
-
-               // handle numbers: negative, out of range
-               if ( active !== false ) {
-                       active = this.tabs.index( this.tabs.eq( active ) );
-                       if ( active === -1 ) {
-                               active = collapsible ? false : 0;
-                       }
-               }
-
-               // don't allow collapsible: false and active: false
-               if ( !collapsible && active === false && this.anchors.length ) {
-                       active = 0;
-               }
-
-               return active;
-       },
-
-       _getCreateEventData: function() {
-               return {
-                       tab: this.active,
-                       panel: !this.active.length ? $() : this._getPanelForTab( this.active )
-               };
-       },
-
-       _tabKeydown: function( event ) {
-               var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
-                       selectedIndex = this.tabs.index( focusedTab ),
-                       goingForward = true;
-
-               if ( this._handlePageNav( event ) ) {
-                       return;
-               }
-
-               switch ( event.keyCode ) {
-                       case $.ui.keyCode.RIGHT:
-                       case $.ui.keyCode.DOWN:
-                               selectedIndex++;
-                               break;
-                       case $.ui.keyCode.UP:
-                       case $.ui.keyCode.LEFT:
-                               goingForward = false;
-                               selectedIndex--;
-                               break;
-                       case $.ui.keyCode.END:
-                               selectedIndex = this.anchors.length - 1;
-                               break;
-                       case $.ui.keyCode.HOME:
-                               selectedIndex = 0;
-                               break;
-                       case $.ui.keyCode.SPACE:
-                               // Activate only, no collapsing
-                               event.preventDefault();
-                               clearTimeout( this.activating );
-                               this._activate( selectedIndex );
-                               return;
-                       case $.ui.keyCode.ENTER:
-                               // Toggle (cancel delayed activation, allow collapsing)
-                               event.preventDefault();
-                               clearTimeout( this.activating );
-                               // Determine if we should collapse or activate
-                               this._activate( selectedIndex === this.options.active ? false : selectedIndex );
-                               return;
-                       default:
-                               return;
-               }
-
-               // Focus the appropriate tab, based on which key was pressed
-               event.preventDefault();
-               clearTimeout( this.activating );
-               selectedIndex = this._focusNextTab( selectedIndex, goingForward );
-
-               // Navigating with control key will prevent automatic activation
-               if ( !event.ctrlKey ) {
-                       // Update aria-selected immediately so that AT think the tab is already selected.
-                       // Otherwise AT may confuse the user by stating that they need to activate the tab,
-                       // but the tab will already be activated by the time the announcement finishes.
-                       focusedTab.attr( "aria-selected", "false" );
-                       this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
-
-                       this.activating = this._delay(function() {
-                               this.option( "active", selectedIndex );
-                       }, this.delay );
-               }
-       },
-
-       _panelKeydown: function( event ) {
-               if ( this._handlePageNav( event ) ) {
-                       return;
-               }
-
-               // Ctrl+up moves focus to the current tab
-               if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
-                       event.preventDefault();
-                       this.active.focus();
-               }
-       },
-
-       // Alt+page up/down moves focus to the previous/next tab (and activates)
-       _handlePageNav: function( event ) {
-               if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
-                       this._activate( this._focusNextTab( this.options.active - 1, false ) );
-                       return true;
-               }
-               if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
-                       this._activate( this._focusNextTab( this.options.active + 1, true ) );
-                       return true;
-               }
-       },
-
-       _findNextTab: function( index, goingForward ) {
-               var lastTabIndex = this.tabs.length - 1;
-
-               function constrain() {
-                       if ( index > lastTabIndex ) {
-                               index = 0;
-                       }
-                       if ( index < 0 ) {
-                               index = lastTabIndex;
-                       }
-                       return index;
-               }
-
-               while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
-                       index = goingForward ? index + 1 : index - 1;
-               }
-
-               return index;
-       },
-
-       _focusNextTab: function( index, goingForward ) {
-               index = this._findNextTab( index, goingForward );
-               this.tabs.eq( index ).focus();
-               return index;
-       },
-
-       _setOption: function( key, value ) {
-               if ( key === "active" ) {
-                       // _activate() will handle invalid values and update this.options
-                       this._activate( value );
-                       return;
-               }
-
-               if ( key === "disabled" ) {
-                       // don't use the widget factory's disabled handling
-                       this._setupDisabled( value );
-                       return;
-               }
-
-               this._super( key, value);
-
-               if ( key === "collapsible" ) {
-                       this.element.toggleClass( "ui-tabs-collapsible", value );
-                       // Setting collapsible: false while collapsed; open first panel
-                       if ( !value && this.options.active === false ) {
-                               this._activate( 0 );
-                       }
-               }
-
-               if ( key === "event" ) {
-                       this._setupEvents( value );
-               }
-
-               if ( key === "heightStyle" ) {
-                       this._setupHeightStyle( value );
-               }
-       },
-
-       _tabId: function( tab ) {
-               return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
-       },
-
-       _sanitizeSelector: function( hash ) {
-               return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
-       },
-
-       refresh: function() {
-               var options = this.options,
-                       lis = this.tablist.children( ":has(a[href])" );
-
-               // get disabled tabs from class attribute from HTML
-               // this will get converted to a boolean if needed in _refresh()
-               options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
-                       return lis.index( tab );
-               });
-
-               this._processTabs();
-
-               // was collapsed or no tabs
-               if ( options.active === false || !this.anchors.length ) {
-                       options.active = false;
-                       this.active = $();
-               // was active, but active tab is gone
-               } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
-                       // all remaining tabs are disabled
-                       if ( this.tabs.length === options.disabled.length ) {
-                               options.active = false;
-                               this.active = $();
-                       // activate previous tab
-                       } else {
-                               this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
-                       }
-               // was active, active tab still exists
-               } else {
-                       // make sure active index is correct
-                       options.active = this.tabs.index( this.active );
-               }
-
-               this._refresh();
-       },
-
-       _refresh: function() {
-               this._setupDisabled( this.options.disabled );
-               this._setupEvents( this.options.event );
-               this._setupHeightStyle( this.options.heightStyle );
-
-               this.tabs.not( this.active ).attr({
-                       "aria-selected": "false",
-                       tabIndex: -1
-               });
-               this.panels.not( this._getPanelForTab( this.active ) )
-                       .hide()
-                       .attr({
-                               "aria-expanded": "false",
-                               "aria-hidden": "true"
-                       });
-
-               // Make sure one tab is in the tab order
-               if ( !this.active.length ) {
-                       this.tabs.eq( 0 ).attr( "tabIndex", 0 );
-               } else {
-                       this.active
-                               .addClass( "ui-tabs-active ui-state-active" )
-                               .attr({
-                                       "aria-selected": "true",
-                                       tabIndex: 0
-                               });
-                       this._getPanelForTab( this.active )
-                               .show()
-                               .attr({
-                                       "aria-expanded": "true",
-                                       "aria-hidden": "false"
-                               });
-               }
-       },
-
-       _processTabs: function() {
-               var that = this;
-
-               this.tablist = this._getList()
-                       .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-                       .attr( "role", "tablist" );
-
-               this.tabs = this.tablist.find( "> li:has(a[href])" )
-                       .addClass( "ui-state-default ui-corner-top" )
-                       .attr({
-                               role: "tab",
-                               tabIndex: -1
-                       });
-
-               this.anchors = this.tabs.map(function() {
-                               return $( "a", this )[ 0 ];
-                       })
-                       .addClass( "ui-tabs-anchor" )
-                       .attr({
-                               role: "presentation",
-                               tabIndex: -1
-                       });
-
-               this.panels = $();
-
-               this.anchors.each(function( i, anchor ) {
-                       var selector, panel, panelId,
-                               anchorId = $( anchor ).uniqueId().attr( "id" ),
-                               tab = $( anchor ).closest( "li" ),
-                               originalAriaControls = tab.attr( "aria-controls" );
-
-                       // inline tab
-                       if ( isLocal( anchor ) ) {
-                               selector = anchor.hash;
-                               panel = that.element.find( that._sanitizeSelector( selector ) );
-                       // remote tab
-                       } else {
-                               panelId = that._tabId( tab );
-                               selector = "#" + panelId;
-                               panel = that.element.find( selector );
-                               if ( !panel.length ) {
-                                       panel = that._createPanel( panelId );
-                                       panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
-                               }
-                               panel.attr( "aria-live", "polite" );
-                       }
-
-                       if ( panel.length) {
-                               that.panels = that.panels.add( panel );
-                       }
-                       if ( originalAriaControls ) {
-                               tab.data( "ui-tabs-aria-controls", originalAriaControls );
-                       }
-                       tab.attr({
-                               "aria-controls": selector.substring( 1 ),
-                               "aria-labelledby": anchorId
-                       });
-                       panel.attr( "aria-labelledby", anchorId );
-               });
-
-               this.panels
-                       .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-                       .attr( "role", "tabpanel" );
-       },
-
-       // allow overriding how to find the list for rare usage scenarios (#7715)
-       _getList: function() {
-               return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
-       },
-
-       _createPanel: function( id ) {
-               return $( "<div>" )
-                       .attr( "id", id )
-                       .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-                       .data( "ui-tabs-destroy", true );
-       },
-
-       _setupDisabled: function( disabled ) {
-               if ( $.isArray( disabled ) ) {
-                       if ( !disabled.length ) {
-                               disabled = false;
-                       } else if ( disabled.length === this.anchors.length ) {
-                               disabled = true;
-                       }
-               }
-
-               // disable tabs
-               for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
-                       if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
-                               $( li )
-                                       .addClass( "ui-state-disabled" )
-                                       .attr( "aria-disabled", "true" );
-                       } else {
-                               $( li )
-                                       .removeClass( "ui-state-disabled" )
-                                       .removeAttr( "aria-disabled" );
-                       }
-               }
-
-               this.options.disabled = disabled;
-       },
-
-       _setupEvents: function( event ) {
-               var events = {
-                       click: function( event ) {
-                               event.preventDefault();
-                       }
-               };
-               if ( event ) {
-                       $.each( event.split(" "), function( index, eventName ) {
-                               events[ eventName ] = "_eventHandler";
-                       });
-               }
-
-               this._off( this.anchors.add( this.tabs ).add( this.panels ) );
-               this._on( this.anchors, events );
-               this._on( this.tabs, { keydown: "_tabKeydown" } );
-               this._on( this.panels, { keydown: "_panelKeydown" } );
-
-               this._focusable( this.tabs );
-               this._hoverable( this.tabs );
-       },
-
-       _setupHeightStyle: function( heightStyle ) {
-               var maxHeight,
-                       parent = this.element.parent();
-
-               if ( heightStyle === "fill" ) {
-                       maxHeight = parent.height();
-                       maxHeight -= this.element.outerHeight() - this.element.height();
-
-                       this.element.siblings( ":visible" ).each(function() {
-                               var elem = $( this ),
-                                       position = elem.css( "position" );
-
-                               if ( position === "absolute" || position === "fixed" ) {
-                                       return;
-                               }
-                               maxHeight -= elem.outerHeight( true );
-                       });
-
-                       this.element.children().not( this.panels ).each(function() {
-                               maxHeight -= $( this ).outerHeight( true );
-                       });
-
-                       this.panels.each(function() {
-                               $( this ).height( Math.max( 0, maxHeight -
-                                       $( this ).innerHeight() + $( this ).height() ) );
-                       })
-                       .css( "overflow", "auto" );
-               } else if ( heightStyle === "auto" ) {
-                       maxHeight = 0;
-                       this.panels.each(function() {
-                               maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
-                       }).height( maxHeight );
-               }
-       },
-
-       _eventHandler: function( event ) {
-               var options = this.options,
-                       active = this.active,
-                       anchor = $( event.currentTarget ),
-                       tab = anchor.closest( "li" ),
-                       clickedIsActive = tab[ 0 ] === active[ 0 ],
-                       collapsing = clickedIsActive && options.collapsible,
-                       toShow = collapsing ? $() : this._getPanelForTab( tab ),
-                       toHide = !active.length ? $() : this._getPanelForTab( active ),
-                       eventData = {
-                               oldTab: active,
-                               oldPanel: toHide,
-                               newTab: collapsing ? $() : tab,
-                               newPanel: toShow
-                       };
-
-               event.preventDefault();
-
-               if ( tab.hasClass( "ui-state-disabled" ) ||
-                               // tab is already loading
-                               tab.hasClass( "ui-tabs-loading" ) ||
-                               // can't switch durning an animation
-                               this.running ||
-                               // click on active header, but not collapsible
-                               ( clickedIsActive && !options.collapsible ) ||
-                               // allow canceling activation
-                               ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
-                       return;
-               }
-
-               options.active = collapsing ? false : this.tabs.index( tab );
-
-               this.active = clickedIsActive ? $() : tab;
-               if ( this.xhr ) {
-                       this.xhr.abort();
-               }
-
-               if ( !toHide.length && !toShow.length ) {
-                       $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
-               }
-
-               if ( toShow.length ) {
-                       this.load( this.tabs.index( tab ), event );
-               }
-               this._toggle( event, eventData );
-       },
-
-       // handles show/hide for selecting tabs
-       _toggle: function( event, eventData ) {
-               var that = this,
-                       toShow = eventData.newPanel,
-                       toHide = eventData.oldPanel;
-
-               this.running = true;
-
-               function complete() {
-                       that.running = false;
-                       that._trigger( "activate", event, eventData );
-               }
-
-               function show() {
-                       eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
-
-                       if ( toShow.length && that.options.show ) {
-                               that._show( toShow, that.options.show, complete );
-                       } else {
-                               toShow.show();
-                               complete();
-                       }
-               }
-
-               // start out by hiding, then showing, then completing
-               if ( toHide.length && this.options.hide ) {
-                       this._hide( toHide, this.options.hide, function() {
-                               eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-                               show();
-                       });
-               } else {
-                       eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-                       toHide.hide();
-                       show();
-               }
-
-               toHide.attr({
-                       "aria-expanded": "false",
-                       "aria-hidden": "true"
-               });
-               eventData.oldTab.attr( "aria-selected", "false" );
-               // If we're switching tabs, remove the old tab from the tab order.
-               // If we're opening from collapsed state, remove the previous tab from the tab order.
-               // If we're collapsing, then keep the collapsing tab in the tab order.
-               if ( toShow.length && toHide.length ) {
-                       eventData.oldTab.attr( "tabIndex", -1 );
-               } else if ( toShow.length ) {
-                       this.tabs.filter(function() {
-                               return $( this ).attr( "tabIndex" ) === 0;
-                       })
-                       .attr( "tabIndex", -1 );
-               }
-
-               toShow.attr({
-                       "aria-expanded": "true",
-                       "aria-hidden": "false"
-               });
-               eventData.newTab.attr({
-                       "aria-selected": "true",
-                       tabIndex: 0
-               });
-       },
-
-       _activate: function( index ) {
-               var anchor,
-                       active = this._findActive( index );
-
-               // trying to activate the already active panel
-               if ( active[ 0 ] === this.active[ 0 ] ) {
-                       return;
-               }
-
-               // trying to collapse, simulate a click on the current active header
-               if ( !active.length ) {
-                       active = this.active;
-               }
-
-               anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
-               this._eventHandler({
-                       target: anchor,
-                       currentTarget: anchor,
-                       preventDefault: $.noop
-               });
-       },
-
-       _findActive: function( index ) {
-               return index === false ? $() : this.tabs.eq( index );
-       },
-
-       _getIndex: function( index ) {
-               // meta-function to give users option to provide a href string instead of a numerical index.
-               if ( typeof index === "string" ) {
-                       index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
-               }
-
-               return index;
-       },
-
-       _destroy: function() {
-               if ( this.xhr ) {
-                       this.xhr.abort();
-               }
-
-               this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
-
-               this.tablist
-                       .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-                       .removeAttr( "role" );
-
-               this.anchors
-                       .removeClass( "ui-tabs-anchor" )
-                       .removeAttr( "role" )
-                       .removeAttr( "tabIndex" )
-                       .removeUniqueId();
-
-               this.tabs.add( this.panels ).each(function() {
-                       if ( $.data( this, "ui-tabs-destroy" ) ) {
-                               $( this ).remove();
-                       } else {
-                               $( this )
-                                       .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
-                                               "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
-                                       .removeAttr( "tabIndex" )
-                                       .removeAttr( "aria-live" )
-                                       .removeAttr( "aria-busy" )
-                                       .removeAttr( "aria-selected" )
-                                       .removeAttr( "aria-labelledby" )
-                                       .removeAttr( "aria-hidden" )
-                                       .removeAttr( "aria-expanded" )
-                                       .removeAttr( "role" );
-                       }
-               });
-
-               this.tabs.each(function() {
-                       var li = $( this ),
-                               prev = li.data( "ui-tabs-aria-controls" );
-                       if ( prev ) {
-                               li
-                                       .attr( "aria-controls", prev )
-                                       .removeData( "ui-tabs-aria-controls" );
-                       } else {
-                               li.removeAttr( "aria-controls" );
-                       }
-               });
-
-               this.panels.show();
-
-               if ( this.options.heightStyle !== "content" ) {
-                       this.panels.css( "height", "" );
-               }
-       },
-
-       enable: function( index ) {
-               var disabled = this.options.disabled;
-               if ( disabled === false ) {
-                       return;
-               }
-
-               if ( index === undefined ) {
-                       disabled = false;
-               } else {
-                       index = this._getIndex( index );
-                       if ( $.isArray( disabled ) ) {
-                               disabled = $.map( disabled, function( num ) {
-                                       return num !== index ? num : null;
-                               });
-                       } else {
-                               disabled = $.map( this.tabs, function( li, num ) {
-                                       return num !== index ? num : null;
-                               });
-                       }
-               }
-               this._setupDisabled( disabled );
-       },
-
-       disable: function( index ) {
-               var disabled = this.options.disabled;
-               if ( disabled === true ) {
-                       return;
-               }
-
-               if ( index === undefined ) {
-                       disabled = true;
-               } else {
-                       index = this._getIndex( index );
-                       if ( $.inArray( index, disabled ) !== -1 ) {
-                               return;
-                       }
-                       if ( $.isArray( disabled ) ) {
-                               disabled = $.merge( [ index ], disabled ).sort();
-                       } else {
-                               disabled = [ index ];
-                       }
-               }
-               this._setupDisabled( disabled );
-       },
-
-       load: function( index, event ) {
-               index = this._getIndex( index );
-               var that = this,
-                       tab = this.tabs.eq( index ),
-                       anchor = tab.find( ".ui-tabs-anchor" ),
-                       panel = this._getPanelForTab( tab ),
-                       eventData = {
-                               tab: tab,
-                               panel: panel
-                       };
-
-               // not remote
-               if ( isLocal( anchor[ 0 ] ) ) {
-                       return;
-               }
-
-               this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
-
-               // support: jQuery <1.8
-               // jQuery <1.8 returns false if the request is canceled in beforeSend,
-               // but as of 1.8, $.ajax() always returns a jqXHR object.
-               if ( this.xhr && this.xhr.statusText !== "canceled" ) {
-                       tab.addClass( "ui-tabs-loading" );
-                       panel.attr( "aria-busy", "true" );
-
-                       this.xhr
-                               .success(function( response ) {
-                                       // support: jQuery <1.8
-                                       // http://bugs.jquery.com/ticket/11778
-                                       setTimeout(function() {
-                                               panel.html( response );
-                                               that._trigger( "load", event, eventData );
-                                       }, 1 );
-                               })
-                               .complete(function( jqXHR, status ) {
-                                       // support: jQuery <1.8
-                                       // http://bugs.jquery.com/ticket/11778
-                                       setTimeout(function() {
-                                               if ( status === "abort" ) {
-                                                       that.panels.stop( false, true );
-                                               }
-
-                                               tab.removeClass( "ui-tabs-loading" );
-                                               panel.removeAttr( "aria-busy" );
-
-                                               if ( jqXHR === that.xhr ) {
-                                                       delete that.xhr;
-                                               }
-                                       }, 1 );
-                               });
-               }
-       },
-
-       _ajaxSettings: function( anchor, event, eventData ) {
-               var that = this;
-               return {
-                       url: anchor.attr( "href" ),
-                       beforeSend: function( jqXHR, settings ) {
-                               return that._trigger( "beforeLoad", event,
-                                       $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
-                       }
-               };
-       },
-
-       _getPanelForTab: function( tab ) {
-               var id = $( tab ).attr( "aria-controls" );
-               return this.element.find( this._sanitizeSelector( "#" + id ) );
-       }
-});
-
-})( jQuery );
index 4f6610a2e05e10196f037a8db5c3d342d6aadd04..62b3963d72207c22c3544c35916b0524dfdf66bf 100644 (file)
@@ -6103,6 +6103,14 @@ prop-types@15.6.0, prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, pro
     loose-envify "^1.3.1"
     object-assign "^4.1.1"
 
+prop-types@^15.6.1:
+  version "15.6.1"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
+  dependencies:
+    fbjs "^0.8.16"
+    loose-envify "^1.3.1"
+    object-assign "^4.1.1"
+
 proxy-addr@~2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
@@ -6271,6 +6279,12 @@ rc@^1.1.7:
     minimist "^1.2.0"
     strip-json-comments "~2.0.1"
 
+react-day-picker@7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-7.1.2.tgz#9d6889c391dedc1665056882f06d237b5fb6cd41"
+  dependencies:
+    prop-types "^15.6.1"
+
 react-dev-utils@^3.0.0:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-3.1.1.tgz#09ae7209a81384248db56547e718e65bd3b20eb5"
index 3610dd3c107bb41279a748737af04dd8ae90703f..2485efae2c7bb175ebd16dc912c75fdd646abd03 100644 (file)
@@ -58,6 +58,7 @@ directory=Directory
 display=Display
 download_verb=Download
 duplications=Duplications
+end_date=End Date
 edit=Edit
 events=Events
 explore=Explore
@@ -149,6 +150,7 @@ selected=Selected
 set=Set
 severity=Severity
 shared=Shared
+start_date=Start Date
 x_show={0} shown
 x_selected={0} selected
 x_of_y_shown={0} of {1} shown
@@ -161,6 +163,7 @@ technical_debt=Technical Debt
 template=Template
 title=Title
 to=To
+to_=to
 total=Total
 treemap=Treemap
 true=True