aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-web/archiva-webapp/src
diff options
context:
space:
mode:
authorOlivier Lamy <olamy@apache.org>2012-12-27 14:55:12 +0000
committerOlivier Lamy <olamy@apache.org>2012-12-27 14:55:12 +0000
commit708a34f1f23b9c1a20abb244fecd299992480a4b (patch)
treed54069226f6ee121e308a55bfcc0bd4401a8f8f1 /archiva-modules/archiva-web/archiva-webapp/src
parent58edbc0c438c92c593780f355eae3505e36037e3 (diff)
downloadarchiva-708a34f1f23b9c1a20abb244fecd299992480a4b.tar.gz
archiva-708a34f1f23b9c1a20abb244fecd299992480a4b.zip
rename archiva-webapp-js module to archiva-webapp
git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1426213 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-modules/archiva-web/archiva-webapp/src')
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/resources/META-INF/spring-context.xml51
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/resources/ehcache.xml92
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j2.xml138
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/archiva/redback-security.properties29
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml189
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml146
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css190
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/bootstrap.2.2.1.css5893
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/application.pngbin0 -> 464 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/code.pngbin0 -> 603 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/css.pngbin0 -> 618 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/db.pngbin0 -> 579 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/doc.pngbin0 -> 651 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/file.pngbin0 -> 294 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/film.pngbin0 -> 653 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/flash.pngbin0 -> 582 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder-closed.gifbin0 -> 105 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder.gifbin0 -> 106 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/html.pngbin0 -> 734 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/java.pngbin0 -> 633 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/linux.pngbin0 -> 668 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/music.pngbin0 -> 385 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/pdf.pngbin0 -> 591 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/php.pngbin0 -> 538 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/picture.pngbin0 -> 606 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ppt.pngbin0 -> 588 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/psd.pngbin0 -> 856 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ruby.pngbin0 -> 626 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/script.pngbin0 -> 859 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2.pngbin0 -> 613 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2x2.pngbin0 -> 845 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/spinner.gifbin0 -> 2530 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/txt.pngbin0 -> 342 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 180 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_75_ffffff_40x100.pngbin0 -> 178 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_55_fbf9ee_1x400.pngbin0 -> 120 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_65_ffffff_1x400.pngbin0 -> 105 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_dadada_1x400.pngbin0 -> 111 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_e6e6e6_1x400.pngbin0 -> 110 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_ffffff_1x400.pngbin0 -> 107 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 119 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_highlight-soft_75_cccccc_1x100.pngbin0 -> 101 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_inset-soft_95_fef1ec_1x100.pngbin0 -> 123 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_222222_256x240.pngbin0 -> 4369 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_2e83ff_256x240.pngbin0 -> 4369 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_454545_256x240.pngbin0 -> 4369 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_888888_256x240.pngbin0 -> 4369 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4369 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_f6cf3b_256x240.pngbin0 -> 8884 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/xls.pngbin0 -> 663 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/zip.pngbin0 -> 386 bytes
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery-ui-1.9.2.custom.min.css5
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.fileupload-ui.css84
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.ui.1.8.16.ie.css6
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jqueryFileTree.css91
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/prettify.css52
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/select2-3.2.css524
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/favicon.icobin0 -> 3638 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-2-32-32.pngbin0 -> 2464 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-32-32.pngbin0 -> 2464 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/atom.gifbin0 -> 652 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error-22-22.pngbin0 -> 925 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error.pngbin0 -> 653 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/drive-removable-media-16-16.pngbin0 -> 510 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/edit-cut.pngbin0 -> 807 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder-saved-search.pngbin0 -> 711 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder.pngbin0 -> 581 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/go-home.pngbin0 -> 606 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/green-22-22.pngbin0 -> 1313 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser-32-32.pngbin0 -> 2251 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser.pngbin0 -> 928 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add-22-22.pngbin0 -> 386 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add.pngbin0 -> 323 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/medium-spinner.gifbin0 -> 2545 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/package-x-generic.pngbin0 -> 540 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/preferences-system-network-proxy-32-32.pngbin0 -> 2212 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/red-22-22.pngbin0 -> 1302 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/small-spinner.gifbin0 -> 1542 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-file-manager-32-32.pngbin0 -> 667 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen-22-22.pngbin0 -> 1005 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen.pngbin0 -> 764 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-search-16-16.pngbin0 -> 935 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-software-update-32-32.pngbin0 -> 2216 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-users-32-32.pngbin0 -> 1901 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/trash.pngbin0 -> 655 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash-full.pngbin0 -> 786 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash.pngbin0 -> 655 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor-22-22.pngbin0 -> 990 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor.pngbin0 -> 611 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh-22-22.pngbin0 -> 1364 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh.pngbin0 -> 912 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear-22-22.pngbin0 -> 952 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear.pngbin0 -> 682 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings-white.pngbin0 -> 8777 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings.pngbin0 -> 12799 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/loading.gifbin0 -> 3897 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/progressbar.gifbin0 -> 3323 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/index.html79
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js127
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/artifacts-management.js124
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/docs.js94
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/general-admin.js1585
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main-tmpl.js41
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js879
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/network-proxies.js323
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors-rules.js376
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors.js673
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repositories.js1304
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repository-groups.js385
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js2102
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/startup.js57
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/utils.js511
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/bootstrap.2.2.1.js2025
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/domReady.js125
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-1.8.3.min.js2
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-ui-1.9.2.custom.min.js6
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.cookie.1.0.0.js91
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-5.10.0.js905
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ip-1.0.6.js160
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ui-6.6.3.js630
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.i18n.properties-1.0.9.js499
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.iframe-transport-1.4.js171
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.json-2.3.min.js23
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.tmpl.js492
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.ui.widget-1.9.2.js528
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.validate-1.9.0.js1188
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jqueryFileTree-1.0.1.js102
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-2.2.0.debug.js3577
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-sortable.js285
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout.simpleGrid.js86
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/order.js189
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/prettify.js1477
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/purl-2.2.1.js271
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback-tmpl.js35
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback.js220
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/roles.js387
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/user.js835
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/users.js290
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/require.2.1.2.js35
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/sammy.0.7.1.js2003
-rwxr-xr-xarchiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/select2.min-3.2.js82
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/docs.html38
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/general-admin.html1100
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/generics.html67
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/menu.html116
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/modal.html42
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html1686
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html969
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/login.html163
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/user-edit.html572
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/text.js305
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/tmpl.min.js1
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/auto-admin-creation.properties22
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/log4j2-test.xml92
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/tomcat-context-archiva.xml31
155 files changed, 38073 insertions, 0 deletions
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/META-INF/spring-context.xml
new file mode 100755
index 000000000..a948d74aa
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util-3.0.xsd"
+ default-lazy-init="true">
+
+ <context:annotation-config/>
+ <context:component-scan base-package="org.apache.archiva.web.api"/>
+
+
+ <util:properties id="archivaRuntimeProperties" location="classpath:application.properties" />
+
+ <bean id="jcr-repository" class="org.apache.jackrabbit.core.RepositoryImpl" destroy-method="shutdown" lazy-init="true">
+ <constructor-arg ref="jcr-config"/>
+ </bean>
+
+ <bean id="jcr-config" class="org.apache.archiva.metadata.repository.jcr.ArchivaJcrRepositoryConfig" factory-method="create">
+ <constructor-arg value="${appserver.base}/conf/repository.xml"/>
+ <constructor-arg value="${appserver.base}/data/jcr"/>
+ </bean>
+
+
+
+
+</beans> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/ehcache.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/ehcache.xml
new file mode 100644
index 000000000..7c7dd7d9a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/ehcache.xml
@@ -0,0 +1,92 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<ehcache>
+ <diskStore path="java.io.tmpdir" />
+
+ <!-- make default cache very short lived -->
+
+ <defaultCache
+ maxElementsInMemory="100"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <!--
+ cache Redback classes longer to avoid a lot of SQL queries
+ See REDBACK-227
+ -->
+ <cache name="defaultJpox"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1800"
+ timeToLiveSeconds="14400"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <cache name="org.apache.archiva.redback.rbac.jdo.JdoOperation"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1800"
+ timeToLiveSeconds="14400"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <cache name="org.apache.archiva.redback.rbac.jdo.JdoPermission"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1800"
+ timeToLiveSeconds="14400"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <cache name="org.apache.archiva.redback.rbac.jdo.JdoResource"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1800"
+ timeToLiveSeconds="14400"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <cache name="org.apache.archiva.redback.rbac.jdo.JdoRole"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1800"
+ timeToLiveSeconds="14400"
+ memoryStoreEvictionPolicy="LFU" />
+
+ <cache name="org.apache.archiva.redback.rbac.jdo.JdoUserAssignment"
+ maxElementsInMemory="10000"
+ maxElementsOnDisk="0"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ memoryStoreEvictionPolicy="LFU" />
+
+</ehcache>
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j2.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..c36bbc4e1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j2.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+
+<configuration>
+
+ <properties>
+ <property name="logsDirectory">${sys:appserver.base}/logs</property>
+ </properties>
+
+ <appenders>
+
+ <RollingFile name="rolling" fileName="${logsDirectory}/archiva.log"
+ filePattern="${logsDirectory}/archiva-%d{MM-dd-yyyy}.log">
+ <PatternLayout>
+ <pattern>%d [%t] %-5p %c %x - %m%n</pattern>
+ </PatternLayout>
+ <Policies>
+ <TimeBasedTriggeringPolicy />
+ </Policies>
+ </RollingFile>
+
+ <RollingFile name="auditlog" fileName="${logsDirectory}/archiva-audit.log"
+ filePattern="${logsDirectory}/logs/archiva-audit-%d{MM-dd-yyyy}.log">
+ <PatternLayout>
+ <pattern>%d{yyyy-MM-dd HH:mm:ss} %m%n</pattern>
+ </PatternLayout>
+ <Policies>
+ <TimeBasedTriggeringPolicy />
+ </Policies>
+ </RollingFile>
+
+ <RollingFile name="redbackAuditLog" fileName="${logsDirectory}/archiva-security-audit.log"
+ filePattern="${logsDirectory}/archiva-security-audit.log-%d{MM-dd-yyyy}.log">
+ <PatternLayout>
+ <pattern>%d{yyyy-MM-dd HH:mm:ss} - %X{redback.currentUser} - %m%n</pattern>
+ </PatternLayout>
+ <Policies>
+ <TimeBasedTriggeringPolicy />
+ </Policies>
+ </RollingFile>
+
+ </appenders>
+ <loggers>
+
+ <logger name="org.apache.archiva.redback.struts2.action.AuditEvent" additivity="false" level="info">
+ <appender-ref ref="redbackAuditLog" />
+ </logger>
+
+ <logger name="org.apache.archiva.AuditLog" additivity="false" level="info">
+ <appender-ref ref="auditlog" />
+ </logger>
+
+ <!-- INFO level loggers can use the default
+ <logger name="org.apache.archiva.consumers" level="info"/>
+
+ <logger name="org.apache.archiva" level="info"/>
+
+
+ <logger name="org.quartz" level="info"/>
+
+ <logger name="org.apache.jasper" level="info"/>
+
+ <logger name="com.opensymphony.xwork2" level="info"/>
+
+ <logger name="org.apache.struts2" level="info"/>
+
+ -->
+
+ <!-- WebDav objects -->
+ <logger name="org.apache.archiva.webdav.ArchivaDavResource" level="info"/>
+
+
+ <logger name="org.apache.archiva.webdav.ArchivaDavResourceFactory" level="info"/>
+
+
+ <!-- squelch noisy objects (for now) -->
+ <logger name="org.apache.commons" level="warn"/>
+
+ <logger name="net.sf.ehcache" level="warn"/>
+
+
+ <!-- retained for Redback -->
+ <logger name="JPOX" level="warn"/>
+
+
+ <logger name="JPOX.MetaData" level="error"/>
+
+
+ <logger name="JPOX.RDBMS.SQL" level="error"/>
+
+
+ <logger name="SQL" level="error"/>
+
+
+
+ <logger name="org.apache.commons.configuration.DefaultConfigurationBuilder" level="error"/>
+
+ <!-- debug wagon transfer -->
+ <!--
+ <logger name="org.apache.archiva.proxy.common" level="debug"/>
+
+ -->
+ <!-- apache httpclient debug content transfer verbose -->
+ <!--
+ <logger name="org.apache.http.wire" level="debug"/>
+
+ -->
+ <!-- apache httpclient log headers -->
+ <!--
+ <logger name="org.apache.http.headers" level="debug"/>
+
+ -->
+
+ <root level="info">
+ <appender-ref ref="rolling"/>
+ </root>
+ </loggers>
+</configuration>
+
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/archiva/redback-security.properties b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/archiva/redback-security.properties
new file mode 100644
index 000000000..bb883b18a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/archiva/redback-security.properties
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# --------------------------------------------------------------------
+# Email Settings
+
+# The subject line for the email message.
+email.validation.subject=Welcome to Archiva
+
+# Feedback page
+email.feedback.path=http://archiva.apache.org/mail-lists.html
+
+email.url.path=index.html \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 000000000..704358dec
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:task="http://www.springframework.org/schema/task"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd
+ http://www.springframework.org/schema/task
+ http://www.springframework.org/schema/task/spring-task-3.0.xsd">
+
+ <context:property-placeholder location="classpath:application.properties"/>
+
+ <alias name="userConfiguration#archiva" alias="userConfiguration#default" />
+
+ <bean id="loggerManager" class="org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager"
+ init-method="initialize"/>
+
+ <!-- only here to cleanup temp indexes for groups increase number if use for something else -->
+ <task:executor id="springExecutor" pool-size="2"/>
+ <task:scheduler id="springScheduler" pool-size="2"/>
+ <task:annotation-driven executor="springExecutor" scheduler="springScheduler"/>
+
+ <alias name="repositoryStatisticsManager#default" alias="repositoryStatisticsManager"/>
+ <!-- TODO olamy need to find a more dynamic way if using jcr impl -->
+ <alias name="repositorySessionFactory#jcr" alias="repositorySessionFactory"/>
+
+ <bean id="mailSession" class="org.springframework.jndi.JndiObjectFactoryBean">
+ <property name="jndiName" value="java:comp/env/mail/Session">
+ </property>
+ </bean>
+
+ <bean name="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
+ <property name="session" ref="mailSession"/>
+ </bean>
+
+ <!-- START SNIPPET: configuration-files-list -->
+ <bean name="commons-configuration" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry">
+ <property name="properties">
+ <value>
+ <![CDATA[
+ <configuration>
+ <system/>
+ <jndi prefix="java:comp/env" config-optional="true"/>
+ <xml fileName="${user.home}/.m2/archiva.xml" config-optional="true"
+ config-name="org.apache.archiva.user"
+ config-at="org.apache.archiva"/>
+ <xml fileName="${user.home}/.m2/shared.xml" config-optional="true"
+ config-name="org.apache.maven.shared.app.user" config-at="org.apache.maven.shared.app"
+ config-forceCreate="true"/>
+ <properties fileName="${user.home}/.m2/security.properties" config-optional="true"
+ config-at="org.apache.archiva.redback"/>
+ <properties fileName="${user.home}/.m2/archiva.properties" config-optional="true"
+ config-at="org.apache.archiva.redback"/>
+ <xml fileName="${appserver.base}/conf/archiva.xml" config-optional="true"
+ config-name="org.apache.archiva.base"
+ config-at="org.apache.archiva"/>
+ <xml fileName="${appserver.base}/conf/shared.xml" config-optional="true"
+ config-name="org.apache.maven.shared.app.base" config-at="org.apache.maven.shared.app"/>
+ <xml fileName="${appserver.base}/conf/common.xml" config-optional="true"/>
+ <properties fileName="${appserver.base}/conf/security.properties" config-optional="true"
+ config-at="org.apache.archiva.redback"/>
+ <xml fileName="${appserver.home}/conf/archiva.xml" config-optional="true"
+ config-at="org.apache.archiva"/>
+ <xml fileName="${appserver.home}/conf/shared.xml" config-optional="true"
+ config-at="org.apache.maven.shared.app"/>
+ <xml fileName="${appserver.home}/conf/common.xml" config-optional="true"/>
+ <properties fileName="${appserver.home}/conf/security.properties" config-optional="true"
+ config-at="org.apache.archiva.redback"/>
+ <properties fileName="org/apache/archiva/redback-security.properties" config-at="org.apache.archiva.redback"/>
+ </configuration>
+ ]]>
+ </value>
+ </property>
+ </bean>
+ <!-- END SNIPPET: configuration-files-list -->
+
+ <bean name="jdoFactory#users" class="org.apache.archiva.redback.components.jdo.DataSourceConfigurableJdoFactory">
+ <property name="connectionFactoryName" value="java:comp/env/jdbc/users"/>
+ <property name="shutdownConnectionFactoryName" value="java:comp/env/jdbc/usersShutdown"/>
+ <property name="persistenceManagerFactoryClass" value="org.jpox.PersistenceManagerFactoryImpl"/>
+ <property name="otherProperties">
+ <props>
+ <prop key="org.jpox.autoCreateSchema">true</prop>
+ <prop key="org.jpox.validateTables">false</prop>
+ <prop key="org.jpox.validateConstraints">false</prop>
+ <prop key="org.jpox.validateColumns">false</prop>
+ <prop key="org.jpox.autoStartMechanism">None</prop>
+ <prop key="org.jpox.transactionIsolation">READ_COMMITTED</prop>
+ <prop key="org.jpox.poid.transactionIsolation">READ_COMMITTED</prop>
+ <prop key="org.jpox.rdbms.dateTimezone">JDK_DEFAULT_TIMEZONE</prop>
+ <!-- NEEDED FOR MYSQL UTF-8 Databases -->
+ <prop key="org.jpox.rdbms.stringDefaultLength">255</prop>
+
+ <!-- NEEDED FOR POSTGRES, But causes problems in other JDBC implementations.
+ <prop key="org.jpox.identifier.case">PreserveCase</prop>
+ -->
+
+ <!-- cache activation -->
+ <prop key="org.jpox.cache.level2">true</prop>
+ <prop key="org.jpox.cache.level2.type">ehcacheclassbased</prop>
+ <prop key="org.jpox.cache.level2.cacheName">defaultJpox</prop>
+ <prop key="org.jpox.cache.level2.configurationFile">/ehcache.xml</prop>
+ </props>
+ </property>
+ </bean>
+
+
+ <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
+ <property name="properties">
+ <props>
+ <prop key="org.quartz.scheduler.instanceName">scheduler1</prop>
+ <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
+ <prop key="org.quartz.threadPool.threadCount">2</prop>
+ <prop key="org.quartz.threadPool.threadPriority">4</prop>
+ <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>
+ </props>
+ </property>
+ </bean>
+
+ <alias name="environmentCheck#archiva-locked-admin-check" alias="environmentCheck#locked-admin-check"/>
+ <alias name="userManager#archiva" alias="userManager#configurable"/>
+ <alias name="authenticator#archiva" alias="authenticator#user-manager"/>
+
+ <alias name="ldapConnectionFactory#archiva" alias="ldapConnectionFactory"/>
+ <alias name="ldapConnectionFactory#archiva" alias="ldapConnectionFactory#configurable"/>
+
+ <!--
+ <bean name="mimeTpes" class="org.apache.archiva.webdav.util.MimeTypes">
+ <property name="resource" value="archiva-mime-types.txt"/>
+ </bean>
+ -->
+ <!-- for change configuration of the users cache -->
+ <bean name="cache#users" class="org.apache.archiva.redback.components.cache.ehcache.EhcacheCache"
+ init-method="initialize">
+ <property name="diskPersistent" value="false"/>
+ <property name="eternal" value="false"/>
+ <property name="maxElementsInMemory" value="1000"/>
+ <property name="memoryEvictionPolicy" value="LRU"/>
+ <property name="name" value="usersCache"/>
+ <property name="timeToIdleSeconds" value="14400"/>
+ <property name="timeToLiveSeconds" value="14400"/>
+ </bean>
+
+ <bean name="cache#url-failures-cache" class="org.apache.archiva.redback.components.cache.ehcache.EhcacheCache" lazy-init="true"
+ destroy-method="dispose">
+ <property name="diskExpiryThreadIntervalSeconds" value="600"/>
+ <property name="diskPersistent" value="true"/>
+ <property name="diskStorePath" value="${java.io.tmpdir}/archiva/urlcache"/>
+ <property name="maxElementsInMemory" value="1000"/>
+ <property name="memoryEvictionPolicy" value="LRU"/>
+ <property name="name" value="url-failures-cache"/>
+ <property name="overflowToDisk" value="false"/>
+ <!-- 45 minutes = 2700 seconds -->
+ <property name="timeToIdleSeconds" value="2700"/>
+ <!-- 30 minutes = 1800 seconds -->
+ <property name="timeToLiveSeconds" value="1800"/>
+ </bean>
+
+ <!-- override jcr repository location -->
+ <!-- START SNIPPET: jcr-location -->
+ <!--
+ <bean id="jcr-config" class="org.apache.archiva.metadata.repository.jcr.ArchivaJcrRepositoryConfig" factory-method="create">
+ <constructor-arg value="${appserver.base}/conf/repository.xml"/>
+ <constructor-arg value="${appserver.base}/data/jcr"/>
+ </bean>
+ -->
+ <!-- END SNIPPET: jcr-location -->
+
+</beans>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..8d8515292
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2005-2006 The Apache Software Foundation.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+ <display-name>Apache Archiva</display-name>
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>
+ classpath*:META-INF/spring-context.xml,
+ /WEB-INF/applicationContext.xml
+ </param-value>
+ </context-param>
+
+ <filter>
+ <filter-name>encodingFilter</filter-name>
+ <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
+ <init-param>
+ <param-name>encoding</param-name>
+ <param-value>UTF-8</param-value>
+ </init-param>
+ <init-param>
+ <param-name>forceEncoding</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>encodingFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+ <listener>
+ <!-- TODO: some Spring technique for this? -->
+ <listener-class>
+ org.apache.archiva.web.startup.ArchivaStartup
+ </listener-class>
+ </listener>
+
+ <listener>
+ <listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class>
+ </listener>
+
+ <!-- to cleanup temporary group index created during a session -->
+ <listener>
+ <listener-class>org.apache.archiva.webdav.util.TemporaryGroupIndexSessionCleaner</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>RepositoryServlet</servlet-name>
+ <servlet-class>
+ org.apache.archiva.webdav.RepositoryServlet
+ </servlet-class>
+ <!-- Loading this on startup so as to take advantage of configuration listeners -->
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet>
+ <servlet-name>RestDocumentation</servlet-name>
+ <servlet-class>org.apache.archiva.web.docs.RestDocsServlet</servlet-class>
+ <load-on-startup>3</load-on-startup>
+ </servlet>
+
+
+ <servlet>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <servlet-class>
+ org.apache.archiva.web.rss.RssFeedServlet
+ </servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <url-pattern>/feeds/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RestDocumentation</servlet-name>
+ <url-pattern>/rest-docs/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RepositoryServlet</servlet-name>
+ <url-pattern>/repository/*</url-pattern>
+ </servlet-mapping>
+
+
+
+ <resource-ref>
+ <res-ref-name>jdbc/users</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+ <res-sharing-scope>Shareable</res-sharing-scope>
+ </resource-ref>
+ <resource-ref>
+ <res-ref-name>mail/Session</res-ref-name>
+ <res-type>javax.mail.Session</res-type>
+ <res-auth>Container</res-auth>
+ <res-sharing-scope>Shareable</res-sharing-scope>
+ </resource-ref>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/restServices/*</url-pattern>
+ </servlet-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ <session-config>
+ <!-- 30 minutes session timeout -->
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+</web-app>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css
new file mode 100644
index 000000000..cf688aa23
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* medium-spinner */
+#medium-spinner {
+ z-index: 20001;
+}
+
+.ar-multiselect .ar-multiselect-column {
+ float: left;
+ width: 17em;
+}
+
+.ar-multiselect .ar-multiselect-center {
+ float: left;
+ width: 3em;
+}
+
+.ar-multiselect-center ul {
+ list-style: none;
+ margin: 3px 0 2px 6px
+}
+
+.ar-multiselect-right {
+ margin-left: 2em
+}
+
+.modified {
+ border:2px solid #fbc7c6;
+}
+
+.modified td{
+ border-top:2px solid #fbc7c6;
+ border:2px solid #fbc7c6;
+}
+
+.draggable-item {
+ cursor: move;
+ margin-bottom: 12px;
+ margin-left: 4px;
+ min-height: 2px;
+ padding: 12px;
+ border: 2px dotted #ddd;
+ margin-left: 2em
+}
+
+.network-proxy-remote-item{
+ margin-bottom: 12px;
+ min-height: 2px;
+ padding: 12px;
+ border: 2px dotted #ddd;
+ margin-left: 2em
+}
+
+.dotted{
+ margin-bottom: 12px;
+ min-height: 2px;
+ padding: 12px;
+ border: 2px dotted #ddd;
+ margin-left: 2em
+}
+
+.browse-list{
+ list-style-image: url("../images/folder.png")
+}
+.browse-list-project{
+ list-style-image: url("../images/folder-saved-search.png");
+}
+
+.package-list{
+ list-style-image: url("../images/package-x-generic.png");
+}
+
+.force-upper-case{
+ text-transform: uppercase;
+}
+
+.dropdown-menu {
+ max-width: 920px;
+}
+.ui-menu-item {
+ cursor: pointer;
+}
+
+.ui-autocomplete-loading{
+ background:url('../images/small-spinner.gif') no-repeat right center;
+}
+
+.nav .archiva-nav-header{
+ font-size: 12px;
+}
+
+footer {
+ border-top: 1px solid #CCCCCC;
+ color: #333333;
+ margin-top: 1em;
+ padding-bottom: 30px;
+ padding-top: 10px;
+}
+
+
+/* CSS for loading message */
+#loadingDiv {
+ position: absolute;
+ left: 45%;
+ bottom: 50%;
+ z-index: 20001;
+ height: auto;
+ border: 1px solid #ccc;
+}
+#loadingDiv a {
+ color: #225588;
+}
+
+#loadingDiv .loading-indicator {
+ background: white;
+ color: #444;
+ font: bold 12px tahoma;
+ padding: 10px;
+ margin: 0;
+ height: auto;
+}
+
+.navbar .brand {
+ color: #555555;
+ display: block;
+ float: left;
+ font-size: 20px;
+ font-weight: 200;
+ margin-left: -20px;
+ padding: 5px 5px;
+ text-shadow: 0 1px 0 #FFFFFF;
+}
+
+.sidebar-nav {
+ padding: 9px 0;
+}
+
+.page-header {
+ border-bottom: 1px solid #EEEEEE;
+ margin: 15px 0 20px;
+ padding-bottom: 3px;
+}
+
+.cursor-hand:hover {
+ cursor: pointer;
+}
+
+
+code {
+ background: none repeat scroll 0 0 #EEEEEE;
+ border: 1px solid #DDDDDD;
+ color: #555555;
+ display: block;
+ font: 1.1em "Lucida Sans Unicode",serif;
+ margin-bottom: 12px;
+ max-height: 300px;
+ overflow: auto;
+ padding: 8px 10px;
+ white-space: pre;
+ vertical-align: baseline;
+}
+
+ol.linenums {
+ margin-bottom: 0;
+ margin-top: 0;
+ padding-left: 5px;
+}
+
+.ui-widget {
+ color: #333333;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ font-size: 14px;
+} \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/bootstrap.2.2.1.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/bootstrap.2.2.1.css
new file mode 100644
index 000000000..1b519e220
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/bootstrap.2.2.1.css
@@ -0,0 +1,5893 @@
+/*!
+ * Bootstrap v2.2.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+ display: block;
+}
+
+audio,
+canvas,
+video {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+}
+
+audio:not([controls]) {
+ display: none;
+}
+
+html {
+ font-size: 100%;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+
+a:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+a:hover,
+a:active {
+ outline: 0;
+}
+
+sub,
+sup {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+img {
+ width: auto\9;
+ height: auto;
+ max-width: 100%;
+ vertical-align: middle;
+ border: 0;
+ -ms-interpolation-mode: bicubic;
+}
+
+#map_canvas img,
+.google-maps img {
+ max-width: none;
+}
+
+button,
+input,
+select,
+textarea {
+ margin: 0;
+ font-size: 100%;
+ vertical-align: middle;
+}
+
+button,
+input {
+ *overflow: visible;
+ line-height: normal;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ cursor: pointer;
+ -webkit-appearance: button;
+}
+
+input[type="search"] {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ -webkit-appearance: textfield;
+}
+
+input[type="search"]::-webkit-search-decoration,
+input[type="search"]::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+}
+
+textarea {
+ overflow: auto;
+ vertical-align: top;
+}
+
+.clearfix {
+ *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.clearfix:after {
+ clear: both;
+}
+
+.hide-text {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.input-block-level {
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 20px;
+ color: #333333;
+ background-color: #ffffff;
+}
+
+a {
+ color: #0088cc;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #005580;
+ text-decoration: underline;
+}
+
+.img-rounded {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.img-polaroid {
+ padding: 4px;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.img-circle {
+ -webkit-border-radius: 500px;
+ -moz-border-radius: 500px;
+ border-radius: 500px;
+}
+
+.row {
+ margin-left: -20px;
+ *zoom: 1;
+}
+
+.row:before,
+.row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.row:after {
+ clear: both;
+}
+
+[class*="span"] {
+ float: left;
+ min-height: 1px;
+ margin-left: 20px;
+}
+
+.container,
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+ width: 940px;
+}
+
+.span12 {
+ width: 940px;
+}
+
+.span11 {
+ width: 860px;
+}
+
+.span10 {
+ width: 780px;
+}
+
+.span9 {
+ width: 700px;
+}
+
+.span8 {
+ width: 620px;
+}
+
+.span7 {
+ width: 540px;
+}
+
+.span6 {
+ width: 460px;
+}
+
+.span5 {
+ width: 380px;
+}
+
+.span4 {
+ width: 300px;
+}
+
+.span3 {
+ width: 220px;
+}
+
+.span2 {
+ width: 140px;
+}
+
+.span1 {
+ width: 60px;
+}
+
+.offset12 {
+ margin-left: 980px;
+}
+
+.offset11 {
+ margin-left: 900px;
+}
+
+.offset10 {
+ margin-left: 820px;
+}
+
+.offset9 {
+ margin-left: 740px;
+}
+
+.offset8 {
+ margin-left: 660px;
+}
+
+.offset7 {
+ margin-left: 580px;
+}
+
+.offset6 {
+ margin-left: 500px;
+}
+
+.offset5 {
+ margin-left: 420px;
+}
+
+.offset4 {
+ margin-left: 340px;
+}
+
+.offset3 {
+ margin-left: 260px;
+}
+
+.offset2 {
+ margin-left: 180px;
+}
+
+.offset1 {
+ margin-left: 100px;
+}
+
+.row-fluid {
+ width: 100%;
+ *zoom: 1;
+}
+
+.row-fluid:before,
+.row-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.row-fluid:after {
+ clear: both;
+}
+
+.row-fluid [class*="span"] {
+ display: block;
+ float: left;
+ width: 100%;
+ min-height: 30px;
+ margin-left: 2.127659574468085%;
+ *margin-left: 2.074468085106383%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.row-fluid [class*="span"]:first-child {
+ margin-left: 0;
+}
+
+.row-fluid .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 2.127659574468085%;
+}
+
+.row-fluid .span12 {
+ width: 100%;
+ *width: 99.94680851063829%;
+}
+
+.row-fluid .span11 {
+ width: 91.48936170212765%;
+ *width: 91.43617021276594%;
+}
+
+.row-fluid .span10 {
+ width: 82.97872340425532%;
+ *width: 82.92553191489361%;
+}
+
+.row-fluid .span9 {
+ width: 74.46808510638297%;
+ *width: 74.41489361702126%;
+}
+
+.row-fluid .span8 {
+ width: 65.95744680851064%;
+ *width: 65.90425531914893%;
+}
+
+.row-fluid .span7 {
+ width: 57.44680851063829%;
+ *width: 57.39361702127659%;
+}
+
+.row-fluid .span6 {
+ width: 48.93617021276595%;
+ *width: 48.88297872340425%;
+}
+
+.row-fluid .span5 {
+ width: 40.42553191489362%;
+ *width: 40.37234042553192%;
+}
+
+.row-fluid .span4 {
+ width: 31.914893617021278%;
+ *width: 31.861702127659576%;
+}
+
+.row-fluid .span3 {
+ width: 23.404255319148934%;
+ *width: 23.351063829787233%;
+}
+
+.row-fluid .span2 {
+ width: 14.893617021276595%;
+ *width: 14.840425531914894%;
+}
+
+.row-fluid .span1 {
+ width: 6.382978723404255%;
+ *width: 6.329787234042553%;
+}
+
+.row-fluid .offset12 {
+ margin-left: 104.25531914893617%;
+ *margin-left: 104.14893617021275%;
+}
+
+.row-fluid .offset12:first-child {
+ margin-left: 102.12765957446808%;
+ *margin-left: 102.02127659574467%;
+}
+
+.row-fluid .offset11 {
+ margin-left: 95.74468085106382%;
+ *margin-left: 95.6382978723404%;
+}
+
+.row-fluid .offset11:first-child {
+ margin-left: 93.61702127659574%;
+ *margin-left: 93.51063829787232%;
+}
+
+.row-fluid .offset10 {
+ margin-left: 87.23404255319149%;
+ *margin-left: 87.12765957446807%;
+}
+
+.row-fluid .offset10:first-child {
+ margin-left: 85.1063829787234%;
+ *margin-left: 84.99999999999999%;
+}
+
+.row-fluid .offset9 {
+ margin-left: 78.72340425531914%;
+ *margin-left: 78.61702127659572%;
+}
+
+.row-fluid .offset9:first-child {
+ margin-left: 76.59574468085106%;
+ *margin-left: 76.48936170212764%;
+}
+
+.row-fluid .offset8 {
+ margin-left: 70.2127659574468%;
+ *margin-left: 70.10638297872339%;
+}
+
+.row-fluid .offset8:first-child {
+ margin-left: 68.08510638297872%;
+ *margin-left: 67.9787234042553%;
+}
+
+.row-fluid .offset7 {
+ margin-left: 61.70212765957446%;
+ *margin-left: 61.59574468085106%;
+}
+
+.row-fluid .offset7:first-child {
+ margin-left: 59.574468085106375%;
+ *margin-left: 59.46808510638297%;
+}
+
+.row-fluid .offset6 {
+ margin-left: 53.191489361702125%;
+ *margin-left: 53.085106382978715%;
+}
+
+.row-fluid .offset6:first-child {
+ margin-left: 51.063829787234035%;
+ *margin-left: 50.95744680851063%;
+}
+
+.row-fluid .offset5 {
+ margin-left: 44.68085106382979%;
+ *margin-left: 44.57446808510638%;
+}
+
+.row-fluid .offset5:first-child {
+ margin-left: 42.5531914893617%;
+ *margin-left: 42.4468085106383%;
+}
+
+.row-fluid .offset4 {
+ margin-left: 36.170212765957444%;
+ *margin-left: 36.06382978723405%;
+}
+
+.row-fluid .offset4:first-child {
+ margin-left: 34.04255319148936%;
+ *margin-left: 33.93617021276596%;
+}
+
+.row-fluid .offset3 {
+ margin-left: 27.659574468085104%;
+ *margin-left: 27.5531914893617%;
+}
+
+.row-fluid .offset3:first-child {
+ margin-left: 25.53191489361702%;
+ *margin-left: 25.425531914893618%;
+}
+
+.row-fluid .offset2 {
+ margin-left: 19.148936170212764%;
+ *margin-left: 19.04255319148936%;
+}
+
+.row-fluid .offset2:first-child {
+ margin-left: 17.02127659574468%;
+ *margin-left: 16.914893617021278%;
+}
+
+.row-fluid .offset1 {
+ margin-left: 10.638297872340425%;
+ *margin-left: 10.53191489361702%;
+}
+
+.row-fluid .offset1:first-child {
+ margin-left: 8.51063829787234%;
+ *margin-left: 8.404255319148938%;
+}
+
+[class*="span"].hide,
+.row-fluid [class*="span"].hide {
+ display: none;
+}
+
+[class*="span"].pull-right,
+.row-fluid [class*="span"].pull-right {
+ float: right;
+}
+
+.container {
+ margin-right: auto;
+ margin-left: auto;
+ *zoom: 1;
+}
+
+.container:before,
+.container:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.container:after {
+ clear: both;
+}
+
+.container-fluid {
+ padding-right: 20px;
+ padding-left: 20px;
+ *zoom: 1;
+}
+
+.container-fluid:before,
+.container-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.container-fluid:after {
+ clear: both;
+}
+
+p {
+ margin: 0 0 10px;
+}
+
+.lead {
+ margin-bottom: 20px;
+ font-size: 21px;
+ font-weight: 200;
+ line-height: 30px;
+}
+
+small {
+ font-size: 85%;
+}
+
+strong {
+ font-weight: bold;
+}
+
+em {
+ font-style: italic;
+}
+
+cite {
+ font-style: normal;
+}
+
+.muted {
+ color: #999999;
+}
+
+.text-warning {
+ color: #c09853;
+}
+
+a.text-warning:hover {
+ color: #a47e3c;
+}
+
+.text-error {
+ color: #b94a48;
+}
+
+a.text-error:hover {
+ color: #953b39;
+}
+
+.text-info {
+ color: #3a87ad;
+}
+
+a.text-info:hover {
+ color: #2d6987;
+}
+
+.text-success {
+ color: #468847;
+}
+
+a.text-success:hover {
+ color: #356635;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin: 10px 0;
+ font-family: inherit;
+ font-weight: bold;
+ line-height: 20px;
+ color: inherit;
+ text-rendering: optimizelegibility;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small {
+ font-weight: normal;
+ line-height: 1;
+ color: #999999;
+}
+
+h1,
+h2,
+h3 {
+ line-height: 40px;
+}
+
+h1 {
+ font-size: 38.5px;
+}
+
+h2 {
+ font-size: 31.5px;
+}
+
+h3 {
+ font-size: 24.5px;
+}
+
+h4 {
+ font-size: 17.5px;
+}
+
+h5 {
+ font-size: 14px;
+}
+
+h6 {
+ font-size: 11.9px;
+}
+
+h1 small {
+ font-size: 24.5px;
+}
+
+h2 small {
+ font-size: 17.5px;
+}
+
+h3 small {
+ font-size: 14px;
+}
+
+h4 small {
+ font-size: 14px;
+}
+
+.page-header {
+ padding-bottom: 9px;
+ margin: 20px 0 30px;
+ border-bottom: 1px solid #eeeeee;
+}
+
+ul,
+ol {
+ padding: 0;
+ margin: 0 0 10px 25px;
+}
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin-bottom: 0;
+}
+
+li {
+ line-height: 20px;
+}
+
+ul.unstyled,
+ol.unstyled {
+ margin-left: 0;
+ list-style: none;
+}
+
+dl {
+ margin-bottom: 20px;
+}
+
+dt,
+dd {
+ line-height: 20px;
+}
+
+dt {
+ font-weight: bold;
+}
+
+dd {
+ margin-left: 10px;
+}
+
+.dl-horizontal {
+ *zoom: 1;
+}
+
+.dl-horizontal:before,
+.dl-horizontal:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.dl-horizontal:after {
+ clear: both;
+}
+
+.dl-horizontal dt {
+ float: left;
+ width: 160px;
+ overflow: hidden;
+ clear: left;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.dl-horizontal dd {
+ margin-left: 180px;
+}
+
+hr {
+ margin: 20px 0;
+ border: 0;
+ border-top: 1px solid #eeeeee;
+ border-bottom: 1px solid #ffffff;
+}
+
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #999999;
+}
+
+abbr.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+
+blockquote {
+ padding: 0 0 0 15px;
+ margin: 0 0 20px;
+ border-left: 5px solid #eeeeee;
+}
+
+blockquote p {
+ margin-bottom: 0;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 25px;
+}
+
+blockquote small {
+ display: block;
+ line-height: 20px;
+ color: #999999;
+}
+
+blockquote small:before {
+ content: '\2014 \00A0';
+}
+
+blockquote.pull-right {
+ float: right;
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid #eeeeee;
+ border-left: 0;
+}
+
+blockquote.pull-right p,
+blockquote.pull-right small {
+ text-align: right;
+}
+
+blockquote.pull-right small:before {
+ content: '';
+}
+
+blockquote.pull-right small:after {
+ content: '\00A0 \2014';
+}
+
+q:before,
+q:after,
+blockquote:before,
+blockquote:after {
+ content: "";
+}
+
+address {
+ display: block;
+ margin-bottom: 20px;
+ font-style: normal;
+ line-height: 20px;
+}
+
+code,
+pre {
+ padding: 0 3px 2px;
+ font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
+ font-size: 12px;
+ color: #333333;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+code {
+ padding: 2px 4px;
+ color: #d14;
+ background-color: #f7f7f9;
+ border: 1px solid #e1e1e8;
+}
+
+pre {
+ display: block;
+ padding: 9.5px;
+ margin: 0 0 10px;
+ font-size: 13px;
+ line-height: 20px;
+ word-break: break-all;
+ word-wrap: break-word;
+ white-space: pre;
+ white-space: pre-wrap;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+pre.prettyprint {
+ margin-bottom: 20px;
+}
+
+pre code {
+ padding: 0;
+ color: inherit;
+ background-color: transparent;
+ border: 0;
+}
+
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+
+form {
+ margin: 0 0 20px;
+}
+
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 20px;
+ font-size: 21px;
+ line-height: 40px;
+ color: #333333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+legend small {
+ font-size: 15px;
+ color: #999999;
+}
+
+label,
+input,
+button,
+select,
+textarea {
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 20px;
+}
+
+input,
+button,
+select,
+textarea {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+}
+
+select,
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+ display: inline-block;
+ height: 20px;
+ padding: 4px 6px;
+ margin-bottom: 10px;
+ font-size: 14px;
+ line-height: 20px;
+ color: #555555;
+ vertical-align: middle;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+input,
+textarea,
+.uneditable-input {
+ width: 206px;
+}
+
+textarea {
+ height: auto;
+}
+
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+ transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+textarea:focus,
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="date"]:focus,
+input[type="month"]:focus,
+input[type="time"]:focus,
+input[type="week"]:focus,
+input[type="number"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+input[type="search"]:focus,
+input[type="tel"]:focus,
+input[type="color"]:focus,
+.uneditable-input:focus {
+ border-color: rgba(82, 168, 236, 0.8);
+ outline: 0;
+ outline: thin dotted \9;
+ /* IE6-9 */
+
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ *margin-top: 0;
+ line-height: normal;
+ cursor: pointer;
+}
+
+input[type="file"],
+input[type="image"],
+input[type="submit"],
+input[type="reset"],
+input[type="button"],
+input[type="radio"],
+input[type="checkbox"] {
+ width: auto;
+}
+
+select,
+input[type="file"] {
+ height: 30px;
+ /* In IE7, the height of the select element cannot be changed by height, only font-size */
+
+ *margin-top: 4px;
+ /* For IE7, add top margin to align select with labels */
+
+ line-height: 30px;
+}
+
+select {
+ width: 220px;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+}
+
+select[multiple],
+select[size] {
+ height: auto;
+}
+
+select:focus,
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.uneditable-input,
+.uneditable-textarea {
+ color: #999999;
+ cursor: not-allowed;
+ background-color: #fcfcfc;
+ border-color: #cccccc;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+}
+
+.uneditable-input {
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.uneditable-textarea {
+ width: auto;
+ height: auto;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+ color: #999999;
+}
+
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #999999;
+}
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+ color: #999999;
+}
+
+.radio,
+.checkbox {
+ min-height: 20px;
+ padding-left: 20px;
+}
+
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+ float: left;
+ margin-left: -20px;
+}
+
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+ padding-top: 5px;
+}
+
+.radio.inline,
+.checkbox.inline {
+ display: inline-block;
+ padding-top: 5px;
+ margin-bottom: 0;
+ vertical-align: middle;
+}
+
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+ margin-left: 10px;
+}
+
+.input-mini {
+ width: 60px;
+}
+
+.input-small {
+ width: 90px;
+}
+
+.input-medium {
+ width: 150px;
+}
+
+.input-large {
+ width: 210px;
+}
+
+.input-xlarge {
+ width: 270px;
+}
+
+.input-xxlarge {
+ width: 530px;
+}
+
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"] {
+ float: none;
+ margin-left: 0;
+}
+
+.input-append input[class*="span"],
+.input-append .uneditable-input[class*="span"],
+.input-prepend input[class*="span"],
+.input-prepend .uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"],
+.row-fluid .input-prepend [class*="span"],
+.row-fluid .input-append [class*="span"] {
+ display: inline-block;
+}
+
+input,
+textarea,
+.uneditable-input {
+ margin-left: 0;
+}
+
+.controls-row [class*="span"] + [class*="span"] {
+ margin-left: 20px;
+}
+
+input.span12,
+textarea.span12,
+.uneditable-input.span12 {
+ width: 926px;
+}
+
+input.span11,
+textarea.span11,
+.uneditable-input.span11 {
+ width: 846px;
+}
+
+input.span10,
+textarea.span10,
+.uneditable-input.span10 {
+ width: 766px;
+}
+
+input.span9,
+textarea.span9,
+.uneditable-input.span9 {
+ width: 686px;
+}
+
+input.span8,
+textarea.span8,
+.uneditable-input.span8 {
+ width: 606px;
+}
+
+input.span7,
+textarea.span7,
+.uneditable-input.span7 {
+ width: 526px;
+}
+
+input.span6,
+textarea.span6,
+.uneditable-input.span6 {
+ width: 446px;
+}
+
+input.span5,
+textarea.span5,
+.uneditable-input.span5 {
+ width: 366px;
+}
+
+input.span4,
+textarea.span4,
+.uneditable-input.span4 {
+ width: 286px;
+}
+
+input.span3,
+textarea.span3,
+.uneditable-input.span3 {
+ width: 206px;
+}
+
+input.span2,
+textarea.span2,
+.uneditable-input.span2 {
+ width: 126px;
+}
+
+input.span1,
+textarea.span1,
+.uneditable-input.span1 {
+ width: 46px;
+}
+
+.controls-row {
+ *zoom: 1;
+}
+
+.controls-row:before,
+.controls-row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.controls-row:after {
+ clear: both;
+}
+
+.controls-row [class*="span"],
+.row-fluid .controls-row [class*="span"] {
+ float: left;
+}
+
+.controls-row .checkbox[class*="span"],
+.controls-row .radio[class*="span"] {
+ padding-top: 5px;
+}
+
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+ cursor: not-allowed;
+ background-color: #eeeeee;
+}
+
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"][readonly],
+input[type="checkbox"][readonly] {
+ background-color: transparent;
+}
+
+.control-group.warning > label,
+.control-group.warning .help-block,
+.control-group.warning .help-inline {
+ color: #c09853;
+}
+
+.control-group.warning .checkbox,
+.control-group.warning .radio,
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+ color: #c09853;
+}
+
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+ border-color: #c09853;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.warning input:focus,
+.control-group.warning select:focus,
+.control-group.warning textarea:focus {
+ border-color: #a47e3c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+}
+
+.control-group.warning .input-prepend .add-on,
+.control-group.warning .input-append .add-on {
+ color: #c09853;
+ background-color: #fcf8e3;
+ border-color: #c09853;
+}
+
+.control-group.error > label,
+.control-group.error .help-block,
+.control-group.error .help-inline {
+ color: #b94a48;
+}
+
+.control-group.error .checkbox,
+.control-group.error .radio,
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+ color: #b94a48;
+}
+
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+ border-color: #b94a48;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.error input:focus,
+.control-group.error select:focus,
+.control-group.error textarea:focus {
+ border-color: #953b39;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+}
+
+.control-group.error .input-prepend .add-on,
+.control-group.error .input-append .add-on {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #b94a48;
+}
+
+.control-group.success > label,
+.control-group.success .help-block,
+.control-group.success .help-inline {
+ color: #468847;
+}
+
+.control-group.success .checkbox,
+.control-group.success .radio,
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+ color: #468847;
+}
+
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+ border-color: #468847;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.success input:focus,
+.control-group.success select:focus,
+.control-group.success textarea:focus {
+ border-color: #356635;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+}
+
+.control-group.success .input-prepend .add-on,
+.control-group.success .input-append .add-on {
+ color: #468847;
+ background-color: #dff0d8;
+ border-color: #468847;
+}
+
+.control-group.info > label,
+.control-group.info .help-block,
+.control-group.info .help-inline {
+ color: #3a87ad;
+}
+
+.control-group.info .checkbox,
+.control-group.info .radio,
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+ color: #3a87ad;
+}
+
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+ border-color: #3a87ad;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.info input:focus,
+.control-group.info select:focus,
+.control-group.info textarea:focus {
+ border-color: #2d6987;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+}
+
+.control-group.info .input-prepend .add-on,
+.control-group.info .input-append .add-on {
+ color: #3a87ad;
+ background-color: #d9edf7;
+ border-color: #3a87ad;
+}
+
+input:focus:required:invalid,
+textarea:focus:required:invalid,
+select:focus:required:invalid {
+ color: #b94a48;
+ border-color: #ee5f5b;
+}
+
+input:focus:required:invalid:focus,
+textarea:focus:required:invalid:focus,
+select:focus:required:invalid:focus {
+ border-color: #e9322d;
+ -webkit-box-shadow: 0 0 6px #f8b9b7;
+ -moz-box-shadow: 0 0 6px #f8b9b7;
+ box-shadow: 0 0 6px #f8b9b7;
+}
+
+.form-actions {
+ padding: 19px 20px 20px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #e5e5e5;
+ *zoom: 1;
+}
+
+.form-actions:before,
+.form-actions:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.form-actions:after {
+ clear: both;
+}
+
+.help-block,
+.help-inline {
+ color: #595959;
+}
+
+.help-block {
+ display: block;
+ margin-bottom: 10px;
+}
+
+.help-inline {
+ display: inline-block;
+ *display: inline;
+ padding-left: 5px;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.input-append,
+.input-prepend {
+ margin-bottom: 5px;
+ font-size: 0;
+ white-space: nowrap;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input,
+.input-append .dropdown-menu,
+.input-prepend .dropdown-menu {
+ font-size: 14px;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input {
+ position: relative;
+ margin-bottom: 0;
+ *margin-left: 0;
+ vertical-align: top;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-append input:focus,
+.input-prepend input:focus,
+.input-append select:focus,
+.input-prepend select:focus,
+.input-append .uneditable-input:focus,
+.input-prepend .uneditable-input:focus {
+ z-index: 2;
+}
+
+.input-append .add-on,
+.input-prepend .add-on {
+ display: inline-block;
+ width: auto;
+ height: 20px;
+ min-width: 16px;
+ padding: 4px 5px;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 20px;
+ text-align: center;
+ text-shadow: 0 1px 0 #ffffff;
+ background-color: #eeeeee;
+ border: 1px solid #ccc;
+}
+
+.input-append .add-on,
+.input-prepend .add-on,
+.input-append .btn,
+.input-prepend .btn {
+ vertical-align: top;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.input-append .active,
+.input-prepend .active {
+ background-color: #a9dba9;
+ border-color: #46a546;
+}
+
+.input-prepend .add-on,
+.input-prepend .btn {
+ margin-right: -1px;
+}
+
+.input-prepend .add-on:first-child,
+.input-prepend .btn:first-child {
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-append input,
+.input-append select,
+.input-append .uneditable-input {
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-append input + .btn-group .btn,
+.input-append select + .btn-group .btn,
+.input-append .uneditable-input + .btn-group .btn {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-append .add-on,
+.input-append .btn,
+.input-append .btn-group {
+ margin-left: -1px;
+}
+
+.input-append .add-on:last-child,
+.input-append .btn:last-child {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append input,
+.input-prepend.input-append select,
+.input-prepend.input-append .uneditable-input {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.input-prepend.input-append input + .btn-group .btn,
+.input-prepend.input-append select + .btn-group .btn,
+.input-prepend.input-append .uneditable-input + .btn-group .btn {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .add-on:first-child,
+.input-prepend.input-append .btn:first-child {
+ margin-right: -1px;
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-prepend.input-append .add-on:last-child,
+.input-prepend.input-append .btn:last-child {
+ margin-left: -1px;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .btn-group:first-child {
+ margin-left: 0;
+}
+
+input.search-query {
+ padding-right: 14px;
+ padding-right: 4px \9;
+ padding-left: 14px;
+ padding-left: 4px \9;
+ /* IE7-8 doesn't have border-radius, so don't indent the padding */
+
+ margin-bottom: 0;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+/* Allow for input prepend/append in search forms */
+
+.form-search .input-append .search-query,
+.form-search .input-prepend .search-query {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.form-search .input-append .search-query {
+ -webkit-border-radius: 14px 0 0 14px;
+ -moz-border-radius: 14px 0 0 14px;
+ border-radius: 14px 0 0 14px;
+}
+
+.form-search .input-append .btn {
+ -webkit-border-radius: 0 14px 14px 0;
+ -moz-border-radius: 0 14px 14px 0;
+ border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .search-query {
+ -webkit-border-radius: 0 14px 14px 0;
+ -moz-border-radius: 0 14px 14px 0;
+ border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .btn {
+ -webkit-border-radius: 14px 0 0 14px;
+ -moz-border-radius: 14px 0 0 14px;
+ border-radius: 14px 0 0 14px;
+}
+
+.form-search input,
+.form-inline input,
+.form-horizontal input,
+.form-search textarea,
+.form-inline textarea,
+.form-horizontal textarea,
+.form-search select,
+.form-inline select,
+.form-horizontal select,
+.form-search .help-inline,
+.form-inline .help-inline,
+.form-horizontal .help-inline,
+.form-search .uneditable-input,
+.form-inline .uneditable-input,
+.form-horizontal .uneditable-input,
+.form-search .input-prepend,
+.form-inline .input-prepend,
+.form-horizontal .input-prepend,
+.form-search .input-append,
+.form-inline .input-append,
+.form-horizontal .input-append {
+ display: inline-block;
+ *display: inline;
+ margin-bottom: 0;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.form-search .hide,
+.form-inline .hide,
+.form-horizontal .hide {
+ display: none;
+}
+
+.form-search label,
+.form-inline label,
+.form-search .btn-group,
+.form-inline .btn-group {
+ display: inline-block;
+}
+
+.form-search .input-append,
+.form-inline .input-append,
+.form-search .input-prepend,
+.form-inline .input-prepend {
+ margin-bottom: 0;
+}
+
+.form-search .radio,
+.form-search .checkbox,
+.form-inline .radio,
+.form-inline .checkbox {
+ padding-left: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+}
+
+.form-search .radio input[type="radio"],
+.form-search .checkbox input[type="checkbox"],
+.form-inline .radio input[type="radio"],
+.form-inline .checkbox input[type="checkbox"] {
+ float: left;
+ margin-right: 3px;
+ margin-left: 0;
+}
+
+.control-group {
+ margin-bottom: 10px;
+}
+
+legend + .control-group {
+ margin-top: 20px;
+ -webkit-margin-top-collapse: separate;
+}
+
+.form-horizontal .control-group {
+ margin-bottom: 20px;
+ *zoom: 1;
+}
+
+.form-horizontal .control-group:before,
+.form-horizontal .control-group:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.form-horizontal .control-group:after {
+ clear: both;
+}
+
+.form-horizontal .control-label {
+ float: left;
+ width: 160px;
+ padding-top: 5px;
+ text-align: right;
+}
+
+.form-horizontal .controls {
+ *display: inline-block;
+ *padding-left: 20px;
+ margin-left: 180px;
+ *margin-left: 0;
+}
+
+.form-horizontal .controls:first-child {
+ *padding-left: 180px;
+}
+
+.form-horizontal .help-block {
+ margin-bottom: 0;
+}
+
+.form-horizontal input + .help-block,
+.form-horizontal select + .help-block,
+.form-horizontal textarea + .help-block {
+ margin-top: 10px;
+}
+
+.form-horizontal .form-actions {
+ padding-left: 180px;
+}
+
+table {
+ max-width: 100%;
+ background-color: transparent;
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+.table {
+ width: 100%;
+ margin-bottom: 20px;
+}
+
+.table th,
+.table td {
+ padding: 8px;
+ line-height: 20px;
+ text-align: left;
+ vertical-align: top;
+ border-top: 1px solid #dddddd;
+}
+
+.table th {
+ font-weight: bold;
+}
+
+.table thead th {
+ vertical-align: bottom;
+}
+
+.table caption + thead tr:first-child th,
+.table caption + thead tr:first-child td,
+.table colgroup + thead tr:first-child th,
+.table colgroup + thead tr:first-child td,
+.table thead:first-child tr:first-child th,
+.table thead:first-child tr:first-child td {
+ border-top: 0;
+}
+
+.table tbody + tbody {
+ border-top: 2px solid #dddddd;
+}
+
+.table-condensed th,
+.table-condensed td {
+ padding: 4px 5px;
+}
+
+.table-bordered {
+ border: 1px solid #dddddd;
+ border-collapse: separate;
+ *border-collapse: collapse;
+ border-left: 0;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.table-bordered th,
+.table-bordered td {
+ border-left: 1px solid #dddddd;
+}
+
+.table-bordered caption + thead tr:first-child th,
+.table-bordered caption + tbody tr:first-child th,
+.table-bordered caption + tbody tr:first-child td,
+.table-bordered colgroup + thead tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child td,
+.table-bordered thead:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child td {
+ border-top: 0;
+}
+
+.table-bordered thead:first-child tr:first-child th:first-child,
+.table-bordered tbody:first-child tr:first-child td:first-child {
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered thead:first-child tr:first-child th:last-child,
+.table-bordered tbody:first-child tr:first-child td:last-child {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child th:first-child,
+.table-bordered tbody:last-child tr:last-child td:first-child,
+.table-bordered tfoot:last-child tr:last-child td:first-child {
+ -webkit-border-radius: 0 0 0 4px;
+ -moz-border-radius: 0 0 0 4px;
+ border-radius: 0 0 0 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child th:last-child,
+.table-bordered tbody:last-child tr:last-child td:last-child,
+.table-bordered tfoot:last-child tr:last-child td:last-child {
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.table-bordered caption + thead tr:first-child th:first-child,
+.table-bordered caption + tbody tr:first-child td:first-child,
+.table-bordered colgroup + thead tr:first-child th:first-child,
+.table-bordered colgroup + tbody tr:first-child td:first-child {
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered caption + thead tr:first-child th:last-child,
+.table-bordered caption + tbody tr:first-child td:last-child,
+.table-bordered colgroup + thead tr:first-child th:last-child,
+.table-bordered colgroup + tbody tr:first-child td:last-child {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+}
+
+.table-striped tbody tr:nth-child(odd) td,
+.table-striped tbody tr:nth-child(odd) th {
+ background-color: #f9f9f9;
+}
+
+.table-hover tbody tr:hover td,
+.table-hover tbody tr:hover th {
+ background-color: #f5f5f5;
+}
+
+table td[class*="span"],
+table th[class*="span"],
+.row-fluid table td[class*="span"],
+.row-fluid table th[class*="span"] {
+ display: table-cell;
+ float: none;
+ margin-left: 0;
+}
+
+.table td.span1,
+.table th.span1 {
+ float: none;
+ width: 44px;
+ margin-left: 0;
+}
+
+.table td.span2,
+.table th.span2 {
+ float: none;
+ width: 124px;
+ margin-left: 0;
+}
+
+.table td.span3,
+.table th.span3 {
+ float: none;
+ width: 204px;
+ margin-left: 0;
+}
+
+.table td.span4,
+.table th.span4 {
+ float: none;
+ width: 284px;
+ margin-left: 0;
+}
+
+.table td.span5,
+.table th.span5 {
+ float: none;
+ width: 364px;
+ margin-left: 0;
+}
+
+.table td.span6,
+.table th.span6 {
+ float: none;
+ width: 444px;
+ margin-left: 0;
+}
+
+.table td.span7,
+.table th.span7 {
+ float: none;
+ width: 524px;
+ margin-left: 0;
+}
+
+.table td.span8,
+.table th.span8 {
+ float: none;
+ width: 604px;
+ margin-left: 0;
+}
+
+.table td.span9,
+.table th.span9 {
+ float: none;
+ width: 684px;
+ margin-left: 0;
+}
+
+.table td.span10,
+.table th.span10 {
+ float: none;
+ width: 764px;
+ margin-left: 0;
+}
+
+.table td.span11,
+.table th.span11 {
+ float: none;
+ width: 844px;
+ margin-left: 0;
+}
+
+.table td.span12,
+.table th.span12 {
+ float: none;
+ width: 924px;
+ margin-left: 0;
+}
+
+.table tbody tr.success td {
+ background-color: #dff0d8;
+}
+
+.table tbody tr.error td {
+ background-color: #f2dede;
+}
+
+.table tbody tr.warning td {
+ background-color: #fcf8e3;
+}
+
+.table tbody tr.info td {
+ background-color: #d9edf7;
+}
+
+.table-hover tbody tr.success:hover td {
+ background-color: #d0e9c6;
+}
+
+.table-hover tbody tr.error:hover td {
+ background-color: #ebcccc;
+}
+
+.table-hover tbody tr.warning:hover td {
+ background-color: #faf2cc;
+}
+
+.table-hover tbody tr.info:hover td {
+ background-color: #c4e3f3;
+}
+
+[class^="icon-"],
+[class*=" icon-"] {
+ display: inline-block;
+ width: 14px;
+ height: 14px;
+ margin-top: 1px;
+ *margin-right: .3em;
+ line-height: 14px;
+ vertical-align: text-top;
+ background-image: url("../img/glyphicons-halflings.png");
+ background-position: 14px 14px;
+ background-repeat: no-repeat;
+}
+
+/* White icons with optional class, or on hover/active states of certain elements */
+
+.icon-white,
+.nav-pills > .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"] {
+ background-image: url("../img/glyphicons-halflings-white.png");
+}
+
+.icon-glass {
+ background-position: 0 0;
+}
+
+.icon-music {
+ background-position: -24px 0;
+}
+
+.icon-search {
+ background-position: -48px 0;
+}
+
+.icon-envelope {
+ background-position: -72px 0;
+}
+
+.icon-heart {
+ background-position: -96px 0;
+}
+
+.icon-star {
+ background-position: -120px 0;
+}
+
+.icon-star-empty {
+ background-position: -144px 0;
+}
+
+.icon-user {
+ background-position: -168px 0;
+}
+
+.icon-film {
+ background-position: -192px 0;
+}
+
+.icon-th-large {
+ background-position: -216px 0;
+}
+
+.icon-th {
+ background-position: -240px 0;
+}
+
+.icon-th-list {
+ background-position: -264px 0;
+}
+
+.icon-ok {
+ background-position: -288px 0;
+}
+
+.icon-remove {
+ background-position: -312px 0;
+}
+
+.icon-zoom-in {
+ background-position: -336px 0;
+}
+
+.icon-zoom-out {
+ background-position: -360px 0;
+}
+
+.icon-off {
+ background-position: -384px 0;
+}
+
+.icon-signal {
+ background-position: -408px 0;
+}
+
+.icon-cog {
+ background-position: -432px 0;
+}
+
+.icon-trash {
+ background-position: -456px 0;
+}
+
+.icon-home {
+ background-position: 0 -24px;
+}
+
+.icon-file {
+ background-position: -24px -24px;
+}
+
+.icon-time {
+ background-position: -48px -24px;
+}
+
+.icon-road {
+ background-position: -72px -24px;
+}
+
+.icon-download-alt {
+ background-position: -96px -24px;
+}
+
+.icon-download {
+ background-position: -120px -24px;
+}
+
+.icon-upload {
+ background-position: -144px -24px;
+}
+
+.icon-inbox {
+ background-position: -168px -24px;
+}
+
+.icon-play-circle {
+ background-position: -192px -24px;
+}
+
+.icon-repeat {
+ background-position: -216px -24px;
+}
+
+.icon-refresh {
+ background-position: -240px -24px;
+}
+
+.icon-list-alt {
+ background-position: -264px -24px;
+}
+
+.icon-lock {
+ background-position: -287px -24px;
+}
+
+.icon-flag {
+ background-position: -312px -24px;
+}
+
+.icon-headphones {
+ background-position: -336px -24px;
+}
+
+.icon-volume-off {
+ background-position: -360px -24px;
+}
+
+.icon-volume-down {
+ background-position: -384px -24px;
+}
+
+.icon-volume-up {
+ background-position: -408px -24px;
+}
+
+.icon-qrcode {
+ background-position: -432px -24px;
+}
+
+.icon-barcode {
+ background-position: -456px -24px;
+}
+
+.icon-tag {
+ background-position: 0 -48px;
+}
+
+.icon-tags {
+ background-position: -25px -48px;
+}
+
+.icon-book {
+ background-position: -48px -48px;
+}
+
+.icon-bookmark {
+ background-position: -72px -48px;
+}
+
+.icon-print {
+ background-position: -96px -48px;
+}
+
+.icon-camera {
+ background-position: -120px -48px;
+}
+
+.icon-font {
+ background-position: -144px -48px;
+}
+
+.icon-bold {
+ background-position: -167px -48px;
+}
+
+.icon-italic {
+ background-position: -192px -48px;
+}
+
+.icon-text-height {
+ background-position: -216px -48px;
+}
+
+.icon-text-width {
+ background-position: -240px -48px;
+}
+
+.icon-align-left {
+ background-position: -264px -48px;
+}
+
+.icon-align-center {
+ background-position: -288px -48px;
+}
+
+.icon-align-right {
+ background-position: -312px -48px;
+}
+
+.icon-align-justify {
+ background-position: -336px -48px;
+}
+
+.icon-list {
+ background-position: -360px -48px;
+}
+
+.icon-indent-left {
+ background-position: -384px -48px;
+}
+
+.icon-indent-right {
+ background-position: -408px -48px;
+}
+
+.icon-facetime-video {
+ background-position: -432px -48px;
+}
+
+.icon-picture {
+ background-position: -456px -48px;
+}
+
+.icon-pencil {
+ background-position: 0 -72px;
+}
+
+.icon-map-marker {
+ background-position: -24px -72px;
+}
+
+.icon-adjust {
+ background-position: -48px -72px;
+}
+
+.icon-tint {
+ background-position: -72px -72px;
+}
+
+.icon-edit {
+ background-position: -96px -72px;
+}
+
+.icon-share {
+ background-position: -120px -72px;
+}
+
+.icon-check {
+ background-position: -144px -72px;
+}
+
+.icon-move {
+ background-position: -168px -72px;
+}
+
+.icon-step-backward {
+ background-position: -192px -72px;
+}
+
+.icon-fast-backward {
+ background-position: -216px -72px;
+}
+
+.icon-backward {
+ background-position: -240px -72px;
+}
+
+.icon-play {
+ background-position: -264px -72px;
+}
+
+.icon-pause {
+ background-position: -288px -72px;
+}
+
+.icon-stop {
+ background-position: -312px -72px;
+}
+
+.icon-forward {
+ background-position: -336px -72px;
+}
+
+.icon-fast-forward {
+ background-position: -360px -72px;
+}
+
+.icon-step-forward {
+ background-position: -384px -72px;
+}
+
+.icon-eject {
+ background-position: -408px -72px;
+}
+
+.icon-chevron-left {
+ background-position: -432px -72px;
+}
+
+.icon-chevron-right {
+ background-position: -456px -72px;
+}
+
+.icon-plus-sign {
+ background-position: 0 -96px;
+}
+
+.icon-minus-sign {
+ background-position: -24px -96px;
+}
+
+.icon-remove-sign {
+ background-position: -48px -96px;
+}
+
+.icon-ok-sign {
+ background-position: -72px -96px;
+}
+
+.icon-question-sign {
+ background-position: -96px -96px;
+}
+
+.icon-info-sign {
+ background-position: -120px -96px;
+}
+
+.icon-screenshot {
+ background-position: -144px -96px;
+}
+
+.icon-remove-circle {
+ background-position: -168px -96px;
+}
+
+.icon-ok-circle {
+ background-position: -192px -96px;
+}
+
+.icon-ban-circle {
+ background-position: -216px -96px;
+}
+
+.icon-arrow-left {
+ background-position: -240px -96px;
+}
+
+.icon-arrow-right {
+ background-position: -264px -96px;
+}
+
+.icon-arrow-up {
+ background-position: -289px -96px;
+}
+
+.icon-arrow-down {
+ background-position: -312px -96px;
+}
+
+.icon-share-alt {
+ background-position: -336px -96px;
+}
+
+.icon-resize-full {
+ background-position: -360px -96px;
+}
+
+.icon-resize-small {
+ background-position: -384px -96px;
+}
+
+.icon-plus {
+ background-position: -408px -96px;
+}
+
+.icon-minus {
+ background-position: -433px -96px;
+}
+
+.icon-asterisk {
+ background-position: -456px -96px;
+}
+
+.icon-exclamation-sign {
+ background-position: 0 -120px;
+}
+
+.icon-gift {
+ background-position: -24px -120px;
+}
+
+.icon-leaf {
+ background-position: -48px -120px;
+}
+
+.icon-fire {
+ background-position: -72px -120px;
+}
+
+.icon-eye-open {
+ background-position: -96px -120px;
+}
+
+.icon-eye-close {
+ background-position: -120px -120px;
+}
+
+.icon-warning-sign {
+ background-position: -144px -120px;
+}
+
+.icon-plane {
+ background-position: -168px -120px;
+}
+
+.icon-calendar {
+ background-position: -192px -120px;
+}
+
+.icon-random {
+ width: 16px;
+ background-position: -216px -120px;
+}
+
+.icon-comment {
+ background-position: -240px -120px;
+}
+
+.icon-magnet {
+ background-position: -264px -120px;
+}
+
+.icon-chevron-up {
+ background-position: -288px -120px;
+}
+
+.icon-chevron-down {
+ background-position: -313px -119px;
+}
+
+.icon-retweet {
+ background-position: -336px -120px;
+}
+
+.icon-shopping-cart {
+ background-position: -360px -120px;
+}
+
+.icon-folder-close {
+ background-position: -384px -120px;
+}
+
+.icon-folder-open {
+ width: 16px;
+ background-position: -408px -120px;
+}
+
+.icon-resize-vertical {
+ background-position: -432px -119px;
+}
+
+.icon-resize-horizontal {
+ background-position: -456px -118px;
+}
+
+.icon-hdd {
+ background-position: 0 -144px;
+}
+
+.icon-bullhorn {
+ background-position: -24px -144px;
+}
+
+.icon-bell {
+ background-position: -48px -144px;
+}
+
+.icon-certificate {
+ background-position: -72px -144px;
+}
+
+.icon-thumbs-up {
+ background-position: -96px -144px;
+}
+
+.icon-thumbs-down {
+ background-position: -120px -144px;
+}
+
+.icon-hand-right {
+ background-position: -144px -144px;
+}
+
+.icon-hand-left {
+ background-position: -168px -144px;
+}
+
+.icon-hand-up {
+ background-position: -192px -144px;
+}
+
+.icon-hand-down {
+ background-position: -216px -144px;
+}
+
+.icon-circle-arrow-right {
+ background-position: -240px -144px;
+}
+
+.icon-circle-arrow-left {
+ background-position: -264px -144px;
+}
+
+.icon-circle-arrow-up {
+ background-position: -288px -144px;
+}
+
+.icon-circle-arrow-down {
+ background-position: -312px -144px;
+}
+
+.icon-globe {
+ background-position: -336px -144px;
+}
+
+.icon-wrench {
+ background-position: -360px -144px;
+}
+
+.icon-tasks {
+ background-position: -384px -144px;
+}
+
+.icon-filter {
+ background-position: -408px -144px;
+}
+
+.icon-briefcase {
+ background-position: -432px -144px;
+}
+
+.icon-fullscreen {
+ background-position: -456px -144px;
+}
+
+.dropup,
+.dropdown {
+ position: relative;
+}
+
+.dropdown-toggle {
+ *margin-bottom: -3px;
+}
+
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+ outline: 0;
+}
+
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ vertical-align: top;
+ border-top: 4px solid #000000;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+ content: "";
+}
+
+.dropdown .caret {
+ margin-top: 8px;
+ margin-left: 2px;
+}
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ list-style: none;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ *border-right-width: 2px;
+ *border-bottom-width: 2px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+
+.dropdown-menu .divider {
+ *width: 100%;
+ height: 1px;
+ margin: 9px 1px;
+ *margin: -5px 0 5px;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ border-bottom: 1px solid #ffffff;
+}
+
+.dropdown-menu li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 20px;
+ color: #333333;
+ white-space: nowrap;
+}
+
+.dropdown-menu li > a:hover,
+.dropdown-menu li > a:focus,
+.dropdown-submenu:hover > a {
+ color: #ffffff;
+ text-decoration: none;
+ background-color: #0081c2;
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu .active > a,
+.dropdown-menu .active > a:hover {
+ color: #333333;
+ text-decoration: none;
+ background-color: #0081c2;
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+ background-repeat: repeat-x;
+ outline: 0;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu .disabled > a,
+.dropdown-menu .disabled > a:hover {
+ color: #999999;
+}
+
+.dropdown-menu .disabled > a:hover {
+ text-decoration: none;
+ cursor: default;
+ background-color: transparent;
+ background-image: none;
+}
+
+.open {
+ *z-index: 1000;
+}
+
+.open > .dropdown-menu {
+ display: block;
+}
+
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ border-top: 0;
+ border-bottom: 4px solid #000000;
+ content: "";
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 1px;
+}
+
+.dropdown-submenu {
+ position: relative;
+}
+
+.dropdown-submenu > .dropdown-menu {
+ top: 0;
+ left: 100%;
+ margin-top: -6px;
+ margin-left: -1px;
+ -webkit-border-radius: 0 6px 6px 6px;
+ -moz-border-radius: 0 6px 6px 6px;
+ border-radius: 0 6px 6px 6px;
+}
+
+.dropdown-submenu:hover > .dropdown-menu {
+ display: block;
+}
+
+.dropup .dropdown-submenu > .dropdown-menu {
+ top: auto;
+ bottom: 0;
+ margin-top: 0;
+ margin-bottom: -2px;
+ -webkit-border-radius: 5px 5px 5px 0;
+ -moz-border-radius: 5px 5px 5px 0;
+ border-radius: 5px 5px 5px 0;
+}
+
+.dropdown-submenu > a:after {
+ display: block;
+ float: right;
+ width: 0;
+ height: 0;
+ margin-top: 5px;
+ margin-right: -10px;
+ border-color: transparent;
+ border-left-color: #cccccc;
+ border-style: solid;
+ border-width: 5px 0 5px 5px;
+ content: " ";
+}
+
+.dropdown-submenu:hover > a:after {
+ border-left-color: #ffffff;
+}
+
+.dropdown-submenu.pull-left {
+ float: none;
+}
+
+.dropdown-submenu.pull-left > .dropdown-menu {
+ left: -100%;
+ margin-left: 10px;
+ -webkit-border-radius: 6px 0 6px 6px;
+ -moz-border-radius: 6px 0 6px 6px;
+ border-radius: 6px 0 6px 6px;
+}
+
+.dropdown .dropdown-menu .nav-header {
+ padding-right: 20px;
+ padding-left: 20px;
+}
+
+.typeahead {
+ margin-top: 2px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, 0.15);
+}
+
+.well-large {
+ padding: 24px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.well-small {
+ padding: 9px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity 0.15s linear;
+ -moz-transition: opacity 0.15s linear;
+ -o-transition: opacity 0.15s linear;
+ transition: opacity 0.15s linear;
+}
+
+.fade.in {
+ opacity: 1;
+}
+
+.collapse {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition: height 0.35s ease;
+ -moz-transition: height 0.35s ease;
+ -o-transition: height 0.35s ease;
+ transition: height 0.35s ease;
+}
+
+.collapse.in {
+ height: auto;
+}
+
+.close {
+ float: right;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 20px;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+
+.close:hover {
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+
+.btn {
+ display: inline-block;
+ *display: inline;
+ padding: 4px 12px;
+ margin-bottom: 0;
+ *margin-left: .3em;
+ font-size: 14px;
+ line-height: 20px;
+ *line-height: 20px;
+ color: #333333;
+ text-align: center;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+ vertical-align: middle;
+ cursor: pointer;
+ background-color: #f5f5f5;
+ *background-color: #e6e6e6;
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+ background-repeat: repeat-x;
+ border: 1px solid #bbbbbb;
+ *border: 0;
+ border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ border-bottom-color: #a2a2a2;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+ *zoom: 1;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn:hover,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+ color: #333333;
+ background-color: #e6e6e6;
+ *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+ background-color: #cccccc \9;
+}
+
+.btn:first-child {
+ *margin-left: 0;
+}
+
+.btn:hover {
+ color: #333333;
+ text-decoration: none;
+ background-color: #e6e6e6;
+ *background-color: #d9d9d9;
+ /* Buttons in IE7 don't get borders, so darken on hover */
+
+ background-position: 0 -15px;
+ -webkit-transition: background-position 0.1s linear;
+ -moz-transition: background-position 0.1s linear;
+ -o-transition: background-position 0.1s linear;
+ transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+ background-color: #e6e6e6;
+ background-color: #d9d9d9 \9;
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+ cursor: default;
+ background-color: #e6e6e6;
+ background-image: none;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-large {
+ padding: 11px 19px;
+ font-size: 17.5px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.btn-large [class^="icon-"],
+.btn-large [class*=" icon-"] {
+ margin-top: 2px;
+}
+
+.btn-small {
+ padding: 2px 10px;
+ font-size: 11.9px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-small [class^="icon-"],
+.btn-small [class*=" icon-"] {
+ margin-top: 0;
+}
+
+.btn-mini {
+ padding: 1px 6px;
+ font-size: 10.5px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-block {
+ display: block;
+ width: 100%;
+ padding-right: 0;
+ padding-left: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+ color: rgba(255, 255, 255, 0.75);
+}
+
+.btn {
+ border-color: #c5c5c5;
+ border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);
+}
+
+.btn-primary {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #006dcc;
+ *background-color: #0044cc;
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+ background-repeat: repeat-x;
+ border-color: #0044cc #0044cc #002a80;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+ color: #ffffff;
+ background-color: #0044cc;
+ *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+ background-color: #003399 \9;
+}
+
+.btn-warning {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #faa732;
+ *background-color: #f89406;
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
+ background-repeat: repeat-x;
+ border-color: #f89406 #f89406 #ad6704;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+ color: #ffffff;
+ background-color: #f89406;
+ *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+ background-color: #c67605 \9;
+}
+
+.btn-danger {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #da4f49;
+ *background-color: #bd362f;
+ background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+ background-repeat: repeat-x;
+ border-color: #bd362f #bd362f #802420;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+ color: #ffffff;
+ background-color: #bd362f;
+ *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+ background-color: #942a25 \9;
+}
+
+.btn-success {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #5bb75b;
+ *background-color: #51a351;
+ background-image: -moz-linear-gradient(top, #62c462, #51a351);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+ background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+ background-image: -o-linear-gradient(top, #62c462, #51a351);
+ background-image: linear-gradient(to bottom, #62c462, #51a351);
+ background-repeat: repeat-x;
+ border-color: #51a351 #51a351 #387038;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+ color: #ffffff;
+ background-color: #51a351;
+ *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+ background-color: #408140 \9;
+}
+
+.btn-info {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #49afcd;
+ *background-color: #2f96b4;
+ background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+ background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+ background-repeat: repeat-x;
+ border-color: #2f96b4 #2f96b4 #1f6377;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+ color: #ffffff;
+ background-color: #2f96b4;
+ *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+ background-color: #24748c \9;
+}
+
+.btn-inverse {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #363636;
+ *background-color: #222222;
+ background-image: -moz-linear-gradient(top, #444444, #222222);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+ background-image: -webkit-linear-gradient(top, #444444, #222222);
+ background-image: -o-linear-gradient(top, #444444, #222222);
+ background-image: linear-gradient(to bottom, #444444, #222222);
+ background-repeat: repeat-x;
+ border-color: #222222 #222222 #000000;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+ color: #ffffff;
+ background-color: #222222;
+ *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+ background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+ *padding-top: 7px;
+ *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+ *padding-top: 1px;
+ *padding-bottom: 1px;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled] {
+ background-color: transparent;
+ background-image: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-link {
+ color: #0088cc;
+ cursor: pointer;
+ border-color: transparent;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-link:hover {
+ color: #005580;
+ text-decoration: underline;
+ background-color: transparent;
+}
+
+.btn-link[disabled]:hover {
+ color: #333333;
+ text-decoration: none;
+}
+
+.btn-group {
+ position: relative;
+ display: inline-block;
+ *display: inline;
+ *margin-left: .3em;
+ font-size: 0;
+ white-space: nowrap;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.btn-group:first-child {
+ *margin-left: 0;
+}
+
+.btn-group + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-toolbar {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ font-size: 0;
+}
+
+.btn-toolbar .btn + .btn,
+.btn-toolbar .btn-group + .btn,
+.btn-toolbar .btn + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-group > .btn {
+ position: relative;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group > .btn + .btn {
+ margin-left: -1px;
+}
+
+.btn-group > .btn,
+.btn-group > .dropdown-menu {
+ font-size: 14px;
+}
+
+.btn-group > .btn-mini {
+ font-size: 11px;
+}
+
+.btn-group > .btn-small {
+ font-size: 12px;
+}
+
+.btn-group > .btn-large {
+ font-size: 16px;
+}
+
+.btn-group > .btn:first-child {
+ margin-left: 0;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.btn-group > .btn:last-child,
+.btn-group > .dropdown-toggle {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.btn-group > .btn.large:first-child {
+ margin-left: 0;
+ -webkit-border-bottom-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+ -webkit-border-top-left-radius: 6px;
+ border-top-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ -moz-border-radius-topleft: 6px;
+}
+
+.btn-group > .btn.large:last-child,
+.btn-group > .large.dropdown-toggle {
+ -webkit-border-top-right-radius: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ -moz-border-radius-bottomright: 6px;
+}
+
+.btn-group > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group > .btn:active,
+.btn-group > .btn.active {
+ z-index: 2;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+
+.btn-group > .btn + .dropdown-toggle {
+ *padding-top: 5px;
+ padding-right: 8px;
+ *padding-bottom: 5px;
+ padding-left: 8px;
+ -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group > .btn-mini + .dropdown-toggle {
+ *padding-top: 2px;
+ padding-right: 5px;
+ *padding-bottom: 2px;
+ padding-left: 5px;
+}
+
+.btn-group > .btn-small + .dropdown-toggle {
+ *padding-top: 5px;
+ *padding-bottom: 4px;
+}
+
+.btn-group > .btn-large + .dropdown-toggle {
+ *padding-top: 7px;
+ padding-right: 12px;
+ *padding-bottom: 7px;
+ padding-left: 12px;
+}
+
+.btn-group.open .dropdown-toggle {
+ background-image: none;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group.open .btn.dropdown-toggle {
+ background-color: #e6e6e6;
+}
+
+.btn-group.open .btn-primary.dropdown-toggle {
+ background-color: #0044cc;
+}
+
+.btn-group.open .btn-warning.dropdown-toggle {
+ background-color: #f89406;
+}
+
+.btn-group.open .btn-danger.dropdown-toggle {
+ background-color: #bd362f;
+}
+
+.btn-group.open .btn-success.dropdown-toggle {
+ background-color: #51a351;
+}
+
+.btn-group.open .btn-info.dropdown-toggle {
+ background-color: #2f96b4;
+}
+
+.btn-group.open .btn-inverse.dropdown-toggle {
+ background-color: #222222;
+}
+
+.btn .caret {
+ margin-top: 8px;
+ margin-left: 0;
+}
+
+.btn-mini .caret,
+.btn-small .caret,
+.btn-large .caret {
+ margin-top: 6px;
+}
+
+.btn-large .caret {
+ border-top-width: 5px;
+ border-right-width: 5px;
+ border-left-width: 5px;
+}
+
+.dropup .btn-large .caret {
+ border-bottom-width: 5px;
+}
+
+.btn-primary .caret,
+.btn-warning .caret,
+.btn-danger .caret,
+.btn-info .caret,
+.btn-success .caret,
+.btn-inverse .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.btn-group-vertical {
+ display: inline-block;
+ *display: inline;
+ /* IE7 inline-block hack */
+
+ *zoom: 1;
+}
+
+.btn-group-vertical .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group-vertical .btn + .btn {
+ margin-top: -1px;
+ margin-left: 0;
+}
+
+.btn-group-vertical .btn:first-child {
+ -webkit-border-radius: 4px 4px 0 0;
+ -moz-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+.btn-group-vertical .btn:last-child {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.btn-group-vertical .btn-large:first-child {
+ -webkit-border-radius: 6px 6px 0 0;
+ -moz-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+}
+
+.btn-group-vertical .btn-large:last-child {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+}
+
+.alert {
+ padding: 8px 35px 8px 14px;
+ margin-bottom: 20px;
+ color: #c09853;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ background-color: #fcf8e3;
+ border: 1px solid #fbeed5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.alert h4 {
+ margin: 0;
+}
+
+.alert .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ line-height: 20px;
+}
+
+.alert-success {
+ color: #468847;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+
+.alert-danger,
+.alert-error {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #eed3d7;
+}
+
+.alert-info {
+ color: #3a87ad;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+
+.alert-block {
+ padding-top: 14px;
+ padding-bottom: 14px;
+}
+
+.alert-block > p,
+.alert-block > ul {
+ margin-bottom: 0;
+}
+
+.alert-block p + p {
+ margin-top: 5px;
+}
+
+.nav {
+ margin-bottom: 20px;
+ margin-left: 0;
+ list-style: none;
+}
+
+.nav > li > a {
+ display: block;
+}
+
+.nav > li > a:hover {
+ text-decoration: none;
+ background-color: #eeeeee;
+}
+
+.nav > .pull-right {
+ float: right;
+}
+
+.nav-header {
+ display: block;
+ padding: 3px 15px;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 20px;
+ color: #999999;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ text-transform: uppercase;
+}
+
+.nav li + .nav-header {
+ margin-top: 9px;
+}
+
+.nav-list {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-bottom: 0;
+}
+
+.nav-list > li > a,
+.nav-list .nav-header {
+ margin-right: -15px;
+ margin-left: -15px;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.nav-list > li > a {
+ padding: 3px 15px;
+}
+
+.nav-list > .active > a,
+.nav-list > .active > a:hover {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
+ background-color: #0088cc;
+}
+
+.nav-list [class^="icon-"],
+.nav-list [class*=" icon-"] {
+ margin-right: 2px;
+}
+
+.nav-list .divider {
+ *width: 100%;
+ height: 1px;
+ margin: 9px 1px;
+ *margin: -5px 0 5px;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ border-bottom: 1px solid #ffffff;
+}
+
+.nav-tabs,
+.nav-pills {
+ *zoom: 1;
+}
+
+.nav-tabs:before,
+.nav-pills:before,
+.nav-tabs:after,
+.nav-pills:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.nav-tabs:after,
+.nav-pills:after {
+ clear: both;
+}
+
+.nav-tabs > li,
+.nav-pills > li {
+ float: left;
+}
+
+.nav-tabs > li > a,
+.nav-pills > li > a {
+ padding-right: 12px;
+ padding-left: 12px;
+ margin-right: 2px;
+ line-height: 14px;
+}
+
+.nav-tabs {
+ border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs > li {
+ margin-bottom: -1px;
+}
+
+.nav-tabs > li > a {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ line-height: 20px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 4px 4px 0 0;
+ -moz-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+.nav-tabs > li > a:hover {
+ border-color: #eeeeee #eeeeee #dddddd;
+}
+
+.nav-tabs > .active > a,
+.nav-tabs > .active > a:hover {
+ color: #555555;
+ cursor: default;
+ background-color: #ffffff;
+ border: 1px solid #ddd;
+ border-bottom-color: transparent;
+}
+
+.nav-pills > li > a {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+.nav-pills > .active > a,
+.nav-pills > .active > a:hover {
+ color: #ffffff;
+ background-color: #0088cc;
+}
+
+.nav-stacked > li {
+ float: none;
+}
+
+.nav-stacked > li > a {
+ margin-right: 0;
+}
+
+.nav-tabs.nav-stacked {
+ border-bottom: 0;
+}
+
+.nav-tabs.nav-stacked > li > a {
+ border: 1px solid #ddd;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.nav-tabs.nav-stacked > li:first-child > a {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li:last-child > a {
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-border-radius-bottomleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li > a:hover {
+ z-index: 2;
+ border-color: #ddd;
+}
+
+.nav-pills.nav-stacked > li > a {
+ margin-bottom: 3px;
+}
+
+.nav-pills.nav-stacked > li:last-child > a {
+ margin-bottom: 1px;
+}
+
+.nav-tabs .dropdown-menu {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+}
+
+.nav-pills .dropdown-menu {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.nav .dropdown-toggle .caret {
+ margin-top: 6px;
+ border-top-color: #0088cc;
+ border-bottom-color: #0088cc;
+}
+
+.nav .dropdown-toggle:hover .caret {
+ border-top-color: #005580;
+ border-bottom-color: #005580;
+}
+
+/* move down carets for tabs */
+
+.nav-tabs .dropdown-toggle .caret {
+ margin-top: 8px;
+}
+
+.nav .active .dropdown-toggle .caret {
+ border-top-color: #fff;
+ border-bottom-color: #fff;
+}
+
+.nav-tabs .active .dropdown-toggle .caret {
+ border-top-color: #555555;
+ border-bottom-color: #555555;
+}
+
+.nav > .dropdown.active > a:hover {
+ cursor: pointer;
+}
+
+.nav-tabs .open .dropdown-toggle,
+.nav-pills .open .dropdown-toggle,
+.nav > li.dropdown.open.active > a:hover {
+ color: #ffffff;
+ background-color: #999999;
+ border-color: #999999;
+}
+
+.nav li.dropdown.open .caret,
+.nav li.dropdown.open.active .caret,
+.nav li.dropdown.open a:hover .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+
+.tabs-stacked .open > a:hover {
+ border-color: #999999;
+}
+
+.tabbable {
+ *zoom: 1;
+}
+
+.tabbable:before,
+.tabbable:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.tabbable:after {
+ clear: both;
+}
+
+.tab-content {
+ overflow: auto;
+}
+
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
+ border-bottom: 0;
+}
+
+.tab-content > .tab-pane,
+.pill-content > .pill-pane {
+ display: none;
+}
+
+.tab-content > .active,
+.pill-content > .active {
+ display: block;
+}
+
+.tabs-below > .nav-tabs {
+ border-top: 1px solid #ddd;
+}
+
+.tabs-below > .nav-tabs > li {
+ margin-top: -1px;
+ margin-bottom: 0;
+}
+
+.tabs-below > .nav-tabs > li > a {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.tabs-below > .nav-tabs > li > a:hover {
+ border-top-color: #ddd;
+ border-bottom-color: transparent;
+}
+
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover {
+ border-color: transparent #ddd #ddd #ddd;
+}
+
+.tabs-left > .nav-tabs > li,
+.tabs-right > .nav-tabs > li {
+ float: none;
+}
+
+.tabs-left > .nav-tabs > li > a,
+.tabs-right > .nav-tabs > li > a {
+ min-width: 74px;
+ margin-right: 0;
+ margin-bottom: 3px;
+}
+
+.tabs-left > .nav-tabs {
+ float: left;
+ margin-right: 19px;
+ border-right: 1px solid #ddd;
+}
+
+.tabs-left > .nav-tabs > li > a {
+ margin-right: -1px;
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.tabs-left > .nav-tabs > li > a:hover {
+ border-color: #eeeeee #dddddd #eeeeee #eeeeee;
+}
+
+.tabs-left > .nav-tabs .active > a,
+.tabs-left > .nav-tabs .active > a:hover {
+ border-color: #ddd transparent #ddd #ddd;
+ *border-right-color: #ffffff;
+}
+
+.tabs-right > .nav-tabs {
+ float: right;
+ margin-left: 19px;
+ border-left: 1px solid #ddd;
+}
+
+.tabs-right > .nav-tabs > li > a {
+ margin-left: -1px;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.tabs-right > .nav-tabs > li > a:hover {
+ border-color: #eeeeee #eeeeee #eeeeee #dddddd;
+}
+
+.tabs-right > .nav-tabs .active > a,
+.tabs-right > .nav-tabs .active > a:hover {
+ border-color: #ddd #ddd #ddd transparent;
+ *border-left-color: #ffffff;
+}
+
+.nav > .disabled > a {
+ color: #999999;
+}
+
+.nav > .disabled > a:hover {
+ text-decoration: none;
+ cursor: default;
+ background-color: transparent;
+}
+
+.navbar {
+ *position: relative;
+ *z-index: 2;
+ margin-bottom: 20px;
+ overflow: visible;
+ color: #777777;
+}
+
+.navbar-inner {
+ min-height: 40px;
+ padding-right: 20px;
+ padding-left: 20px;
+ background-color: #fafafa;
+ background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
+ background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+ background-repeat: repeat-x;
+ border: 1px solid #d4d4d4;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+ *zoom: 1;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.navbar-inner:before,
+.navbar-inner:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.navbar-inner:after {
+ clear: both;
+}
+
+.navbar .container {
+ width: auto;
+}
+
+.nav-collapse.collapse {
+ height: auto;
+ overflow: visible;
+}
+
+.navbar .brand {
+ display: block;
+ float: left;
+ padding: 10px 20px 10px;
+ margin-left: -20px;
+ font-size: 20px;
+ font-weight: 200;
+ color: #777777;
+ text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .brand:hover {
+ text-decoration: none;
+}
+
+.navbar-text {
+ margin-bottom: 0;
+ line-height: 40px;
+}
+
+.navbar-link {
+ color: #777777;
+}
+
+.navbar-link:hover {
+ color: #333333;
+}
+
+.navbar .divider-vertical {
+ height: 40px;
+ margin: 0 9px;
+ border-right: 1px solid #ffffff;
+ border-left: 1px solid #f2f2f2;
+}
+
+.navbar .btn,
+.navbar .btn-group {
+ margin-top: 5px;
+}
+
+.navbar .btn-group .btn,
+.navbar .input-prepend .btn,
+.navbar .input-append .btn {
+ margin-top: 0;
+}
+
+.navbar-form {
+ margin-bottom: 0;
+ *zoom: 1;
+}
+
+.navbar-form:before,
+.navbar-form:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.navbar-form:after {
+ clear: both;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .radio,
+.navbar-form .checkbox {
+ margin-top: 5px;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .btn {
+ display: inline-block;
+ margin-bottom: 0;
+}
+
+.navbar-form input[type="image"],
+.navbar-form input[type="checkbox"],
+.navbar-form input[type="radio"] {
+ margin-top: 3px;
+}
+
+.navbar-form .input-append,
+.navbar-form .input-prepend {
+ margin-top: 6px;
+ white-space: nowrap;
+}
+
+.navbar-form .input-append input,
+.navbar-form .input-prepend input {
+ margin-top: 0;
+}
+
+.navbar-search {
+ position: relative;
+ float: left;
+ margin-top: 5px;
+ margin-bottom: 0;
+}
+
+.navbar-search .search-query {
+ padding: 4px 14px;
+ margin-bottom: 0;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+.navbar-static-top {
+ position: static;
+ margin-bottom: 0;
+}
+
+.navbar-static-top .navbar-inner {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+ margin-bottom: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+ border-width: 0 0 1px;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+ border-width: 1px 0 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-fixed-bottom .navbar-inner {
+ padding-right: 0;
+ padding-left: 0;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+ width: 940px;
+}
+
+.navbar-fixed-top {
+ top: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+ -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-fixed-bottom {
+ bottom: 0;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+ -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar .nav {
+ position: relative;
+ left: 0;
+ display: block;
+ float: left;
+ margin: 0 10px 0 0;
+}
+
+.navbar .nav.pull-right {
+ float: right;
+ margin-right: 0;
+}
+
+.navbar .nav > li {
+ float: left;
+}
+
+.navbar .nav > li > a {
+ float: none;
+ padding: 10px 15px 10px;
+ color: #777777;
+ text-decoration: none;
+ text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .nav .dropdown-toggle .caret {
+ margin-top: 8px;
+}
+
+.navbar .nav > li > a:focus,
+.navbar .nav > li > a:hover {
+ color: #333333;
+ text-decoration: none;
+ background-color: transparent;
+}
+
+.navbar .nav > .active > a,
+.navbar .nav > .active > a:hover,
+.navbar .nav > .active > a:focus {
+ color: #555555;
+ text-decoration: none;
+ background-color: #e5e5e5;
+ -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+ -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+}
+
+.navbar .btn-navbar {
+ display: none;
+ float: right;
+ padding: 7px 10px;
+ margin-right: 5px;
+ margin-left: 5px;
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #ededed;
+ *background-color: #e5e5e5;
+ background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
+ background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
+ background-repeat: repeat-x;
+ border-color: #e5e5e5 #e5e5e5 #bfbfbf;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+}
+
+.navbar .btn-navbar:hover,
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active,
+.navbar .btn-navbar.disabled,
+.navbar .btn-navbar[disabled] {
+ color: #ffffff;
+ background-color: #e5e5e5;
+ *background-color: #d9d9d9;
+}
+
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active {
+ background-color: #cccccc \9;
+}
+
+.navbar .btn-navbar .icon-bar {
+ display: block;
+ width: 18px;
+ height: 2px;
+ background-color: #f5f5f5;
+ -webkit-border-radius: 1px;
+ -moz-border-radius: 1px;
+ border-radius: 1px;
+ -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+ -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.btn-navbar .icon-bar + .icon-bar {
+ margin-top: 3px;
+}
+
+.navbar .nav > li > .dropdown-menu:before {
+ position: absolute;
+ top: -7px;
+ left: 9px;
+ display: inline-block;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #ccc;
+ border-left: 7px solid transparent;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ content: '';
+}
+
+.navbar .nav > li > .dropdown-menu:after {
+ position: absolute;
+ top: -6px;
+ left: 10px;
+ display: inline-block;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid #ffffff;
+ border-left: 6px solid transparent;
+ content: '';
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
+ top: auto;
+ bottom: -7px;
+ border-top: 7px solid #ccc;
+ border-bottom: 0;
+ border-top-color: rgba(0, 0, 0, 0.2);
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
+ top: auto;
+ bottom: -6px;
+ border-top: 6px solid #ffffff;
+ border-bottom: 0;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle,
+.navbar .nav li.dropdown.active > .dropdown-toggle,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle {
+ color: #555555;
+ background-color: #e5e5e5;
+}
+
+.navbar .nav li.dropdown > .dropdown-toggle .caret {
+ border-top-color: #777777;
+ border-bottom-color: #777777;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
+ border-top-color: #555555;
+ border-bottom-color: #555555;
+}
+
+.navbar .pull-right > li > .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:before,
+.navbar .nav > li > .dropdown-menu.pull-right:before {
+ right: 12px;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:after,
+.navbar .nav > li > .dropdown-menu.pull-right:after {
+ right: 13px;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
+ right: 100%;
+ left: auto;
+ margin-right: -1px;
+ margin-left: 0;
+ -webkit-border-radius: 6px 0 6px 6px;
+ -moz-border-radius: 6px 0 6px 6px;
+ border-radius: 6px 0 6px 6px;
+}
+
+.navbar-inverse {
+ color: #999999;
+}
+
+.navbar-inverse .navbar-inner {
+ background-color: #1b1b1b;
+ background-image: -moz-linear-gradient(top, #222222, #111111);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
+ background-image: -webkit-linear-gradient(top, #222222, #111111);
+ background-image: -o-linear-gradient(top, #222222, #111111);
+ background-image: linear-gradient(to bottom, #222222, #111111);
+ background-repeat: repeat-x;
+ border-color: #252525;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
+}
+
+.navbar-inverse .brand,
+.navbar-inverse .nav > li > a {
+ color: #999999;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.navbar-inverse .brand:hover,
+.navbar-inverse .nav > li > a:hover {
+ color: #ffffff;
+}
+
+.navbar-inverse .nav > li > a:focus,
+.navbar-inverse .nav > li > a:hover {
+ color: #ffffff;
+ background-color: transparent;
+}
+
+.navbar-inverse .nav .active > a,
+.navbar-inverse .nav .active > a:hover,
+.navbar-inverse .nav .active > a:focus {
+ color: #ffffff;
+ background-color: #111111;
+}
+
+.navbar-inverse .navbar-link {
+ color: #999999;
+}
+
+.navbar-inverse .navbar-link:hover {
+ color: #ffffff;
+}
+
+.navbar-inverse .divider-vertical {
+ border-right-color: #222222;
+ border-left-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
+ color: #ffffff;
+ background-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
+ border-top-color: #999999;
+ border-bottom-color: #999999;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .navbar-search .search-query {
+ color: #ffffff;
+ background-color: #515151;
+ border-color: #111111;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+
+.navbar-inverse .navbar-search .search-query:-moz-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:focus,
+.navbar-inverse .navbar-search .search-query.focused {
+ padding: 5px 15px;
+ color: #333333;
+ text-shadow: 0 1px 0 #ffffff;
+ background-color: #ffffff;
+ border: 0;
+ outline: 0;
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+}
+
+.navbar-inverse .btn-navbar {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #0e0e0e;
+ *background-color: #040404;
+ background-image: -moz-linear-gradient(top, #151515, #040404);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
+ background-image: -webkit-linear-gradient(top, #151515, #040404);
+ background-image: -o-linear-gradient(top, #151515, #040404);
+ background-image: linear-gradient(to bottom, #151515, #040404);
+ background-repeat: repeat-x;
+ border-color: #040404 #040404 #000000;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.navbar-inverse .btn-navbar:hover,
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active,
+.navbar-inverse .btn-navbar.disabled,
+.navbar-inverse .btn-navbar[disabled] {
+ color: #ffffff;
+ background-color: #040404;
+ *background-color: #000000;
+}
+
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active {
+ background-color: #000000 \9;
+}
+
+.breadcrumb {
+ padding: 8px 15px;
+ margin: 0 0 20px;
+ list-style: none;
+ background-color: #f5f5f5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.breadcrumb li {
+ display: inline-block;
+ *display: inline;
+ text-shadow: 0 1px 0 #ffffff;
+ *zoom: 1;
+}
+
+.breadcrumb .divider {
+ padding: 0 5px;
+ color: #ccc;
+}
+
+.breadcrumb .active {
+ color: #999999;
+}
+
+.pagination {
+ margin: 20px 0;
+}
+
+.pagination ul {
+ display: inline-block;
+ *display: inline;
+ margin-bottom: 0;
+ margin-left: 0;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ *zoom: 1;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.pagination ul > li {
+ display: inline;
+}
+
+.pagination ul > li > a,
+.pagination ul > li > span {
+ float: left;
+ padding: 4px 12px;
+ line-height: 20px;
+ text-decoration: none;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-left-width: 0;
+}
+
+.pagination ul > li > a:hover,
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+ background-color: #f5f5f5;
+}
+
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+ color: #999999;
+ cursor: default;
+}
+
+.pagination ul > .disabled > span,
+.pagination ul > .disabled > a,
+.pagination ul > .disabled > a:hover {
+ color: #999999;
+ cursor: default;
+ background-color: transparent;
+}
+
+.pagination ul > li:first-child > a,
+.pagination ul > li:first-child > span {
+ border-left-width: 1px;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.pagination ul > li:last-child > a,
+.pagination ul > li:last-child > span {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.pagination-centered {
+ text-align: center;
+}
+
+.pagination-right {
+ text-align: right;
+}
+
+.pagination-large ul > li > a,
+.pagination-large ul > li > span {
+ padding: 11px 19px;
+ font-size: 17.5px;
+}
+
+.pagination-large ul > li:first-child > a,
+.pagination-large ul > li:first-child > span {
+ -webkit-border-bottom-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+ -webkit-border-top-left-radius: 6px;
+ border-top-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ -moz-border-radius-topleft: 6px;
+}
+
+.pagination-large ul > li:last-child > a,
+.pagination-large ul > li:last-child > span {
+ -webkit-border-top-right-radius: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ -moz-border-radius-bottomright: 6px;
+}
+
+.pagination-mini ul > li:first-child > a,
+.pagination-small ul > li:first-child > a,
+.pagination-mini ul > li:first-child > span,
+.pagination-small ul > li:first-child > span {
+ -webkit-border-bottom-left-radius: 3px;
+ border-bottom-left-radius: 3px;
+ -webkit-border-top-left-radius: 3px;
+ border-top-left-radius: 3px;
+ -moz-border-radius-bottomleft: 3px;
+ -moz-border-radius-topleft: 3px;
+}
+
+.pagination-mini ul > li:last-child > a,
+.pagination-small ul > li:last-child > a,
+.pagination-mini ul > li:last-child > span,
+.pagination-small ul > li:last-child > span {
+ -webkit-border-top-right-radius: 3px;
+ border-top-right-radius: 3px;
+ -webkit-border-bottom-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+ -moz-border-radius-topright: 3px;
+ -moz-border-radius-bottomright: 3px;
+}
+
+.pagination-small ul > li > a,
+.pagination-small ul > li > span {
+ padding: 2px 10px;
+ font-size: 11.9px;
+}
+
+.pagination-mini ul > li > a,
+.pagination-mini ul > li > span {
+ padding: 1px 6px;
+ font-size: 10.5px;
+}
+
+.pager {
+ margin: 20px 0;
+ text-align: center;
+ list-style: none;
+ *zoom: 1;
+}
+
+.pager:before,
+.pager:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.pager:after {
+ clear: both;
+}
+
+.pager li {
+ display: inline;
+}
+
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+.pager li > a:hover {
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > span {
+ color: #999999;
+ cursor: default;
+ background-color: #fff;
+}
+
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000000;
+}
+
+.modal-backdrop.fade {
+ opacity: 0;
+}
+
+.modal-backdrop,
+.modal-backdrop.fade.in {
+ opacity: 0.8;
+ filter: alpha(opacity=80);
+}
+
+.modal {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ z-index: 1050;
+ width: 560px;
+ margin: -250px 0 0 -280px;
+ background-color: #ffffff;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ *border: 1px solid #999;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ outline: none;
+ -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding-box;
+ background-clip: padding-box;
+}
+
+.modal.fade {
+ top: -25%;
+ -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
+ -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
+ -o-transition: opacity 0.3s linear, top 0.3s ease-out;
+ transition: opacity 0.3s linear, top 0.3s ease-out;
+}
+
+.modal.fade.in {
+ top: 50%;
+}
+
+.modal-header {
+ padding: 9px 15px;
+ border-bottom: 1px solid #eee;
+}
+
+.modal-header .close {
+ margin-top: 2px;
+}
+
+.modal-header h3 {
+ margin: 0;
+ line-height: 30px;
+}
+
+.modal-body {
+ max-height: 400px;
+ padding: 15px;
+ overflow-y: auto;
+}
+
+.modal-form {
+ margin-bottom: 0;
+}
+
+.modal-footer {
+ padding: 14px 15px 15px;
+ margin-bottom: 0;
+ text-align: right;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+ *zoom: 1;
+ -webkit-box-shadow: inset 0 1px 0 #ffffff;
+ -moz-box-shadow: inset 0 1px 0 #ffffff;
+ box-shadow: inset 0 1px 0 #ffffff;
+}
+
+.modal-footer:before,
+.modal-footer:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.modal-footer:after {
+ clear: both;
+}
+
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+
+.tooltip {
+ position: absolute;
+ z-index: 1030;
+ display: block;
+ padding: 5px;
+ font-size: 11px;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ visibility: visible;
+}
+
+.tooltip.in {
+ opacity: 0.8;
+ filter: alpha(opacity=80);
+}
+
+.tooltip.top {
+ margin-top: -3px;
+}
+
+.tooltip.right {
+ margin-left: 3px;
+}
+
+.tooltip.bottom {
+ margin-top: 3px;
+}
+
+.tooltip.left {
+ margin-left: -3px;
+}
+
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #ffffff;
+ text-align: center;
+ text-decoration: none;
+ background-color: #000000;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-top-color: #000000;
+ border-width: 5px 5px 0;
+}
+
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-right-color: #000000;
+ border-width: 5px 5px 5px 0;
+}
+
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-left-color: #000000;
+ border-width: 5px 0 5px 5px;
+}
+
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-bottom-color: #000000;
+ border-width: 0 5px 5px;
+}
+
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1010;
+ display: none;
+ width: 236px;
+ padding: 1px;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.popover.top {
+ margin-top: -10px;
+}
+
+.popover.right {
+ margin-left: 10px;
+}
+
+.popover.bottom {
+ margin-top: 10px;
+}
+
+.popover.left {
+ margin-left: -10px;
+}
+
+.popover-title {
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 18px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
+}
+
+.popover-content {
+ padding: 9px 14px;
+}
+
+.popover-content p,
+.popover-content ul,
+.popover-content ol {
+ margin-bottom: 0;
+}
+
+.popover .arrow,
+.popover .arrow:after {
+ position: absolute;
+ display: inline-block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+
+.popover .arrow:after {
+ z-index: -1;
+ content: "";
+}
+
+.popover.top .arrow {
+ bottom: -10px;
+ left: 50%;
+ margin-left: -10px;
+ border-top-color: #ffffff;
+ border-width: 10px 10px 0;
+}
+
+.popover.top .arrow:after {
+ bottom: -1px;
+ left: -11px;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ border-width: 11px 11px 0;
+}
+
+.popover.right .arrow {
+ top: 50%;
+ left: -10px;
+ margin-top: -10px;
+ border-right-color: #ffffff;
+ border-width: 10px 10px 10px 0;
+}
+
+.popover.right .arrow:after {
+ bottom: -11px;
+ left: -1px;
+ border-right-color: rgba(0, 0, 0, 0.25);
+ border-width: 11px 11px 11px 0;
+}
+
+.popover.bottom .arrow {
+ top: -10px;
+ left: 50%;
+ margin-left: -10px;
+ border-bottom-color: #ffffff;
+ border-width: 0 10px 10px;
+}
+
+.popover.bottom .arrow:after {
+ top: -1px;
+ left: -11px;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+ border-width: 0 11px 11px;
+}
+
+.popover.left .arrow {
+ top: 50%;
+ right: -10px;
+ margin-top: -10px;
+ border-left-color: #ffffff;
+ border-width: 10px 0 10px 10px;
+}
+
+.popover.left .arrow:after {
+ right: -1px;
+ bottom: -11px;
+ border-left-color: rgba(0, 0, 0, 0.25);
+ border-width: 11px 0 11px 11px;
+}
+
+.thumbnails {
+ margin-left: -20px;
+ list-style: none;
+ *zoom: 1;
+}
+
+.thumbnails:before,
+.thumbnails:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.thumbnails:after {
+ clear: both;
+}
+
+.row-fluid .thumbnails {
+ margin-left: 0;
+}
+
+.thumbnails > li {
+ float: left;
+ margin-bottom: 20px;
+ margin-left: 20px;
+}
+
+.thumbnail {
+ display: block;
+ padding: 4px;
+ line-height: 20px;
+ border: 1px solid #ddd;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ -webkit-transition: all 0.2s ease-in-out;
+ -moz-transition: all 0.2s ease-in-out;
+ -o-transition: all 0.2s ease-in-out;
+ transition: all 0.2s ease-in-out;
+}
+
+a.thumbnail:hover {
+ border-color: #0088cc;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+ -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+ box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+}
+
+.thumbnail > img {
+ display: block;
+ max-width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+.thumbnail .caption {
+ padding: 9px;
+ color: #555555;
+}
+
+.media,
+.media-body {
+ overflow: hidden;
+ *overflow: visible;
+ zoom: 1;
+}
+
+.media,
+.media .media {
+ margin-top: 15px;
+}
+
+.media:first-child {
+ margin-top: 0;
+}
+
+.media-object {
+ display: block;
+}
+
+.media-heading {
+ margin: 0 0 5px;
+}
+
+.media .pull-left {
+ margin-right: 10px;
+}
+
+.media .pull-right {
+ margin-left: 10px;
+}
+
+.media-list {
+ margin-left: 0;
+ list-style: none;
+}
+
+.label,
+.badge {
+ display: inline-block;
+ padding: 2px 4px;
+ font-size: 11.844px;
+ font-weight: bold;
+ line-height: 14px;
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ white-space: nowrap;
+ vertical-align: baseline;
+ background-color: #999999;
+}
+
+.label {
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.badge {
+ padding-right: 9px;
+ padding-left: 9px;
+ -webkit-border-radius: 9px;
+ -moz-border-radius: 9px;
+ border-radius: 9px;
+}
+
+a.label:hover,
+a.badge:hover {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+.label-important,
+.badge-important {
+ background-color: #b94a48;
+}
+
+.label-important[href],
+.badge-important[href] {
+ background-color: #953b39;
+}
+
+.label-warning,
+.badge-warning {
+ background-color: #f89406;
+}
+
+.label-warning[href],
+.badge-warning[href] {
+ background-color: #c67605;
+}
+
+.label-success,
+.badge-success {
+ background-color: #468847;
+}
+
+.label-success[href],
+.badge-success[href] {
+ background-color: #356635;
+}
+
+.label-info,
+.badge-info {
+ background-color: #3a87ad;
+}
+
+.label-info[href],
+.badge-info[href] {
+ background-color: #2d6987;
+}
+
+.label-inverse,
+.badge-inverse {
+ background-color: #333333;
+}
+
+.label-inverse[href],
+.badge-inverse[href] {
+ background-color: #1a1a1a;
+}
+
+.btn .label,
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+
+.btn-mini .label,
+.btn-mini .badge {
+ top: 0;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-moz-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-ms-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 0 0;
+ }
+ to {
+ background-position: 40px 0;
+ }
+}
+
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+.progress {
+ height: 20px;
+ margin-bottom: 20px;
+ overflow: hidden;
+ background-color: #f7f7f7;
+ background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
+ background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
+ background-repeat: repeat-x;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.progress .bar {
+ float: left;
+ width: 0;
+ height: 100%;
+ font-size: 12px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #0e90d2;
+ background-image: -moz-linear-gradient(top, #149bdf, #0480be);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
+ background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
+ background-image: -o-linear-gradient(top, #149bdf, #0480be);
+ background-image: linear-gradient(to bottom, #149bdf, #0480be);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-transition: width 0.6s ease;
+ -moz-transition: width 0.6s ease;
+ -o-transition: width 0.6s ease;
+ transition: width 0.6s ease;
+}
+
+.progress .bar + .bar {
+ -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+}
+
+.progress-striped .bar {
+ background-color: #149bdf;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ -webkit-background-size: 40px 40px;
+ -moz-background-size: 40px 40px;
+ -o-background-size: 40px 40px;
+ background-size: 40px 40px;
+}
+
+.progress.active .bar {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -moz-animation: progress-bar-stripes 2s linear infinite;
+ -ms-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-danger .bar,
+.progress .bar-danger {
+ background-color: #dd514c;
+ background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
+}
+
+.progress-danger.progress-striped .bar,
+.progress-striped .bar-danger {
+ background-color: #ee5f5b;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-success .bar,
+.progress .bar-success {
+ background-color: #5eb95e;
+ background-image: -moz-linear-gradient(top, #62c462, #57a957);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
+ background-image: -webkit-linear-gradient(top, #62c462, #57a957);
+ background-image: -o-linear-gradient(top, #62c462, #57a957);
+ background-image: linear-gradient(to bottom, #62c462, #57a957);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
+}
+
+.progress-success.progress-striped .bar,
+.progress-striped .bar-success {
+ background-color: #62c462;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-info .bar,
+.progress .bar-info {
+ background-color: #4bb1cf;
+ background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
+ background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
+}
+
+.progress-info.progress-striped .bar,
+.progress-striped .bar-info {
+ background-color: #5bc0de;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-warning .bar,
+.progress .bar-warning {
+ background-color: #faa732;
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+}
+
+.progress-warning.progress-striped .bar,
+.progress-striped .bar-warning {
+ background-color: #fbb450;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.accordion {
+ margin-bottom: 20px;
+}
+
+.accordion-group {
+ margin-bottom: 2px;
+ border: 1px solid #e5e5e5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.accordion-heading {
+ border-bottom: 0;
+}
+
+.accordion-heading .accordion-toggle {
+ display: block;
+ padding: 8px 15px;
+}
+
+.accordion-toggle {
+ cursor: pointer;
+}
+
+.accordion-inner {
+ padding: 9px 15px;
+ border-top: 1px solid #e5e5e5;
+}
+
+.carousel {
+ position: relative;
+ margin-bottom: 20px;
+ line-height: 1;
+}
+
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+}
+
+.carousel .item {
+ position: relative;
+ display: none;
+ -webkit-transition: 0.6s ease-in-out left;
+ -moz-transition: 0.6s ease-in-out left;
+ -o-transition: 0.6s ease-in-out left;
+ transition: 0.6s ease-in-out left;
+}
+
+.carousel .item > img {
+ display: block;
+ line-height: 1;
+}
+
+.carousel .active,
+.carousel .next,
+.carousel .prev {
+ display: block;
+}
+
+.carousel .active {
+ left: 0;
+}
+
+.carousel .next,
+.carousel .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+
+.carousel .next {
+ left: 100%;
+}
+
+.carousel .prev {
+ left: -100%;
+}
+
+.carousel .next.left,
+.carousel .prev.right {
+ left: 0;
+}
+
+.carousel .active.left {
+ left: -100%;
+}
+
+.carousel .active.right {
+ left: 100%;
+}
+
+.carousel-control {
+ position: absolute;
+ top: 40%;
+ left: 15px;
+ width: 40px;
+ height: 40px;
+ margin-top: -20px;
+ font-size: 60px;
+ font-weight: 100;
+ line-height: 30px;
+ color: #ffffff;
+ text-align: center;
+ background: #222222;
+ border: 3px solid #ffffff;
+ -webkit-border-radius: 23px;
+ -moz-border-radius: 23px;
+ border-radius: 23px;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+
+.carousel-control.right {
+ right: 15px;
+ left: auto;
+}
+
+.carousel-control:hover {
+ color: #ffffff;
+ text-decoration: none;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+
+.carousel-caption {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 15px;
+ background: #333333;
+ background: rgba(0, 0, 0, 0.75);
+}
+
+.carousel-caption h4,
+.carousel-caption p {
+ line-height: 20px;
+ color: #ffffff;
+}
+
+.carousel-caption h4 {
+ margin: 0 0 5px;
+}
+
+.carousel-caption p {
+ margin-bottom: 0;
+}
+
+.hero-unit {
+ padding: 60px;
+ margin-bottom: 30px;
+ font-size: 18px;
+ font-weight: 200;
+ line-height: 30px;
+ color: inherit;
+ background-color: #eeeeee;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.hero-unit h1 {
+ margin-bottom: 0;
+ font-size: 60px;
+ line-height: 1;
+ letter-spacing: -1px;
+ color: inherit;
+}
+
+.hero-unit li {
+ line-height: 30px;
+}
+
+.pull-right {
+ float: right;
+}
+
+.pull-left {
+ float: left;
+}
+
+.hide {
+ display: none;
+}
+
+.show {
+ display: block;
+}
+
+.invisible {
+ visibility: hidden;
+}
+
+.affix {
+ position: fixed;
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/application.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/application.png
new file mode 100755
index 000000000..1dee9e366
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/application.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/code.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/code.png
new file mode 100755
index 000000000..0c76bd129
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/code.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/css.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/css.png
new file mode 100755
index 000000000..f907e44b3
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/css.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/db.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/db.png
new file mode 100755
index 000000000..bddba1f98
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/db.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/doc.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/doc.png
new file mode 100755
index 000000000..ae8ecbf47
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/doc.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/file.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/file.png
new file mode 100755
index 000000000..8b8b1ca00
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/file.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/film.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/film.png
new file mode 100755
index 000000000..b0ce7bb19
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/film.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/flash.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/flash.png
new file mode 100755
index 000000000..5769120b1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/flash.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder-closed.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder-closed.gif
new file mode 100755
index 000000000..541107888
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder-closed.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder.gif
new file mode 100755
index 000000000..2b31631ca
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/folder.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/html.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/html.png
new file mode 100755
index 000000000..6ed2490ed
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/html.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/java.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/java.png
new file mode 100755
index 000000000..b7bfcd15f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/java.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/linux.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/linux.png
new file mode 100755
index 000000000..52699bfee
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/linux.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/music.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/music.png
new file mode 100755
index 000000000..a8b3ede3d
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/music.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/pdf.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/pdf.png
new file mode 100755
index 000000000..8f8095e46
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/pdf.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/php.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/php.png
new file mode 100755
index 000000000..7868a2594
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/php.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/picture.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/picture.png
new file mode 100755
index 000000000..4a158fef7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/picture.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ppt.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ppt.png
new file mode 100755
index 000000000..c4eff0387
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ppt.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/psd.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/psd.png
new file mode 100755
index 000000000..73c5b3f24
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/psd.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ruby.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ruby.png
new file mode 100755
index 000000000..f59b7c436
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ruby.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/script.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/script.png
new file mode 100755
index 000000000..63fe6ceff
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/script.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2.png
new file mode 100755
index 000000000..1d804ffb9
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2x2.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2x2.png
new file mode 100755
index 000000000..4bdd5c961
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/select2x2.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/spinner.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/spinner.gif
new file mode 100755
index 000000000..85b99d46b
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/spinner.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/txt.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/txt.png
new file mode 100755
index 000000000..813f712f7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/txt.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_0_aaaaaa_40x100.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100755
index 000000000..5b5dab2ab
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_75_ffffff_40x100.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100755
index 000000000..ac8b229af
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_55_fbf9ee_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100755
index 000000000..ad3d6346e
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_65_ffffff_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100755
index 000000000..42ccba269
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_dadada_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100755
index 000000000..5a46b47cb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_e6e6e6_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100755
index 000000000..86c2baa65
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_ffffff_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_ffffff_1x400.png
new file mode 100755
index 000000000..e65ca1297
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_75_ffffff_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_95_fef1ec_1x400.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100755
index 000000000..4443fdc1a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100755
index 000000000..7c9fa6c6e
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png
new file mode 100755
index 000000000..0e05810ff
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_222222_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_222222_256x240.png
new file mode 100755
index 000000000..b273ff111
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_2e83ff_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_2e83ff_256x240.png
new file mode 100755
index 000000000..09d1cdc85
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_454545_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_454545_256x240.png
new file mode 100755
index 000000000..59bd45b90
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_888888_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_888888_256x240.png
new file mode 100755
index 000000000..6d02426c1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_cd0a0a_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_cd0a0a_256x240.png
new file mode 100755
index 000000000..2ab019b73
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_f6cf3b_256x240.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_f6cf3b_256x240.png
new file mode 100644
index 000000000..c9869351a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/ui-icons_f6cf3b_256x240.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/xls.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/xls.png
new file mode 100755
index 000000000..b977d7e52
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/xls.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/zip.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/zip.png
new file mode 100755
index 000000000..fd4bbccdf
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/images/zip.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery-ui-1.9.2.custom.min.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery-ui-1.9.2.custom.min.css
new file mode 100755
index 000000000..e96496989
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery-ui-1.9.2.custom.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.9.2 - 2012-11-23
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/
+* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */.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}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;zoom:1}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;zoom:1}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}* html .ui-autocomplete{width:1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.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:.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:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .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:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.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 .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{border-left-width:0}.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:0em}.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{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;zoom:1;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.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-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}* html .ui-tooltip{background-image:none}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px} \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.fileupload-ui.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.fileupload-ui.css
new file mode 100644
index 000000000..e36a93df3
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.fileupload-ui.css
@@ -0,0 +1,84 @@
+@charset 'UTF-8';
+/*
+ * jQuery File Upload UI Plugin CSS 6.3
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.fileinput-button {
+ position: relative;
+ overflow: hidden;
+ float: left;
+ margin-right: 4px;
+}
+.fileinput-button input {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin: 0;
+ border: solid transparent;
+ border-width: 0 0 100px 200px;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ -moz-transform: translate(-300px, 0) scale(4);
+ direction: ltr;
+ cursor: pointer;
+}
+.fileupload-buttonbar .btn,
+.fileupload-buttonbar .toggle {
+ margin-bottom: 5px;
+}
+.files .progress {
+ width: 200px;
+}
+.progress-animated .bar {
+ background: url(../img/progressbar.gif) !important;
+ filter: none;
+}
+.fileupload-loading {
+ position: absolute;
+ left: 50%;
+ width: 128px;
+ height: 128px;
+ background: url(../img/loading.gif) center no-repeat;
+ display: none;
+}
+.fileupload-processing .fileupload-loading {
+ display: block;
+}
+
+/* Fix for IE 6: */
+*html .fileinput-button {
+ line-height: 22px;
+ margin: 1px -3px 0 0;
+}
+
+/* Fix for IE 7: */
+*+html .fileinput-button {
+ margin: 1px 0 0 0;
+}
+
+@media (max-width: 480px) {
+ .files .btn span {
+ display: none;
+ }
+ .files .preview * {
+ width: 40px;
+ }
+ .files .name * {
+ width: 80px;
+ display: inline-block;
+ word-wrap: break-word;
+ }
+ .files .progress {
+ width: 20px;
+ }
+ .files .delete {
+ width: 60px;
+ }
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.ui.1.8.16.ie.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.ui.1.8.16.ie.css
new file mode 100755
index 000000000..b24b9fb8a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jquery.ui.1.8.16.ie.css
@@ -0,0 +1,6 @@
+
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-left, .ui-corner-bottom{ border-radius:0px;}
+.ui-state-active,.ui-tabs-selected { border-radius:0px;}
+.ui-tabs-selected { border-radius:0px;}
+.ui-tabs .ui-tabs-nav li{ filter:none;}
+.ui-tabs .ui-tabs-nav li a { border-radius:0px; }
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jqueryFileTree.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jqueryFileTree.css
new file mode 100755
index 000000000..073d1fdec
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/jqueryFileTree.css
@@ -0,0 +1,91 @@
+UL.jqueryFileTree {
+ font-family: Verdana, sans-serif;
+ font-size: 11px;
+ line-height: 18px;
+ padding: 0px;
+ margin: 0px;
+}
+
+UL.jqueryFileTree LI {
+ list-style: none;
+ padding: 0px;
+ padding-left: 20px;
+ margin: 0px;
+ white-space: nowrap;
+}
+
+UL.jqueryFileTree A {
+ color: #333;
+ text-decoration: none;
+ display: block;
+ padding: 0px 2px;
+}
+
+UL.jqueryFileTree A:hover {
+ background: #BDF;
+}
+
+/* Core Styles */
+.jqueryFileTree LI.directory { background: url(images/folder-closed.gif) left top no-repeat; }
+.jqueryFileTree LI.expanded { background: url(images/folder.gif) left top no-repeat; }
+.jqueryFileTree LI.file { background: url(images/file.png) left top no-repeat; }
+.jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; }
+/* File Extensions*/
+.jqueryFileTree LI.ext_3gp { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_afp { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_afpa { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_asp { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_aspx { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_avi { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_bat { background: url(images/application.png) left top no-repeat; }
+.jqueryFileTree LI.ext_bmp { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_c { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_cfm { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_cgi { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_com { background: url(images/application.png) left top no-repeat; }
+.jqueryFileTree LI.ext_cpp { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_css { background: url(images/css.png) left top no-repeat; }
+.jqueryFileTree LI.ext_doc { background: url(images/doc.png) left top no-repeat; }
+.jqueryFileTree LI.ext_exe { background: url(images/application.png) left top no-repeat; }
+.jqueryFileTree LI.ext_gif { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_fla { background: url(images/flash.png) left top no-repeat; }
+.jqueryFileTree LI.ext_h { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_htm { background: url(images/html.png) left top no-repeat; }
+.jqueryFileTree LI.ext_html { background: url(images/html.png) left top no-repeat; }
+.jqueryFileTree LI.ext_jar { background: url(images/java.png) left top no-repeat; }
+.jqueryFileTree LI.ext_jpg { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_jpeg { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_js { background: url(images/script.png) left top no-repeat; }
+.jqueryFileTree LI.ext_lasso { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_log { background: url(images/txt.png) left top no-repeat; }
+.jqueryFileTree LI.ext_m4p { background: url(images/music.png) left top no-repeat; }
+.jqueryFileTree LI.ext_mov { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_mp3 { background: url(images/music.png) left top no-repeat; }
+.jqueryFileTree LI.ext_mp4 { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_mpg { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_mpeg { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_ogg { background: url(images/music.png) left top no-repeat; }
+.jqueryFileTree LI.ext_pcx { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_pdf { background: url(images/pdf.png) left top no-repeat; }
+.jqueryFileTree LI.ext_php { background: url(images/php.png) left top no-repeat; }
+.jqueryFileTree LI.ext_png { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_ppt { background: url(images/ppt.png) left top no-repeat; }
+.jqueryFileTree LI.ext_psd { background: url(images/psd.png) left top no-repeat; }
+.jqueryFileTree LI.ext_pl { background: url(images/script.png) left top no-repeat; }
+.jqueryFileTree LI.ext_py { background: url(images/script.png) left top no-repeat; }
+.jqueryFileTree LI.ext_rb { background: url(images/ruby.png) left top no-repeat; }
+.jqueryFileTree LI.ext_rbx { background: url(images/ruby.png) left top no-repeat; }
+.jqueryFileTree LI.ext_rhtml { background: url(images/ruby.png) left top no-repeat; }
+.jqueryFileTree LI.ext_rpm { background: url(images/linux.png) left top no-repeat; }
+.jqueryFileTree LI.ext_ruby { background: url(images/ruby.png) left top no-repeat; }
+.jqueryFileTree LI.ext_sql { background: url(images/db.png) left top no-repeat; }
+.jqueryFileTree LI.ext_swf { background: url(images/flash.png) left top no-repeat; }
+.jqueryFileTree LI.ext_tif { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_tiff { background: url(images/picture.png) left top no-repeat; }
+.jqueryFileTree LI.ext_txt { background: url(images/txt.png) left top no-repeat; }
+.jqueryFileTree LI.ext_vb { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_wav { background: url(images/music.png) left top no-repeat; }
+.jqueryFileTree LI.ext_wmv { background: url(images/film.png) left top no-repeat; }
+.jqueryFileTree LI.ext_xls { background: url(images/xls.png) left top no-repeat; }
+.jqueryFileTree LI.ext_xml { background: url(images/code.png) left top no-repeat; }
+.jqueryFileTree LI.ext_zip { background: url(images/zip.png) left top no-repeat; } \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/prettify.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/prettify.css
new file mode 100644
index 000000000..400fd7428
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/prettify.css
@@ -0,0 +1,52 @@
+/* Pretty printing styles. Used with prettify.js. */
+
+/* SPAN elements with the classes below are added by prettyprint. */
+.pln { color: #000 } /* plain text */
+
+@media screen {
+ .str { color: #080 } /* string content */
+ .kwd { color: #008 } /* a keyword */
+ .com { color: #800 } /* a comment */
+ .typ { color: #606 } /* a type name */
+ .lit { color: #066 } /* a literal value */
+ /* punctuation, lisp open bracket, lisp close bracket */
+ .pun, .opn, .clo { color: #660 }
+ .tag { color: #008 } /* a markup tag name */
+ .atn { color: #606 } /* a markup attribute name */
+ .atv { color: #080 } /* a markup attribute value */
+ .dec, .var { color: #606 } /* a declaration; a variable name */
+ .fun { color: red } /* a function name */
+}
+
+/* Use higher contrast and text-weight for printable form. */
+@media print, projection {
+ .str { color: #060 }
+ .kwd { color: #006; font-weight: bold }
+ .com { color: #600; font-style: italic }
+ .typ { color: #404; font-weight: bold }
+ .lit { color: #044 }
+ .pun, .opn, .clo { color: #440 }
+ .tag { color: #006; font-weight: bold }
+ .atn { color: #404 }
+ .atv { color: #060 }
+}
+
+/* Put a border around prettyprinted code snippets. */
+pre.prettyprint { padding: 2px; border: 1px solid #888 }
+
+/* Specify class=linenums on a pre to get line numbering */
+ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
+li.L0,
+li.L1,
+li.L2,
+li.L3,
+li.L5,
+li.L6,
+li.L7,
+li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,
+li.L3,
+li.L5,
+li.L7,
+li.L9 { background: #eee }
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/select2-3.2.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/select2-3.2.css
new file mode 100755
index 000000000..568d3e5c0
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/select2-3.2.css
@@ -0,0 +1,524 @@
+/*
+Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012
+*/
+.select2-container {
+ position: relative;
+ display: inline-block;
+ /* inline-block for ie7 */
+ zoom: 1;
+ *display: inline;
+ vertical-align: top;
+}
+
+.select2-container,
+.select2-drop,
+.select2-search,
+.select2-search input{
+ /*
+ Force border-box so that % widths fit the parent
+ container without overlap because of margin/padding.
+
+ More Info : http://www.quirksmode.org/css/box.html
+ */
+ -moz-box-sizing: border-box; /* firefox */
+ -ms-box-sizing: border-box; /* ie */
+ -webkit-box-sizing: border-box; /* webkit */
+ -khtml-box-sizing: border-box; /* konqueror */
+ box-sizing: border-box; /* css3 */
+}
+
+.select2-container .select2-choice {
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white));
+ background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%);
+ background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%);
+ background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%);
+ background-image: -ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#ffffff', GradientType = 0);
+ background-image: linear-gradient(top, #eeeeee 0%, #ffffff 50%);
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -moz-background-clip: padding;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #aaa;
+ display: block;
+ overflow: hidden;
+ white-space: nowrap;
+ position: relative;
+ height: 26px;
+ line-height: 26px;
+ padding: 0 0 0 8px;
+ color: #444;
+ text-decoration: none;
+}
+
+.select2-container.select2-drop-above .select2-choice
+{
+ border-bottom-color: #aaa;
+ -webkit-border-radius:0px 0px 4px 4px;
+ -moz-border-radius:0px 0px 4px 4px;
+ border-radius:0px 0px 4px 4px;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white));
+ background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%);
+ background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 90%);
+ background-image: -o-linear-gradient(bottom, #eeeeee 0%, white 90%);
+ background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 90%);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
+ background-image: linear-gradient(top, #eeeeee 0%,#ffffff 90%);
+}
+
+.select2-container .select2-choice span {
+ margin-right: 26px;
+ display: block;
+ overflow: hidden;
+ white-space: nowrap;
+ -o-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+}
+
+.select2-container .select2-choice abbr {
+ display: block;
+ position: absolute;
+ right: 26px;
+ top: 8px;
+ width: 12px;
+ height: 12px;
+ font-size: 1px;
+ background: url('images/select2.png') right top no-repeat;
+ cursor: pointer;
+ text-decoration: none;
+ border:0;
+ outline: 0;
+}
+.select2-container .select2-choice abbr:hover {
+ background-position: right -11px;
+ cursor: pointer;
+}
+
+.select2-drop {
+ background: #fff;
+ color: #000;
+ border: 1px solid #aaa;
+ border-top: 0;
+ position: absolute;
+ top: 100%;
+ -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+ -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+ -o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+ box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+ z-index: 9999;
+ width:100%;
+ margin-top:-1px;
+
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.select2-drop.select2-drop-above {
+ -webkit-border-radius: 4px 4px 0px 0px;
+ -moz-border-radius: 4px 4px 0px 0px;
+ border-radius: 4px 4px 0px 0px;
+ margin-top:1px;
+ border-top: 1px solid #aaa;
+ border-bottom: 0;
+
+ -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+ -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+ -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+ box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+}
+
+.select2-container .select2-choice div {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+ -moz-background-clip: padding;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ background: #ccc;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
+ background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
+ background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
+ background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%);
+ background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#cccccc', endColorstr = '#eeeeee', GradientType = 0);
+ background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%);
+ border-left: 1px solid #aaa;
+ position: absolute;
+ right: 0;
+ top: 0;
+ display: block;
+ height: 100%;
+ width: 18px;
+}
+
+.select2-container .select2-choice div b {
+ background: url('images/select2.png') no-repeat 0 1px;
+ display: block;
+ width: 100%;
+ height: 100%;
+}
+
+.select2-search {
+ display: inline-block;
+ white-space: nowrap;
+ z-index: 10000;
+ min-height: 26px;
+ width: 100%;
+ margin: 0;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+.select2-search-hidden {
+ display: block;
+ position: absolute;
+ left: -10000px;
+}
+
+.select2-search input {
+ background: #fff url('images/select2.png') no-repeat 100% -22px;
+ background: url('images/select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
+ background: url('images/select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+ background: url('images/select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+ background: url('images/select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
+ background: url('images/select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+ background: url('images/select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+ padding: 4px 20px 4px 5px;
+ outline: 0;
+ border: 1px solid #aaa;
+ font-family: sans-serif;
+ font-size: 1em;
+ width:100%;
+ margin:0;
+ height:auto !important;
+ min-height: 26px;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ border-radius: 0;
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+}
+
+.select2-drop.select2-drop-above .select2-search input
+{
+ margin-top:4px;
+}
+
+.select2-search input.select2-active {
+ background: #fff url('images/spinner.gif') no-repeat 100%;
+ background: url('images/spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
+ background: url('images/spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+ background: url('images/spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+ background: url('images/spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
+ background: url('images/spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+ background: url('images/spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+}
+
+
+.select2-container-active .select2-choice,
+.select2-container-active .select2-choices {
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+ -moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ -o-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ box-shadow : 0 0 5px rgba(0,0,0,.3);
+ border: 1px solid #5897fb;
+ outline: none;
+}
+
+.select2-dropdown-open .select2-choice {
+ border: 1px solid #aaa;
+ border-bottom-color: transparent;
+ -webkit-box-shadow: 0 1px 0 #fff inset;
+ -moz-box-shadow : 0 1px 0 #fff inset;
+ -o-box-shadow : 0 1px 0 #fff inset;
+ box-shadow : 0 1px 0 #fff inset;
+ background-color: #eee;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee));
+ background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%);
+ background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%);
+ background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%);
+ background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 );
+ background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%);
+ -webkit-border-bottom-left-radius : 0;
+ -webkit-border-bottom-right-radius: 0;
+ -moz-border-radius-bottomleft : 0;
+ -moz-border-radius-bottomright: 0;
+ border-bottom-left-radius : 0;
+ border-bottom-right-radius: 0;
+}
+
+.select2-dropdown-open .select2-choice div {
+ background: transparent;
+ border-left: none;
+}
+.select2-dropdown-open .select2-choice div b {
+ background-position: -18px 1px;
+}
+
+/* results */
+.select2-results {
+ margin: 4px 4px 4px 0;
+ padding: 0 0 0 4px;
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: auto;
+ max-height: 200px;
+}
+
+.select2-results ul.select2-result-sub {
+ margin: 0 0 0 0;
+}
+
+.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
+.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
+.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
+.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
+.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
+.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
+.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
+
+.select2-results li {
+ list-style: none;
+ display: list-item;
+}
+
+.select2-results li.select2-result-with-children > .select2-result-label {
+ font-weight: bold;
+}
+
+.select2-results .select2-result-label {
+ padding: 3px 7px 4px;
+ margin: 0;
+ cursor: pointer;
+}
+
+.select2-results .select2-highlighted {
+ background: #3875d7;
+ color: #fff;
+}
+.select2-results li em {
+ background: #feffde;
+ font-style: normal;
+}
+.select2-results .select2-highlighted em {
+ background: transparent;
+}
+.select2-results .select2-no-results,
+.select2-results .select2-searching,
+.select2-results .select2-selection-limit {
+ background: #f4f4f4;
+ display: list-item;
+}
+
+/*
+disabled look for already selected choices in the results dropdown
+.select2-results .select2-disabled.select2-highlighted {
+ color: #666;
+ background: #f4f4f4;
+ display: list-item;
+ cursor: default;
+}
+.select2-results .select2-disabled {
+ background: #f4f4f4;
+ display: list-item;
+ cursor: default;
+}
+*/
+.select2-results .select2-disabled {
+ display: none;
+}
+
+.select2-more-results.select2-active {
+ background: #f4f4f4 url('images/spinner.gif') no-repeat 100%;
+}
+
+.select2-more-results {
+ background: #f4f4f4;
+ display: list-item;
+}
+
+/* disabled styles */
+
+.select2-container.select2-container-disabled .select2-choice {
+ background-color: #f4f4f4;
+ background-image: none;
+ border: 1px solid #ddd;
+ cursor: default;
+}
+
+.select2-container.select2-container-disabled .select2-choice div {
+ background-color: #f4f4f4;
+ background-image: none;
+ border-left: 0;
+}
+
+
+/* multiselect */
+
+.select2-container-multi .select2-choices {
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ border: 1px solid #aaa;
+ margin: 0;
+ padding: 0;
+ cursor: text;
+ overflow: hidden;
+ height: auto !important;
+ height: 1%;
+ position: relative;
+}
+
+.select2-container-multi .select2-choices {
+ min-height: 26px;
+}
+
+.select2-container-multi.select2-container-active .select2-choices {
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+ -moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ -o-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ box-shadow : 0 0 5px rgba(0,0,0,.3);
+ border: 1px solid #5897fb;
+ outline: none;
+}
+.select2-container-multi .select2-choices li {
+ float: left;
+ list-style: none;
+}
+.select2-container-multi .select2-choices .select2-search-field {
+ white-space: nowrap;
+ margin: 0;
+ padding: 0;
+}
+
+.select2-container-multi .select2-choices .select2-search-field input {
+ color: #666;
+ background: transparent !important;
+ font-family: sans-serif;
+ font-size: 100%;
+ height: 15px;
+ padding: 5px;
+ margin: 1px 0;
+ outline: 0;
+ border: 0;
+ -webkit-box-shadow: none;
+ -moz-box-shadow : none;
+ -o-box-shadow : none;
+ box-shadow : none;
+}
+
+.select2-container-multi .select2-choices .select2-search-field input.select2-active {
+ background: #fff url('images/spinner.gif') no-repeat 100% !important;
+}
+
+.select2-default {
+ color: #999 !important;
+}
+
+.select2-container-multi .select2-choices .select2-search-choice {
+ -webkit-border-radius: 3px;
+ -moz-border-radius : 3px;
+ border-radius : 3px;
+ -moz-background-clip : padding;
+ -webkit-background-clip: padding-box;
+ background-clip : padding-box;
+ background-color: #e4e4e4;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ -moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ color: #333;
+ border: 1px solid #aaaaaa;
+ line-height: 13px;
+ padding: 3px 5px 3px 18px;
+ margin: 3px 0 3px 5px;
+ position: relative;
+ cursor: default;
+}
+.select2-container-multi .select2-choices .select2-search-choice span {
+ cursor: default;
+}
+.select2-container-multi .select2-choices .select2-search-choice-focus {
+ background: #d4d4d4;
+}
+
+.select2-search-choice-close {
+ display: block;
+ position: absolute;
+ right: 3px;
+ top: 4px;
+ width: 12px;
+ height: 13px;
+ font-size: 1px;
+ background: url('images/select2.png') right top no-repeat;
+ outline: none;
+}
+
+.select2-container-multi .select2-search-choice-close {
+ left: 3px;
+}
+
+
+.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
+ background-position: right -11px;
+}
+.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
+ background-position: right -11px;
+}
+
+/* disabled styles */
+
+.select2-container-multi.select2-container-disabled .select2-choices{
+ background-color: #f4f4f4;
+ background-image: none;
+ border: 1px solid #ddd;
+ cursor: default;
+}
+
+.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
+ background-image: none;
+ background-color: #f4f4f4;
+ border: 1px solid #ddd;
+ padding: 3px 5px 3px 5px;
+}
+
+.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close {
+ display: none;
+}
+/* end multiselect */
+
+.select2-result-selectable .select2-match,
+.select2-result-unselectable .select2-result-selectable .select2-match { text-decoration: underline; }
+.select2-result-unselectable .select2-match { text-decoration: none; }
+
+.select2-offscreen { position: absolute; left: -10000px; }
+
+/* Retina-ize icons */
+
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
+ .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b {
+ background-image: url('images/select2x2.png') !important;
+ background-repeat: no-repeat !important;
+ background-size: 60px 40px !important;
+ }
+ .select2-search input {
+ background-position: 100% -21px !important;
+ }
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/favicon.ico b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/favicon.ico
new file mode 100644
index 000000000..06714d34a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/favicon.ico
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-2-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-2-32-32.png
new file mode 100644
index 000000000..096e84895
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-2-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-32-32.png
new file mode 100644
index 000000000..096e84895
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/applications-internet-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/atom.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/atom.gif
new file mode 100644
index 000000000..b0e4adf1d
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/atom.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error-22-22.png
new file mode 100644
index 000000000..7d6aaf6f2
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error.png
new file mode 100644
index 000000000..3bbbb4a0d
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/dialog-error.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/drive-removable-media-16-16.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/drive-removable-media-16-16.png
new file mode 100644
index 000000000..915389828
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/drive-removable-media-16-16.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/edit-cut.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/edit-cut.png
new file mode 100644
index 000000000..dc9eb9a7a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/edit-cut.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder-saved-search.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder-saved-search.png
new file mode 100644
index 000000000..ca24a3676
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder-saved-search.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder.png
new file mode 100644
index 000000000..65bd0bbdc
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/folder.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/go-home.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/go-home.png
new file mode 100644
index 000000000..a46fb2220
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/go-home.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/green-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/green-22-22.png
new file mode 100644
index 000000000..21d46595c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/green-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser-32-32.png
new file mode 100644
index 000000000..10d2ed4f4
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser.png
new file mode 100644
index 000000000..ac5957ad6
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/internet-web-browser.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add-22-22.png
new file mode 100644
index 000000000..306d3d892
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add.png
new file mode 100644
index 000000000..1aa7f095c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/list-add.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/medium-spinner.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/medium-spinner.gif
new file mode 100644
index 000000000..1c72ebb55
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/medium-spinner.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/package-x-generic.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/package-x-generic.png
new file mode 100644
index 000000000..901542615
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/package-x-generic.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/preferences-system-network-proxy-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/preferences-system-network-proxy-32-32.png
new file mode 100644
index 000000000..e75f6f769
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/preferences-system-network-proxy-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/red-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/red-22-22.png
new file mode 100644
index 000000000..d5202f7fa
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/red-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/small-spinner.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/small-spinner.gif
new file mode 100644
index 000000000..529e72f45
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/small-spinner.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-file-manager-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-file-manager-32-32.png
new file mode 100644
index 000000000..1d6ce3151
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-file-manager-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen-22-22.png
new file mode 100644
index 000000000..dc6b825b1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen.png
new file mode 100644
index 000000000..f7ea0cd22
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-lock-screen.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-search-16-16.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-search-16-16.png
new file mode 100644
index 000000000..fd7f0b07a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-search-16-16.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-software-update-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-software-update-32-32.png
new file mode 100644
index 000000000..470b5d46f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-software-update-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-users-32-32.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-users-32-32.png
new file mode 100644
index 000000000..749c825e0
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/system-users-32-32.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/trash.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/trash.png
new file mode 100644
index 000000000..0e0953c73
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/trash.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash-full.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash-full.png
new file mode 100644
index 000000000..695d215a7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash-full.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash.png
new file mode 100644
index 000000000..0e0953c73
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/user-trash.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor-22-22.png
new file mode 100644
index 000000000..f2d266f79
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor.png
new file mode 100644
index 000000000..8734e777a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/utilities-system-monitor.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh-22-22.png
new file mode 100644
index 000000000..cab4d02c7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh.png
new file mode 100644
index 000000000..3fd71d6e5
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/view-refresh.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear-22-22.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear-22-22.png
new file mode 100644
index 000000000..e17ca7ce0
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear-22-22.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear.png
new file mode 100644
index 000000000..7dc15ea96
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/weather-clear.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings-white.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings-white.png
new file mode 100644
index 000000000..3bf6484a2
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings-white.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings.png b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings.png
new file mode 100644
index 000000000..a99699932
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/glyphicons-halflings.png
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/loading.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/loading.gif
new file mode 100644
index 000000000..90f28cbdb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/loading.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/progressbar.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/progressbar.gif
new file mode 100644
index 000000000..fbcce6bc9
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/img/progressbar.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/index.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/index.html
new file mode 100644
index 000000000..761ea3dfd
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/index.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+
+<!--
+~ ~ Licensed to the Apache Software Foundation (ASF) under one
+~ ~ or more contributor license agreements. See the NOTICE file
+~ ~ distributed with this work for additional information
+~ ~ regarding copyright ownership. The ASF licenses this file
+~ ~ to you under the Apache License, Version 2.0 (the
+~ ~ "License"); you may not use this file except in compliance
+~ ~ with the License. You may obtain a copy of the License at
+~ ~
+~ ~ http://www.apache.org/licenses/LICENSE-2.0
+~ ~
+~ ~ Unless required by applicable law or agreed to in writing,
+~ ~ software distributed under the License is distributed on an
+~ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+~ ~ KIND, either express or implied. See the License for the
+~ ~ specific language governing permissions and limitations
+~ ~ under the License.
+~ -->
+
+<html>
+<head>
+
+ <link rel="stylesheet" href="css/jquery.fileupload-ui.css"/>
+ <link rel="stylesheet" href="css/jqueryFileTree.css"/>
+ <link rel="stylesheet" href="css/jquery-ui-1.9.2.custom.min.css"/>
+ <link rel="stylesheet" href="css/select2-3.2.css"/>
+ <link rel="stylesheet" href="css/bootstrap.2.2.1.css">
+ <link rel="stylesheet" href="css/archiva.css">
+ <link rel="shortcut icon" href="favicon.ico"/>
+ <link rel="stylesheet" href="css/prettify.css"/>
+
+ <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
+ <script type="text/javascript" src="js/jquery-ui-1.9.2.custom.min.js"></script>
+ <script type="text/javascript" src="js/sammy.0.7.1.js"></script>
+ <script type="text/javascript" data-main="js/archiva/archiva.js" src="js/require.2.1.2.js"></script>
+
+ <title>Apache Archiva</title>
+
+</head>
+
+<body id="body_content" style="padding-top: 42px;">
+
+<div id="topbar-menu-container"></div>
+
+<div class="container-fluid" style="min-height: 550px">
+ <div class="row-fluid">
+ <div class="span2 columns">
+ <div class="well sidebar-nav" id="sidebar-content"></div>
+ </div>
+ <div class="span10 columns">
+ <div class="content">
+ <div id="user-messages"></div>
+ <div id="main-content"></div>
+ </div>
+ </div>
+ </div>
+
+</div>
+
+<footer id="footer-content" style="vertical-align: bottom">
+</footer>
+
+<div id="html-fragments"></div>
+
+<div id="loadingDiv">
+ <div class="loading-indicator">
+ <img src="images/medium-spinner.gif" alt="Archiva loading"/>
+ <span id="loading-msg">Loading</span>
+ </div>
+</div>
+<noscript>
+Archiva needs Javascript, please check the Javascript configuration of your browser
+</noscript>
+</body>
+
+
+</html>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js
new file mode 100644
index 000000000..6c3bd992a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+appendArchivaVersion=function(){
+ return "_archivaVersion="+window.archivaRuntimeInfo.version;
+};
+
+timestampNoCache=function(){
+ if (window.archivaRuntimeInfo.version.match("SNAPSHOT$")){
+ return "&archivaTimestamp="+window.archivaRuntimeInfo.timestamp+(window.archivaRuntimeInfo.devMode?"&_="+jQuery.now():"");
+ }
+ return "";
+};
+
+appendTemplateUrl=function(){
+ return appendArchivaVersion()+timestampNoCache();
+};
+
+appendJsNoCacheUrl=function(){
+ return appendArchivaVersion()+timestampNoCache();
+};
+
+$.ajax({
+ url: "restServices/archivaUiServices/runtimeInfoService/archivaRuntimeInfo/en",
+ dataType: 'json',
+ cache: false,
+ success:function(data){
+
+ window.archivaDevMode=data.devMode;
+ window.archivaJavascriptLog=data.javascriptLog;
+ window.archivaRuntimeInfo=data;
+
+ requirejs.config({
+ baseUrl: "js/",
+ urlArgs: ""+appendJsNoCacheUrl(),
+ shim: {
+ 'sammy':['jquery','jquery.tmpl'],
+ 'archiva.main':['jquery','jquery.ui','sammy','jquery.tmpl','utils','i18n'],
+ 'utils':['jquery','jquery.tmpl','i18n'],
+ 'archiva.templates': ['jquery','jquery.tmpl','utils'],
+ 'redback.templates': ['jquery','jquery.tmpl','utils']
+ },
+ paths: {
+ "i18n":"jquery.i18n.properties-1.0.9",
+ "jquery": "jquery-1.8.3.min",
+ "jquery.tmpl": "jquery.tmpl",
+ "utils": "archiva/utils",
+ "startup": "archiva/startup",
+ "jquery.ui": "jquery-ui-1.9.2.custom.min",
+ "jquery.ui.widget": "jquery.ui.widget-1.9.2",
+ "jquery.cookie": "jquery.cookie.1.0.0",
+ "bootstrap": "bootstrap.2.2.1",
+ "jquery.validate": "jquery.validate-1.9.0",
+ "jquery.json": "jquery.json-2.3.min",
+ "knockout": "knockout-2.2.0.debug",
+ "knockout.simpleGrid": "knockout.simpleGrid",
+ "knockout.sortable": "knockout-sortable",
+ "jquery.iframe.transport": "jquery.iframe-transport-1.4",
+ "jquery.fileupload": "jquery.fileupload-5.10.0",
+ "jquery.fileupload.ip":"jquery.fileupload-ip-1.0.6",
+ "jquery.fileupload.ui":"jquery.fileupload-ui-6.6.3",
+ "tmpl": "tmpl.min",
+ "purl": "purl-2.2.1",
+ "prettify": "prettify",
+ "sammy": "sammy.0.7.1",
+ "select2": "select2.min-3.2",
+ "jqueryFileTree": "jqueryFileTree-1.0.1",
+ "redback": "redback/redback",
+ "redback.roles": "redback/roles",
+ "redback.user": "redback/user",
+ "redback.users": "redback/users",
+ "redback.templates": "redback/redback-tmpl",
+ "archiva.general-admin":"archiva/general-admin",
+ "archiva.templates": "archiva/main-tmpl",
+ "archiva.repositories": "archiva/repositories",
+ "archiva.network-proxies": "archiva/network-proxies",
+ "archiva.proxy-connectors": "archiva/proxy-connectors",
+ "archiva.repository-groups": "archiva/repository-groups",
+ "archiva.artifacts-management": "archiva/artifacts-management",
+ "archiva.search": "archiva/search",
+ "archiva.proxy-connectors-rules": "archiva/proxy-connectors-rules",
+ "archiva.docs": "archiva/docs",
+ "archiva.main": "archiva/main"
+ }
+ });
+
+ requirejs(['jquery','jquery.tmpl','jquery.ui','i18n','sammy','startup','utils','domReady!','archiva.main','archiva.general-admin'], function () {
+ loadi18n(function () {
+ $.ajax({
+ url: "restServices/archivaUiServices/runtimeInfoService/archivaRuntimeInfo/"+usedLang(),
+ dataType: 'json',
+ success:function(data){
+ window.archivaDevMode=data.devMode;
+ window.archivaJavascriptLog=data.javascriptLog;
+ window.archivaRuntimeInfo=data;
+
+ window.redbackRuntimeConfiguration=mapRedbackRuntimeConfiguration(data.redbackRuntimeConfiguration);
+
+ $.log("security.rememberme.enabled key value:"+ window.redbackRuntimeConfiguration.findPropertyValue('security.rememberme.enabled'));
+
+ require(['sammy','jquery','i18n','jquery.tmpl','archiva.main','utils','domReady!'],function () {
+ startArchivaApplication();
+ $("#loadingDiv").hide();
+ drawQuickSearchAutocomplete();
+ })
+ }
+ })
+ });
+ })
+ }
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/artifacts-management.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/artifacts-management.js
new file mode 100644
index 000000000..9a571355d
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/artifacts-management.js
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.artifacts-management",["jquery","i18n","utils","jquery.tmpl","knockout",
+ "knockout.simpleGrid","jquery.validate","bootstrap","jquery.fileupload","jquery.fileupload.ui"]
+ , function(jquery,i18n,utils,jqueryTmpl,ko) {
+
+ ArtifactUpload=function(classifier,pomFile){
+ this.classifier=classifier;
+ this.pomFile=pomFile;
+ }
+
+ ArtifactUploadViewModel=function(managedRepositories){
+ var self=this;
+ this.managedRepositories=ko.observableArray(managedRepositories);
+ this.repositoryId=ko.observable();
+ this.groupId=ko.observable();
+ this.artifactId=ko.observable();
+ this.version=ko.observable();
+ this.packaging=ko.observable();
+ this.generatePom=ko.observable();
+
+ this.artifactUploads=[];
+
+ saveArtifacts=function(){
+ clearUserMessages();
+ if(!$("#main-content" ).find("#fileupload" ).valid()){
+ return;
+ }
+ if(this.artifactUploads.length<1){
+ displayErrorMessage( $.i18n.prop("fileupload.upload.required"));
+ return;
+ }
+ var url="restServices/archivaUiServices/fileUploadService/save/"+this.repositoryId()+"/"+this.groupId()+"/"+this.artifactId();
+ url+="/"+this.version()+"/"+this.packaging();
+ if (this.generatePom()){
+ url+="?generatePom=true";
+ }
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop("fileupload.artifacts.saved"));
+ self.artifactUploads=[];
+ $("#main-content" ).find("#uploaded-files-list" ).empty();
+ $.ajax("restServices/archivaUiServices/fileUploadService/clearUploadedFiles", {type: "GET", dataType: 'json'});
+ clearForm("#main-content #fileupload");
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+
+ }
+
+ }
+
+ displayUploadArtifact=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+
+ $.ajax("restServices/archivaUiServices/fileUploadService/clearUploadedFiles", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ mainContent.html($("#file-upload-screen" ).html());
+ $.ajax("restServices/archivaServices/browseService/userRepositories", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var artifactUploadViewModel=new ArtifactUploadViewModel(data);
+ ko.applyBindings(artifactUploadViewModel,mainContent.find("#file-upload-main" ).get(0));
+ var fileUpload=$("#main-content" ).find("#fileupload");
+ $("#repositoryId" ).select2();
+ var validator = fileUpload.validate({
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #fileupload",validator,errorMap,errorMap);
+ }
+ });
+
+ fileUpload.fileupload({
+ submit: function (e, data) {
+ var $this = $(this);
+ $this.fileupload('send', data);
+ artifactUploadViewModel.artifactUploads.push(new ArtifactUpload(data.formData.classifier,data.formData.pomFile));
+ return false;
+ }
+ }
+ );
+ fileUpload.bind('fileuploadsubmit', function (e, data) {
+ var pomFile = data.context.find('#pomFile' ).attr("checked");
+ var classifier = data.context.find('#classifier' ).val();
+ if (!data.formData){
+ data.formData={};
+ }
+ data.formData.pomFile = pomFile;
+ data.formData.classifier = classifier;
+ });
+ }
+ });
+ }
+ });
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/docs.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/docs.js
new file mode 100644
index 000000000..5389cdd42
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/docs.js
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.docs",["jquery","i18n","jquery.tmpl","bootstrap"], function() {
+
+ displayRestDocs=function(){
+ $.log("displayRestDocs");
+ screenChange();
+ $("#main-content" ).html($("#rest_docs").tmpl());
+ }
+
+ goToArchivaRestDoc=function(target){
+ goToRestDoc(target,"rest-docs/rest-docs-archiva-rest-api");
+ }
+
+ goToArchivaRestUiDoc=function(target){
+
+ goToRestDoc(target,"rest-docs/rest-docs-archiva-ui");
+ }
+
+ goToRedbackRestDoc=function(target){
+
+ goToRestDoc(target,"rest-docs/rest-docs-redback-rest-api");
+ }
+
+ goToRestDoc=function(target,rootPath){
+ var mainContent = $("#main-content");
+ mainContent.find("#rest_docs_content" ).html(mediumSpinnerImg());
+ $.ajax({
+ url:rootPath+"/"+target,
+ type:"get",
+ dataType: "html",
+ success: function(data){
+ mainContent.html($("#rest_docs").tmpl());
+ if(target.endsWith(".xsd")){
+ mainContent.find("#rest_docs_content" ).html("<code id='xsd_content'></code>");
+ mainContent.find("#xsd_content" ).html(data);
+ } else {
+ mainContent.find("#rest_docs_content" ).html(data);
+ }
+
+ prettyPrint();
+ }
+ });
+ }
+
+ displayRedbackRestDocs=function(){
+ window.sammyArchivaApplication.setLocation("#rest-docs-redback-rest-api/index.html");
+ }
+
+ displayArchivaRestUIDocs=function(){
+ window.sammyArchivaApplication.setLocation("#rest-docs-archiva-ui/index.html");
+ }
+
+ displayArchivaRestDocs=function(){
+ window.sammyArchivaApplication.setLocation("#rest-docs-archiva-rest-api/index.html");
+ }
+
+ loadRestDocs=function(docType, fullPath){
+ $.log("loadRestDocs:"+docType+","+fullPath);
+ //if (docType=='rest-docs-archiva-rest-api'){
+ $.ajax({
+ url:fullPath,
+ type:"get",
+ dataType: "html",
+ success: function(data){
+ $("#main-content" ).find("#rest_docs_content" ).html(data);
+ prettyPrint();
+ }
+ });
+ //}
+ }
+
+ displayUsersDocs=function(){
+ $.log("displayUsersDocs");
+ window.open("");
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/general-admin.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/general-admin.js
new file mode 100644
index 000000000..0db8054b1
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/general-admin.js
@@ -0,0 +1,1585 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.general-admin",["jquery","i18n","utils","jquery.tmpl","knockout","knockout.simpleGrid",
+ "knockout.sortable","jquery.validate","bootstrap"]
+ , function(jquery,i18n,utils,jqueryTmpl,ko) {
+
+ //-------------------------
+ // legacy path part
+ //-------------------------
+
+ LegacyArtifactPath=function(path,groupId,artifactId,version,classifier,type,update){
+ //private String path;
+ this.path=ko.observable(path);
+
+ /**
+ * The artifact reference, as " [groupId] :
+ * [artifactId] : [version] : [classifier] : [type] ".
+ */
+ //private String artifact;
+ //this.artifact=ko.observable(artifact);
+ this.update=update;
+ //private String groupId;
+ this.groupId=ko.observable(groupId);
+
+ //private String artifactId;
+ this.artifactId=ko.observable(artifactId);
+
+ //private String version;
+ this.version=ko.observable(version);
+
+ //private String classifier;
+ this.classifier=ko.observable(classifier);
+
+ //private String type;
+ this.type=ko.observable(type);
+
+ this.modified=ko.observable();
+
+ this.artifact = ko.computed(function() {
+ var artifactValue="";
+ if (this.groupId()){
+ artifactValue+=this.groupId();
+ }
+ if (this.artifactId()){
+ artifactValue+=":"+this.artifactId();
+ }
+ if (this.version()){
+ artifactValue+=":"+this.version();
+ }
+ if (this.classifier()){
+ artifactValue+=":"+this.classifier();
+ }
+ if (this.type()){
+ artifactValue+=":"+this.type();
+ }
+ return artifactValue;
+ }, this);
+ };
+
+ mapLegacyArtifactPaths=function(data){
+ if (data){
+ return $.isArray(data)? $.map(data,function(item){
+ return mapLegacyArtifactPath(item);
+ }):[mapLegacyArtifactPath(data)];
+ }
+ return [];
+ };
+
+ mapLegacyArtifactPath=function(data){
+ return data?new LegacyArtifactPath(data.path,data.groupId,data.artifactId,data.version,data.classifier,data.type):null;
+ };
+
+ activateLegacyArtifactPathFormValidation=function(){
+ var theForm=$("#main-content" ).find("#legacy-artifact-paths-edit-form");
+ var validator = theForm.validate({
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #legacy-artifact-paths-edit-form",validator,errorMap,errorMap);
+ }
+ });
+ };
+
+ LegacyArtifactPathViewModel=function(legacyArtifactPath,update,legacyArtifactPathsViewModel){
+ var self=this;
+ this.update=update;
+ this.legacyArtifactPath=legacyArtifactPath;
+ this.legacyArtifactPathsViewModel=legacyArtifactPathsViewModel;
+
+ this.display=function(){
+ var mainContent=$("#main-content");
+ ko.applyBindings(self,mainContent.find("#legacy-artifact-paths-edit" ).get(0));
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-edit a").html($.i18n.prop("edit"));
+ activateLegacyArtifactPathFormValidation();
+ activateLegacyArtifactPathsEditTab();
+ };
+
+ displayGrid=function(){
+ activateLegacyArtifactPathsGridTab();
+ };
+
+ calculatePath=function(){
+ var path="";
+ if (self.legacyArtifactPath.groupId()){
+ path+=self.legacyArtifactPath.groupId()+"/jars/";
+ }
+ if (self.legacyArtifactPath.artifactId()){
+ path+=self.legacyArtifactPath.artifactId();
+ }
+ if (self.legacyArtifactPath.version()){
+ path+="-"+self.legacyArtifactPath.version();
+ }
+ if (self.legacyArtifactPath.classifier()){
+ path+="-"+self.legacyArtifactPath.classifier();
+ }
+ if (self.legacyArtifactPath.type()){
+ path+="."+self.legacyArtifactPath.type();
+ }
+ self.legacyArtifactPath.path(path);
+ };
+
+ this.save=function(){
+ var theForm=$("#main-content" ).find("#legacy-artifact-paths-edit-form");
+ if (!theForm.valid()){
+ return;
+ }
+ // do that on server side
+ /*if (theForm.find("#artifact" ).val()
+ !=theForm.find("#path" ).val()){
+ var errorList=[{
+ message: $.i18n.prop("path must match artifact"),
+ element: theForm.find("#path" ).get(0)
+ }];
+ customShowError("#main-content #legacy-artifact-paths-edit-form", null, null, errorList);
+ return;
+ }*/
+ // TODO call id exists if add ?
+ clearUserMessages();
+ $.log("save ok");
+ if (self.update){
+ $.log("update");
+ }else {
+ $.ajax("restServices/archivaServices/archivaAdministrationService/addLegacyArtifactPath",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(self.legacyArtifactPath),
+ dataType: 'json',
+ success: function(data) {
+ self.legacyArtifactPath.modified(false);
+ self.legacyArtifactPathsViewModel.legacyArtifactPaths.push(self.legacyArtifactPath);
+ displaySuccessMessage($.i18n.prop('legacy-artifact-path.added',self.legacyArtifactPath.path()));
+ activateLegacyArtifactPathsGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+ }
+ }
+ };
+
+ LegacyArtifactPathsViewModel=function(){
+ var self=this;
+ this.legacyArtifactPaths=ko.observableArray([]);
+
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.legacyArtifactPaths,
+ columns: [
+ {
+ headerText: $.i18n.prop('legacy-artifact-paths.path'),
+ rowText: "path"
+ },
+ {
+ headerText: $.i18n.prop('legacy-artifact-paths.artifact'),
+ rowText: "artifact"
+ }
+ ],
+ pageSize: 5,
+ gridUpdateCallBack: function(networkProxy){
+ $("#main-content").find("#legacy-artifact-paths-table" ).find("[title]").tooltip();
+ }
+ });
+
+
+ editLegacyArtifactPath=function(legacyArtifactPath){
+ var legacyArtifactPathViewModel=new LegacyArtifactPathViewModel(legacyArtifactPath,true);
+ legacyArtifactPathViewModel.display();
+ };
+
+ removeLegacyArtifactPath=function(legacyArtifactPath){
+
+ openDialogConfirm(
+ function(){
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/deleteLegacyArtifactPath?path="+encodeURIComponent(legacyArtifactPath.path()),
+ {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ self.legacyArtifactPaths.remove(legacyArtifactPath);
+ displaySuccessMessage($.i18n.prop('legacy-artifact-path.removed',legacyArtifactPath.path()));
+ activateLegacyArtifactPathsGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ closeDialogConfirm();
+ }
+ }
+ );
+ }, $.i18n.prop('ok'), $.i18n.prop('cancel'), $.i18n.prop('legacy-artifact-path.delete.confirm',legacyArtifactPath.path()),
+ $("#legacy-artifact-path-delete-warning-tmpl" ).tmpl(legacyArtifactPath));
+
+ };
+
+ updateLegacyArtifactPath=function(legacyArtifactPath){
+
+ }
+
+ };
+
+ displayLegacyArtifactPathSupport=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getLegacyArtifactPaths", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ mainContent.html($("#legacy-artifact-path-main").tmpl());
+ var legacyArtifactPathsViewModel=new LegacyArtifactPathsViewModel();
+ var legacyPaths=mapLegacyArtifactPaths(data);
+ $.log("legacyPaths:"+legacyPaths.length);
+ legacyArtifactPathsViewModel.legacyArtifactPaths(legacyPaths);
+ ko.applyBindings(legacyArtifactPathsViewModel,mainContent.find("#legacy-artifact-paths-view" ).get(0));
+
+ mainContent.find("#legacy-artifact-paths-view-tabs").on('show', function (e) {
+ if ($(e.target).attr("href")=="#legacy-artifact-paths-edit") {
+ var viewModel = new LegacyArtifactPathViewModel(new LegacyArtifactPath(),false,legacyArtifactPathsViewModel);
+ viewModel.display();
+ activateLegacyArtifactPathFormValidation();
+ clearUserMessages();
+ }
+ if ($(e.target).attr("href")=="#legacy-artifact-paths-view") {
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-edit a").html($.i18n.prop("add"));
+ clearUserMessages();
+ }
+
+ });
+
+
+ activateLegacyArtifactPathsGridTab();
+ }
+ });
+
+
+ };
+
+
+ activateLegacyArtifactPathsGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-edit").removeClass("active");
+ mainContent.find("#legacy-artifact-paths-edit").removeClass("active");
+
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-grid").addClass("active");
+ mainContent.find("#legacy-artifact-paths-view").addClass("active");
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-edit a").html($.i18n.prop("add"));
+
+ };
+
+ activateLegacyArtifactPathsEditTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-grid").removeClass("active");
+ mainContent.find("#legacy-artifact-paths-view").removeClass("active");
+
+ mainContent.find("#legacy-artifact-paths-view-tabs-li-edit").addClass("active");
+ mainContent.find("#legacy-artifact-paths-edit").addClass("active");
+ };
+
+
+ //---------------------------
+ // repository scanning part
+ //---------------------------
+
+ FileType=function(id,patterns){
+ //private String id;
+ this.id=ko.observable(id);
+
+ //private List<String> patterns;
+ this.patterns=ko.observableArray(patterns);
+
+ };
+
+ mapFileType=function(data){
+ return new FileType(data.id,data.patterns);
+ };
+
+ mapFileTypes=function(data){
+ if (data!=null){
+ return $.isArray(data)? $.map(data,function(item){
+ return mapFileType(item)
+ }):[mapFileType(data)];
+ }
+ return [];
+ };
+
+ AdminRepositoryConsumer=function(enabled,id,description){
+ //private boolean enabled = false;
+ this.enabled=ko.observable(enabled);
+
+ //private String id;
+ this.id=ko.observable(id)
+
+ //private String description;
+ this.description=ko.observable(description);
+ }
+
+ mapAdminRepositoryConsumer=function(data){
+ return new AdminRepositoryConsumer(data.enabled,data.id,data.description);
+ }
+
+ mapAdminRepositoryConsumers=function(data){
+ if (data!=null){
+ return $.isArray(data)? $.map(data,function(item){
+ return mapAdminRepositoryConsumer(item)
+ }):[mapAdminRepositoryConsumer(data)];
+ }
+ return [];
+ }
+
+
+
+ RepositoryScanningViewModel=function(){
+ var self=this;
+ this.fileTypes=ko.observableArray([]);
+ this.knownAdminRepositoryConsumers=ko.observableArray([]);
+ this.invalidAdminRepositoryConsumers=ko.observableArray([]);
+
+ this.findFileType=function(id){
+ var fileType=null;
+ for (var i=0;i<self.fileTypes().length;i++){
+ if (id==self.fileTypes()[i].id()){
+ fileType=self.fileTypes()[i];
+ }
+ }
+ return fileType;
+ }
+
+ removeFileTypePattern=function(id,pattern){
+ clearUserMessages();
+ var url="restServices/archivaServices/archivaAdministrationService/removeFileTypePattern?"
+ url+="fileTypeId="+encodeURIComponent(id);
+ url+="&pattern="+encodeURIComponent(pattern);
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ self.findFileType(id ).patterns.remove(pattern);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.file-types.removed.pattern",id,pattern));
+
+ }
+ });
+ }
+
+ addFileTypePattern=function(id){
+ var pattern=$("#main-content #pattern-"+id ).val();
+ $.log("addFileTypePattern:"+id+":"+pattern);
+ clearUserMessages();
+ var url="restServices/archivaServices/archivaAdministrationService/addFileTypePattern?"
+ url+="fileTypeId="+encodeURIComponent(id);
+ url+="&pattern="+encodeURIComponent(pattern);
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ self.findFileType(id ).patterns.push(pattern);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.file-types.added.pattern",id,pattern));
+
+ }
+ });
+ }
+
+ disableKnowContentConsumer=function(adminRepositoryConsumer){
+ $.log("disableKnowContentConsumer");
+ clearUserMessages();
+ var userMessages=$("#user-messages" )
+ userMessages.html(mediumSpinnerImg());
+ var url="restServices/archivaServices/archivaAdministrationService/disabledKnownContentConsumer/"
+ url+=encodeURIComponent(adminRepositoryConsumer.id());
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ adminRepositoryConsumer.enabled(false);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.consumers.know.disabled",adminRepositoryConsumer.id()));
+ removeMediumSpinnerImg(userMessages);
+ }
+ });
+ }
+
+ enableKnowContentConsumer=function(adminRepositoryConsumer){
+ clearUserMessages();
+ var userMessages=$("#user-messages" )
+ userMessages.html(mediumSpinnerImg());
+ var url="restServices/archivaServices/archivaAdministrationService/enabledKnownContentConsumer/"
+ url+=encodeURIComponent(adminRepositoryConsumer.id());
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ adminRepositoryConsumer.enabled(true);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.consumers.know.enabled",adminRepositoryConsumer.id()));
+ removeMediumSpinnerImg(userMessages);
+ }
+ });
+ }
+
+ disableInvalidContentConsumer=function(adminRepositoryConsumer){
+ clearUserMessages();
+ var url="restServices/archivaServices/archivaAdministrationService/disabledInvalidContentConsumer/"
+ url+=encodeURIComponent(adminRepositoryConsumer.id());
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ adminRepositoryConsumer.enabled(false);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.consumers.invalid.disabled",adminRepositoryConsumer.id()));
+ }
+ });
+ }
+
+ enableInvalidContentConsumer=function(adminRepositoryConsumer){
+ clearUserMessages();
+ var url="restServices/archivaServices/archivaAdministrationService/enabledInvalidContentConsumer/"
+ url+=encodeURIComponent(adminRepositoryConsumer.id());
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ adminRepositoryConsumer.enabled(true);
+ displaySuccessMessage( $.i18n.prop("repository-scanning.consumers.invalid.enabled",adminRepositoryConsumer.id()));
+ }
+ });
+ }
+
+ }
+
+ displayRepositoryScanning=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+
+ mainContent.html($("#repository-scanning-main").tmpl());
+ mainContent.find("#file-types-content").html(mediumSpinnerImg());
+ mainContent.find("#consumers-known-content").html(mediumSpinnerImg());
+ mainContent.find("#consumers-invalid-content").html(mediumSpinnerImg());
+
+ var repositoryScanningViewModel=new RepositoryScanningViewModel();
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getFileTypes", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ var fileTypes=mapFileTypes(data);
+ repositoryScanningViewModel.fileTypes(fileTypes);
+ ko.applyBindings(repositoryScanningViewModel,mainContent.find("#file-types-content").get(0));
+ }
+ });
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getKnownContentAdminRepositoryConsumers", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ var knownAdminRepositoryConsumers=mapAdminRepositoryConsumers(data);
+ repositoryScanningViewModel.knownAdminRepositoryConsumers(knownAdminRepositoryConsumers);
+ ko.applyBindings(repositoryScanningViewModel,mainContent.find("#consumers-known-content").get(0));
+ }
+ });
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getInvalidContentAdminRepositoryConsumers", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ var invalidAdminRepositoryConsumers=mapAdminRepositoryConsumers(data);
+ repositoryScanningViewModel.invalidAdminRepositoryConsumers(invalidAdminRepositoryConsumers);
+ ko.applyBindings(repositoryScanningViewModel,mainContent.find("#consumers-invalid-content").get(0));
+ }
+ });
+
+ }
+
+ //---------------------------
+ // network configuration part
+ //---------------------------
+
+ NetworkConfiguration=function(maxTotal,maxTotalPerHost,usePooling){
+ //private int maxTotal = 30;
+ this.maxTotal=ko.observable(maxTotal);
+
+ //private int maxTotalPerHost = 30;
+ this.maxTotalPerHost=ko.observable(maxTotalPerHost);
+
+ //private boolean usePooling = true;
+ this.usePooling=ko.observable(usePooling);
+ }
+
+ NetworkConfigurationViewModel=function(networkConfiguration){
+ var self=this;
+ this.networkConfiguration=ko.observable(networkConfiguration);
+
+ save=function(){
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ var mainContent=$("#main-content");
+ if (!mainContent.find("#network-configuration-edit-form").valid()){
+ return;
+ }
+ mainContent.find("#network-configuration-btn-save" ).button('loading');
+ $.ajax("restServices/archivaServices/archivaAdministrationService/setNetworkConfiguration", {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(self.networkConfiguration),
+ dataType: 'json',
+ success: function(data){
+ displaySuccessMessage( $.i18n.prop("network-configuration.updated"));
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ mainContent.find("#network-configuration-btn-save" ).button('reset');
+ }
+ });
+ }
+ }
+
+ displayNetworkConfiguration=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getNetworkConfiguration", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ mainContent.html($("#network-configuration-screen").tmpl());
+ var networkConfiguration=new NetworkConfiguration(data.maxTotal,data.maxTotalPerHost,data.usePooling);
+ var networkConfigurationViewModel=new NetworkConfigurationViewModel(networkConfiguration);
+ ko.applyBindings(networkConfigurationViewModel,mainContent.get(0));
+ var validator = mainContent.find("#network-configuration-edit-form").validate({
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError(mainContent.find("#network-configuration-edit-form" ).get(0),validator,errorMap,errorMap);
+ }
+ });
+ }
+ });
+
+ }
+
+ //---------------------------
+ // UiConfiguration part
+ //---------------------------
+
+ displayUiConfiguration=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getUiConfiguration", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ mainContent.html($("#ui-configuration-screen").tmpl());
+ var uiConfiguration=new UiConfiguration(data.showFindArtifacts,data.appletFindEnabled,data.disableEasterEggs,
+ data.applicationUrl,data.disableRegistration);
+ var uiConfigurationViewModel=new UiConfigurationViewModel(uiConfiguration);
+ ko.applyBindings(uiConfigurationViewModel,mainContent.get(0));
+ }
+ });
+ }
+
+ UiConfiguration=function(showFindArtifacts,appletFindEnabled,disableEasterEggs,applicationUrl,disableRegistration){
+ this.showFindArtifacts = ko.observable(showFindArtifacts);
+
+ this.appletFindEnabled = ko.observable(appletFindEnabled);
+
+ this.disableEasterEggs = ko.observable(disableEasterEggs);
+
+ this.applicationUrl = ko.observable(applicationUrl);
+
+ // default to false
+ this.disableRegistration = ko.observable(disableRegistration?disableRegistration:false);
+ }
+
+ UiConfigurationViewModel=function(uiConfiguration){
+ this.uiConfiguration=ko.observable(uiConfiguration);
+ var self=this;
+ save=function(){
+ var mainContent=$("#main-content" );
+ var userMessages=$("#user-messages");
+ userMessages.html( mediumSpinnerImg());
+ mainContent.find("#ui-configuration-btn-save" ).button('loading');
+ $.ajax("restServices/archivaServices/archivaAdministrationService/setUiConfiguration", {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(self.uiConfiguration),
+ dataType: 'json',
+ success: function(data){
+ displaySuccessMessage( $.i18n.prop("ui-configuration.updated"));
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ mainContent.find("#ui-configuration-btn-save" ).button('reset');
+ }
+ });
+ }
+ }
+
+
+ //---------------------------
+ // System status part
+ //---------------------------
+
+ QueueEntry=function(key,entriesNumber){
+ this.key=key;
+ this.entriesNumber=entriesNumber;
+ }
+
+
+ mapQueueEntries=function(data){
+ if (data!=null){
+ return $.map(data,function(item){
+ return new QueueEntry(item.key,item.entriesNumber);
+ })
+ }
+ return [];
+ }
+
+ CacheEntry=function(key,size,cacheHits,cacheMiss,cacheHitRate,inMemorySize){
+ this.key=key;
+ this.size=size;
+ this.cacheHits=cacheHits;
+ this.cacheMiss=cacheMiss;
+ this.cacheHitRate=cacheHitRate;
+ this.inMemorySize=inMemorySize;
+ }
+
+ mapCacheEntries=function(data){
+ if(data!=null){
+ return $.map(data,function(item){
+ return new CacheEntry(item.key,item.size,item.cacheHits,item.cacheMiss,item.cacheHitRate,item.inMemorySize);
+ })
+ }
+ return [];
+ }
+
+
+
+ displayCacheEntries=function(){
+ var divContent = $("#main-content" ).find("#status_caches");
+ divContent.html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/cacheEntries", {
+ type: "GET",
+ success: function(data){
+ var cacheEntries=mapCacheEntries(data);
+ divContent.html($("#status_caches_tmpl" ).tmpl({cacheEntries: cacheEntries}));
+ }
+ });
+ }
+
+ flushCache=function(key){
+ clearUserMessages();
+ $("#main-content" ).find("#status_caches").html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/clearCache/"+encodeURIComponent(key), {
+ type: "GET",
+ success: function(data){
+ displaySuccessMessage( $.i18n.prop("system-status.caches.flushed",key));
+ displayCacheEntries();
+ }
+ });
+ }
+
+ flushAllCaches=function(){
+ clearUserMessages();
+ $("#main-content" ).find("#status_caches").html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/clearAllCaches", {
+ type: "GET",
+ success: function(data){
+ displaySuccessMessage( $.i18n.prop("system-status.caches.all.flushed"));
+ displayCacheEntries();
+ }
+ });
+ }
+
+ mapRepositoryScannerStatisticsList=function(data){
+ if(data!=null){
+ return $.isArray(data)? $.map(data,function(item){
+ return mapRepositoryScannerStatistics(item);
+ }):[data];
+ }
+ return [];
+ }
+
+
+ mapRepositoryScannerStatistics=function(data){
+ return new RepositoryScannerStatistics(mapManagedRepository(data.managedRepository),data.totalFileCount,
+ data.newFileCount,data.consumerScanningStatistics);
+ }
+
+ RepositoryScannerStatistics=function(managedRepository,totalFileCount,newFileCount,consumerScanningStatisticsList){
+ //private ManagedRepository managedRepository;
+ this.managedRepository=managedRepository
+
+ this.consumerScanningStatisticsList= consumerScanningStatisticsList;
+
+ //private long totalFileCount = 0;
+ this.totalFileCount=totalFileCount;
+
+ //private long newFileCount = 0;
+ this.newFileCount=newFileCount;
+ }
+
+ displayScanningStats=function(){
+ var divContent = $("#main-content" ).find("#status_scanning");
+ divContent.html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/repositoryScannerStatistics", {
+ type: "GET",
+ success: function(data){
+ var stats= mapRepositoryScannerStatisticsList(data);
+ $.log("size:"+data.length);
+ divContent.html($("#status_scanning_tmpl").tmpl({repositoryScannerStatisticsList:stats}));
+ }
+ });
+ }
+
+ displayMemoryUsage=function(){
+ var divContent = $("#main-content" ).find("#status_memory_info");
+ divContent.html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/memoryStatus", {
+ type: "GET",
+ dataType: "text",
+ success: function(data){
+ var memUsage = data;
+ $.log("memUsage:"+memUsage);
+ divContent.html(memUsage);
+ }
+ });
+ }
+
+ displayQueueEntries=function(){
+ var divContent = $("#main-content" ).find("#status_queues");
+ divContent.html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/queueEntries", {
+ type: "GET",
+ success: function(data){
+ var queueEntries=mapQueueEntries(data);
+ divContent.html($("#status_queues_tmpl" ).tmpl({queueEntries: queueEntries}));
+ }
+ });
+ }
+
+ displayServerTime=function(){
+ var divContent = $("#main-content" ).find("#status_current_time");
+ divContent.html(smallSpinnerImg());
+ $.ajax("restServices/archivaServices/systemStatusService/currentServerTime/"+encodeURIComponent(usedLang()), {
+ type: "GET",
+ dataType: "text",
+ success: function(data){
+ var curTime=data;
+ $.log("currentServerTime:"+curTime);
+ divContent.html(curTime);
+ }
+ });
+ }
+
+ displaySystemStatus=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html($("#system-status-main").tmpl());
+
+ var versionInfo=window.archivaRuntimeInfo.version+" - "
+ +$.i18n.prop('system-status.header.version.buildNumber')+": "+window.archivaRuntimeInfo.buildNumber
+ +" - "+$.i18n.prop('system-status.header.version.timestampStr')+": "+window.archivaRuntimeInfo.timestampStr;
+ mainContent.find("#status_version_info").html(versionInfo);
+
+ displayMemoryUsage();
+
+ displayServerTime();
+
+ displayQueueEntries();
+
+ displayScanningStats();
+
+ displayCacheEntries();
+ }
+
+ refreshSystemStatus=function(){
+ displayCacheEntries();
+ displayScanningStats();
+ displayMemoryUsage();
+ displayQueueEntries();
+ displayServerTime();
+ }
+
+ //---------------------------
+ // network configuration part
+ //---------------------------
+ OrganisationInformation=function(name,url,logoLocation){
+ this.name=ko.observable(name);
+ this.url=ko.observable(url);
+ this.logoLocation=ko.observable(logoLocation);
+ }
+ mapOrganisationInformation=function(data){
+ return new OrganisationInformation(data.name, data.url, data.logoLocation);
+ }
+ mapOrganisationInformations=function(data){
+ if (data!=null){
+ return $.isArray(data)? $.map(data, function(item){
+ return mapOrganisationInformation(item);
+ }):[mapOrganisationInformation(data)];
+ }
+ }
+ activateOrganisationInformationFormValidation=function(){
+ var validate = $("#main-content" ).find("#appearance-configuration-form-id").validate({
+ rules: {
+ name: {
+ required: true
+ },
+ url: {
+ required:true,
+ url:true
+ },
+ logoLocation: {
+ required:false,
+ url:true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #appearance-configuration-form-id", validator, errorMap, errorMap);
+ }
+ })
+ }
+ OrganisationInformationViewModel=function(organisationInformation){
+ activateOrganisationInformationFormValidation();
+ this.organisationInformation=ko.observable(organisationInformation);
+
+ this.save=function(){
+ var mainContent=$("#main-content" );
+ if (!mainContent.find("#appearance-configuration-form-id").valid()) {
+ return;
+ }
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ mainContent.find("#appearance-configuration-btn-save" ).button('loading');
+ $.ajax("restServices/archivaServices/archivaAdministrationService/setOrganisationInformation", {
+ type: "POST",
+ contentType: "application/json",
+ data: ko.toJSON(this.organisationInformation),
+ dataType: "json",
+ success: function(data){
+ displaySuccessMessage($.i18n.prop('appearance-configuration.updated'));
+ updateAppearanceToolBar();
+ },
+ error: function(data){
+ displayErrorMessage($.i18n.prop('appearance-configuration.updating-error'));
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ mainContent.find("#appearance-configuration-btn-save" ).button('reset');
+ }
+ });
+ }
+ }
+ displayAppearanceConfiguration=function(){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getOrganisationInformation", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ mainContent.html($("#changeAppearance").tmpl());
+ var organisationInformation=new OrganisationInformation(data.name,data.url,data.logoLocation);
+ var organisationInformationViewModel=new OrganisationInformationViewModel(organisationInformation);
+ ko.applyBindings(organisationInformationViewModel, mainContent.get(0));
+ var validator = $("#main-content" ).find("#appearance-configuration-form-id").validate({
+ showErrors: function(validator,errorMap,errorList) {
+ customShowError(mainContent.find("#appearance-configuration-form-id").get(0),validator,errorMap,errorMap);
+ }
+ });
+ }
+ });
+ }
+
+ //---------------------------
+ // report configuration page
+ //---------------------------
+ StatisticsReportRequest=function() {
+ this.repositories = ko.observableArray( [] );
+ this.rowCount = ko.observable(100);
+ this.startDate = ko.observable();
+ this.endDate = ko.observable();
+ }
+
+ reportStatisticsFormValidator=function(){
+ $.log("reportStatisticsFormValidator");
+ var validate = $("#main-content" ).find("#report-statistics-form-id").validate({
+ rules: {
+ rowCountStatistics: {
+ required:true,
+ number: true,
+ min: 10
+ },
+ startDate: {
+ date: true
+ },
+ endDate: {
+ date: true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ $.log("showErrors");
+ customShowError("#main-content #report-statistics-form-id", validator, errorMap, errorMap);
+ }
+ })
+ }
+ ReportStatisticsViewModel=function(repositoriesAvailable){
+ var mainContent=$("#main-content");
+ reportStatisticsFormValidator();
+
+ var self=this;
+ this.availableRepositories = ko.observableArray( repositoriesAvailable );
+ this.statisticsReport = ko.observable( new StatisticsReportRequest() );
+
+ mainContent.find("#startDate" ).datepicker();
+ mainContent.find("#endDate" ).datepicker();
+ mainContent.find("#rowcount-info-button" ).popover();
+
+ this.showStatistics=function() {
+ $.log("showStatistics");
+ clearUserMessages( "repositoriesErrorMessage" );
+ if (!mainContent.find("#report-statistics-form-id").valid()) {
+ return;
+ }
+ if(this.statisticsReport().repositories().length==0){
+ displayErrorMessage( $.i18n.prop('report.statistics.repositories.required'), "repositoriesErrorMessage" );
+ return;
+ }
+
+ var resultTabContent = mainContent.find("#report-result");
+
+ url = "restServices/archivaServices/reportServices/getStatisticsReport/?rowCount="
+ + this.statisticsReport().rowCount();
+
+ for(var i=0;i<this.statisticsReport().repositories().length;i++){
+ url += "&repository=" + this.statisticsReport().repositories()[i];
+ }
+
+ if(this.statisticsReport().startDate()!=null){
+ url += "&startDate=" + this.statisticsReport().startDate();
+ }
+ if(this.statisticsReport().endDate()!=null){
+ url += "&endDate=" + this.statisticsReport().endDate();
+ }
+
+ $.ajax(url, {
+ type: "GET",
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data){
+ resultTabContent.html( $( "#report-statistics" ).tmpl() );
+ var reportStatistics = new ReportStatisticsResultViewModel( data );
+ ko.applyBindings( reportStatistics, resultTabContent.get( 0 ) );
+ var reportResultTabLi=$( "#report-result-tab-li");
+ reportResultTabLi.removeClass( "hide" );
+ reportResultTabLi.addClass( "active" );
+ $( "#report-stat-tab-li" ).removeClass( "active" );
+ $( "#report-stat-tab-content" ).removeClass( "active" );
+ resultTabContent.addClass( "active" );
+ },
+ error: function(data){
+ var res = $.parseJSON(data.responseText);
+ displayErrorMessage($.i18n.prop(res.errorMessage));
+ }
+ });
+ }
+ }
+ ReportStatisticsResultViewModel=function(report){
+ this.reports = ko.observableArray( report );
+ var self = this;
+
+ this.tableReportViewModel = new ko.simpleGrid.viewModel({
+ data: this.reports,
+ viewModel: this,
+ columns: [
+ { headerText: "Repository ID", rowText: "repositoryId" },
+ { headerText: "Start Date", rowText: function(item){return new Date(item.scanStartTime);}},
+ { headerText: "Total File Count", rowText: "totalFileCount" },
+ { headerText: "Total Size", rowText: "totalArtifactFileSize" },
+ { headerText: "Artifact Count", rowText: "totalArtifactCount" },
+ { headerText: "Group Count", rowText: "totalGroupCount" },
+ { headerText: "Project Count", rowText: "totalProjectCount" },
+ { headerText: "Archetypes", rowText: function (item) { return item.totalCountForType.pom === "" ? item.totalCountForType.pom : "0"} },
+ { headerText: "Jars", rowText: function (item) { return item.totalCountForType.jar === "" ? item.totalCountForType.jar : "0" } },
+ { headerText: "Wars", rowText: function (item) { return item.totalCountForType.war === "" ? item.totalCountForType.war : "0" } },
+ { headerText: "Ears", rowText: function (item) { return item.totalCountForType.ear === "" ? item.totalCountForType.ear : "0" } },
+ { headerText: "Exes", rowText: function (item) { return item.totalCountForType.exe === "" ? item.totalCountForType.exe : "0" } },
+ { headerText: "Dlls", rowText: function (item) { return item.totalCountForType.dll === "" ? item.totalCountForType.dll : "0" } },
+ { headerText: "Zips", rowText: function (item) { return item.totalCountForType.zip === "" ? item.totalCountForType.zip : "0" } }
+ ],
+ pageSize: 10
+ });
+ }
+
+ HealthReportRequest=function(){
+ this.repositoryId = ko.observable();
+ this.rowCount = ko.observable(100);
+ this.groupId = ko.observable();
+ }
+ HealthReportResult=function(repositoryId,namespace,project,version,id,message,problem,name,facetId){
+ this.repositoryId = repositoryId;
+ this.namespace = namespace;
+ this.project = project;
+ this.version = version;
+ this.id = id;
+ this.message = message;
+ this.problem = problem;
+ this.name = name;
+ this.facetId = facetId;
+ }
+ mapHealthReportResult=function(data){
+ if(data==null) return;
+ return new HealthReportResult( data.repositoryId, data.namespace, data.project, data.version, data.id, data.message,
+ data.problem, data.name, data.facetId );
+ }
+ mapHealthReportResults=function(data){
+ if (data != null)
+ {
+ return $.isArray(data)? $.map(data, function(item){
+ return mapHealthReportResult(item);
+ }):[mapHealthReportResult(data)];
+ }
+ return [];
+ }
+ ReportHealthResultViewModel=function(report){
+ this.reports = ko.observableArray( report );
+ var self = this;
+ this.tableReportViewModel = new ko.simpleGrid.viewModel({
+ data: this.reports,
+ viewModel: this,
+ columns: [
+ { headerText: "ID", rowText: "id" },
+ { headerText: "Namespace", rowText: "namespace" },
+ { headerText: "Project", rowText: "project" },
+ { headerText: "Version", rowText: "version" },
+ { headerText: "Name", rowText: "name" },
+ { headerText: "Problem", rowText: "problem" },
+ { headerText: "Message", rowText: "message" }
+ ],
+ pageSize: 10
+ });
+ }
+
+ reportHealthFormValidator=function(){
+ var validate = $("#main-content" ).find("#report-health-form-id").validate({
+ rules: {
+ rowCountHealth: {
+ required: true,
+ number: true,
+ min: 10
+ },
+ repositoryId: {
+ required: true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #report-health-form-id", validator, errorMap, errorMap);
+ }
+ })
+ }
+ ReportHealthViewModel=function(){
+ reportHealthFormValidator();
+ this.healthReport = ko.observable(new HealthReportRequest());
+
+ this.showHealth=function() {
+ if (!$("#main-content" ).find("#report-health-form-id").valid()) {
+ return;
+ }
+
+ var resultTabContent = $("#main-content" ).find("#report-result");
+
+ var url =
+ "restServices/archivaServices/reportServices/getHealthReports/" + this.healthReport().repositoryId() + "/"
+ + this.healthReport().rowCount();
+
+ if (this.healthReport().groupId())
+ {
+ url += "?groupId=" + this.healthReport().groupId();
+ }
+
+ $.ajax(url, {
+ type: "GET",
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data){
+ var reports = new ReportHealthResultViewModel( mapHealthReportResults( data ) );
+ resultTabContent.html( $( "#report-health" ).tmpl() );
+ ko.applyBindings( reports, resultTabContent.get( 0 ) );
+ var reportResultTabLi=$( "#report-result-tab-li" );
+ reportResultTabLi.removeClass( "hide" );
+ reportResultTabLi.addClass( "active" );
+ $( "#report-health-tab-li" ).removeClass( "active" );
+ $( "#report-health-tab-content" ).removeClass( "active" );
+ resultTabContent.addClass( "active" );
+ },
+ error: function(data){
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ });
+ }
+ }
+
+ displayReportsPage=function(){
+ screenChange();
+ clearUserMessages();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ $.ajax("restServices/archivaServices/searchService/observableRepoIds", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var repos = mapStringList( data );
+ mainContent.html( $( "#report-base" ).tmpl( {repositoriesList:repos} ) );
+ var statisticsReportViewModel = ReportStatisticsViewModel( repos );
+ var healthReportViewModel = ReportHealthViewModel( );
+ ko.applyBindings( statisticsReportViewModel, mainContent.get( 0 ) );
+ ko.applyBindings( healthReportViewModel, mainContent.get( 0 ) );
+ }
+ });
+ }
+
+
+ RedbackRuntimeConfiguration=function(userManagerImpls,ldapConfiguration,migratedFromRedbackConfiguration,configurationPropertiesEntries
+ ,useUsersCache,cacheConfiguration){
+ $.log("new RedbackRuntimeConfiguration");
+ var self=this;
+ this.modified=ko.observable(false);
+ this.modified.subscribe(function(newValue){$.log("RedbackRuntimeConfiguration modified")});
+
+ this.userManagerImpls=ko.observableArray(userManagerImpls);
+ this.userManagerImpls.subscribe(function(newValue){self.modified(true)});
+
+ this.ldapConfiguration=ko.observable(ldapConfiguration);
+ this.ldapConfiguration.subscribe(function(newValue){self.modified(true)});
+
+ this.migratedFromRedbackConfiguration=ko.observable(migratedFromRedbackConfiguration);
+
+ $.log("new RedbackRuntimeConfiguration before configurationPropertiesEntries mapping:");
+
+ this.configurationPropertiesEntries=ko.observableArray(configurationPropertiesEntries?configurationPropertiesEntries:[]);
+ this.configurationPropertiesEntries.subscribe(function(newValue){
+ self.modified(true);
+ $.log("configurationPropertiesEntries modified")
+ });
+
+ $.log("new RedbackRuntimeConfiguration before configurationPropertiesEntries mapping done");
+
+ this.findPropertyValue=function(key){
+ for(var i=0;i<self.configurationPropertiesEntries().length;i++){
+ if(self.configurationPropertiesEntries()[i].key==key){
+ var val = self.configurationPropertiesEntries()[i].value;
+ $.log("findPropertyValue " + key + "->" + val);
+ return val;
+ }
+ }
+ }
+
+ this.useUsersCache=ko.observable(useUsersCache);
+ this.useUsersCache.subscribe(function(newValue){self.modified(true)});
+
+ this.usersCacheConfiguration=ko.observable(cacheConfiguration);
+ this.usersCacheConfiguration.subscribe(function(newValue){self.modified(true)});
+
+
+ }
+
+ mapRedbackRuntimeConfiguration=function(data){
+ $.log("mapRedbackRuntimeConfiguration");
+ var ldapConfiguration=mapLdapConfiguration(data.ldapConfiguration);
+ $.log("mapLdapConfiguration done for ");
+
+ var redbackRuntimeConfiguration =
+ new RedbackRuntimeConfiguration(data.userManagerImpls,ldapConfiguration,data.migratedFromRedbackConfiguration,[]
+ ,data.useUsersCache,mapCacheConfiguration(data.usersCacheConfiguration));
+
+ $.log("mapRedbackRuntimeConfiguration done");
+ var configurationPropertiesEntries = data.configurationPropertiesEntries == null ? []: $.each(data.configurationPropertiesEntries,function(item){
+ return new Entry(item.key, item.value,function(newValue){
+ redbackRuntimeConfiguration.modified(true);
+ });
+ });
+ if (!$.isArray(configurationPropertiesEntries)){
+ configurationPropertiesEntries=[];
+ }
+ redbackRuntimeConfiguration.configurationPropertiesEntries(configurationPropertiesEntries);
+ redbackRuntimeConfiguration.modified(false);
+ return redbackRuntimeConfiguration;
+
+ }
+
+ LdapConfiguration=function(hostName,port,ssl,baseDn,contextFactory,bindDn,password,authenticationMethod,
+ extraPropertiesEntries){
+
+ var self=this;
+ this.modified=ko.observable(false);
+
+ //private String hostName;
+ this.hostName=ko.observable(hostName);
+ this.hostName.subscribe(function(newValue){self.modified(true)});
+
+ //private String port;
+ this.port=ko.observable(port);
+ this.port.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean ssl = false;
+ this.ssl=ko.observable(ssl);
+ this.ssl.subscribe(function(newValue){self.modified(true)});
+
+ //private String baseDn;
+ this.baseDn=ko.observable(baseDn);
+ this.baseDn.subscribe(function(newValue){self.modified(true)});
+
+ //private String contextFactory;
+ this.contextFactory=ko.observable(contextFactory);
+ this.contextFactory.subscribe(function(newValue){self.modified(true)});
+
+ //private String bindDn;
+ this.bindDn=ko.observable(bindDn);
+ this.bindDn.subscribe(function(newValue){self.modified(true)});
+
+ //private String password;
+ this.password=ko.observable(password);
+ this.password.subscribe(function(newValue){self.modified(true)});
+
+ //private String authenticationMethod;
+ this.authenticationMethod=ko.observable(authenticationMethod);
+ this.authenticationMethod.subscribe(function(newValue){self.modified(true)});
+
+ this.extraPropertiesEntries=ko.observableArray(extraPropertiesEntries);
+ this.extraPropertiesEntries.subscribe(function(newValue){self.modified(true)});
+ }
+
+ mapLdapConfiguration=function(data){
+ $.log("mapLdapConfiguration");
+ if(data){
+ var extraPropertiesEntries = data.extraPropertiesEntries == null ? []: $.each(data.extraPropertiesEntries,function(item){
+ return new Entry(item.key, item.value);
+ });
+ if (!$.isArray(extraPropertiesEntries)){
+ extraPropertiesEntries=[];
+ }
+ $.log("mapLdapConfiguration done");
+ return new LdapConfiguration(data.hostName,data.port,data.ssl,data.baseDn,data.contextFactory,data.bindDn,data.password,
+ data.authenticationMethod,extraPropertiesEntries);
+ }
+ return null;
+ }
+
+ RedbackRuntimeConfigurationViewModel=function(redbackRuntimeConfiguration,userManagerImplementationInformations){
+ var self=this;
+ this.redbackRuntimeConfiguration=ko.observable(redbackRuntimeConfiguration);
+ this.userManagerImplementationInformations=ko.observable(userManagerImplementationInformations);
+
+ this.usedUserManagerImpls=ko.observableArray([]);
+
+ self.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.redbackRuntimeConfiguration().configurationPropertiesEntries,
+ columns: [
+ {
+ headerText: $.i18n.prop('redback.runtime.properties.key.label'),
+ rowText: "key"
+ },
+ {
+ headerText: $.i18n.prop('redback.runtime.properties.value.label'),
+ rowText: "value"
+ }
+ ],
+ pageSize: 10,//self.redbackRuntimeConfiguration().configurationPropertiesEntries.length,
+ gridUpdateCallBack: function(){
+ activatePopoverDoc();
+ }
+ });
+
+ findUserManagerImplementationInformation=function(id){
+ for(var i= 0;i<self.userManagerImplementationInformations().length;i++){
+ $.log(id+""+self.userManagerImplementationInformations()[i].beanId);
+ if(id==self.userManagerImplementationInformations()[i].beanId){
+ return self.userManagerImplementationInformations()[i];
+ }
+ }
+ }
+
+ checkLdapServerConfiguration=function(){
+ $.log("checkLdapServerConfiguration");
+ clearUserMessages();
+ var btn = $("#ldap-configuration-check-server");
+ btn.button('loading');
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $.log("checkChangedLdapConfiguration");
+ $.ajax("restServices/archivaServices/redbackRuntimeConfigurationService/checkLdapConnection",
+ {
+ type: "GET",
+ success: function(data) {
+ var message=$.i18n.prop('redback.runtime.ldap.verified');
+ displaySuccessMessage(message);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ removeMediumSpinnerImg(userMessages);
+ btn.button('reset');
+ }
+ }
+ );
+ }
+
+ checkChangedLdapConfiguration=function(){
+ clearUserMessages();
+ var btn = $("#ldap-configuration-check-modification");
+ btn.button('loading');
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $.log("checkChangedLdapConfiguration");
+ $.ajax("restServices/archivaServices/redbackRuntimeConfigurationService/checkLdapConnection",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data:ko.toJSON(self.redbackRuntimeConfiguration().ldapConfiguration),
+ dataType: 'json',
+ success: function(data) {
+ var message=$.i18n.prop('redback.runtime.ldap.verified');
+ displaySuccessMessage(message);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ removeMediumSpinnerImg(userMessages);
+ btn.button('reset');
+ }
+ }
+ );
+ }
+
+ for(var i= 0;i<redbackRuntimeConfiguration.userManagerImpls().length;i++){
+ var id=redbackRuntimeConfiguration.userManagerImpls()[i];
+ $.log("id:"+id);
+ var userManagerImplementationInformation=findUserManagerImplementationInformation(id);
+
+ if(userManagerImplementationInformation!=null){
+ this.usedUserManagerImpls.push(userManagerImplementationInformation);
+ }
+ }
+
+ isUsedUserManagerImpl=function(userManagerImplementationInformation){
+ for(var i=0;i<self.usedUserManagerImpls().length;i++){
+ if(self.usedUserManagerImpls()[i].beanId==userManagerImplementationInformation.beanId){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ this.availableUserManagerImpls=ko.observableArray([]);
+
+ for(var i=0;i<self.userManagerImplementationInformations().length;i++){
+ if(!isUsedUserManagerImpl(self.userManagerImplementationInformations()[i])){
+ self.availableUserManagerImpls.push(self.userManagerImplementationInformations()[i]);
+ }
+
+ }
+
+ userManagerImplMoved=function(arg){
+ $.log("userManagerImplMoved");
+ self.redbackRuntimeConfiguration().modified(true);
+ }
+
+ saveRedbackRuntimeConfiguration=function(){
+ var mainContent=$("#main-content");
+ var valid = mainContent.find("#redback-runtime-general-form-id").valid();
+ if (valid==false) {
+ return;
+ }
+ var useLdap = false;
+ for(var i=0;i<self.usedUserManagerImpls().length;i++){
+ var beanId=self.usedUserManagerImpls()[i].beanId;
+ $.log("beanId:"+beanId);
+ if(beanId=='ldap'){
+ useLdap=true;
+ }
+ }
+ $.log("useLdap:"+useLdap);
+ if(useLdap==true) {
+ valid = mainContent.find("#redback-runtime-ldap-form-id").valid();
+ $.log("ldap valid:"+valid);
+ if (valid==false) {
+ return;
+ }
+ }
+
+ $.log("saveRedbackRuntimeConfiguration");
+ var saveButton = mainContent.find("#redback-runtime-configuration-save" );
+ saveButton.button('loading');
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ self.redbackRuntimeConfiguration().userManagerImpls=ko.observableArray([]);
+
+ for(var i=0;i<self.usedUserManagerImpls().length;i++){
+ var beanId=self.usedUserManagerImpls()[i].beanId;
+ $.log("beanId:"+beanId);
+ self.redbackRuntimeConfiguration().userManagerImpls.push(beanId);
+ }
+ $.log("rememberme enabled:"+self.redbackRuntimeConfiguration().findPropertyValue("security.rememberme.enabled"));
+ $.ajax("restServices/archivaServices/redbackRuntimeConfigurationService/redbackRuntimeConfiguration",
+ {
+ type: "PUT",
+ contentType: 'application/json',
+ data:ko.toJSON(self.redbackRuntimeConfiguration),
+ dataType: 'json',
+ success: function(data) {
+ var message=$.i18n.prop('redback-runtime-configuration.updated');
+ displaySuccessMessage(message);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ removeMediumSpinnerImg(userMessages);
+ saveButton.button('reset');
+ self.redbackRuntimeConfiguration().modified(false);
+ self.redbackRuntimeConfiguration().ldapConfiguration().modified(false);
+ }
+ }
+ );
+
+ }
+ }
+
+ UserManagerImplementationInformation=function(beanId,descriptionKey,readOnly){
+ this.beanId=beanId;
+ this.descriptionKey=descriptionKey;
+ this.description= $.i18n.prop(descriptionKey);
+ this.readOnly=readOnly;
+ }
+
+ mapUserManagerImplementationInformations=function(data){
+ return $.map(data, function(item) {
+ return mapUserManagerImplementationInformation(item);
+ });
+ }
+
+ mapUserManagerImplementationInformation=function(data){
+ if(data==null){
+ return null;
+ }
+ return new UserManagerImplementationInformation(data.beanId,data.descriptionKey,data.readOnly);
+ }
+
+ activateRedbackRuntimeGeneralFormValidation=function(){
+ var formSelector=$("#main-content" ).find("#redback-runtime-general-form-id");
+ var validator = formSelector.validate({
+ rules: {
+ usersCacheTimeToLiveSeconds : {
+ digits: true,
+ min: 1,
+ required: true
+ },
+ usersCacheTimeToIdleSeconds : {
+ digits: true,
+ min: 1,
+ required: true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError(formSelector,validator,errorMap,errorMap);
+ }
+ });
+ }
+
+ activateLdapConfigurationFormValidation=function(){
+ var formSelector=$("#main-content" ).find("#redback-runtime-ldap-form-id");
+ var validator = formSelector.validate({
+ rules: {
+ ldapHost : {
+ digits: true,
+ min: 1,
+ required: true
+ },
+ ldapPort : {
+ digits: true,
+ min: 1,
+ required: true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError(formSelector,validator,errorMap,errorMap);
+ }
+ });
+ }
+
+ displayRuntimeConfiguration=function(){
+ $.log("displayRuntimeConfiguration");
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+ $.ajax("restServices/archivaServices/redbackRuntimeConfigurationService/userManagerImplementationInformation", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var userManagerImplementationInformations=mapUserManagerImplementationInformations(data);
+ $.ajax("restServices/archivaServices/redbackRuntimeConfigurationService/redbackRuntimeConfiguration", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ // TODO use window.redbackRuntimeConfiguration ?
+ window.redbackRuntimeConfiguration = mapRedbackRuntimeConfiguration(data);
+ var redbackRuntimeConfigurationViewModel =
+ new RedbackRuntimeConfigurationViewModel(window.redbackRuntimeConfiguration,userManagerImplementationInformations);
+ mainContent.html( $("#redback-runtime-configuration-main" ).tmpl() );
+ ko.applyBindings(redbackRuntimeConfigurationViewModel,$("#redback-runtime-configuration-content" ).get(0));
+ activateRedbackRuntimeGeneralFormValidation();
+ activateLdapConfigurationFormValidation();
+ }
+ });
+
+ }
+ });
+
+ }
+
+ CacheConfiguration=function(timeToIdleSeconds,timeToLiveSeconds){
+ var self=this;
+ this.modified=ko.observable(false);
+
+ this.timeToIdleSeconds=ko.observable(timeToIdleSeconds);
+ this.timeToIdleSeconds.subscribe(function(newValue){self.modified(true)});
+
+ this.timeToLiveSeconds=ko.observable(timeToLiveSeconds);
+ this.timeToLiveSeconds.subscribe(function(newValue){self.modified(true)});
+
+ }
+
+ mapCacheConfiguration=function(data){
+ if(!data){
+ return new CacheConfiguration();
+ }
+ return new CacheConfiguration(data.timeToIdleSeconds,data.timeToLiveSeconds);
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main-tmpl.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main-tmpl.js
new file mode 100644
index 000000000..1ca725c7c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main-tmpl.js
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+require(['jquery',"jquery.tmpl",'i18n',"utils","text!templates/archiva/menu.html",
+ "text!templates/archiva/generics.html",
+ "text!templates/archiva/modal.html",
+ "text!templates/archiva/repositories.html",
+ "text!templates/archiva/search.html",
+ "text!templates/archiva/general-admin.html",
+ "text!templates/archiva/docs.html"],
+ function(jquery,jqueryTmpl,i18n,utils,menu,generics,modal,repositories,
+ search,general_admin,docs) {
+ loadArchivaTemplate=function(){
+ var htmlFragment=$("#html-fragments");
+ // template loading
+ htmlFragment.append(menu);
+ htmlFragment.append(generics);
+ $.tmpl( modal ).appendTo(htmlFragment);
+ $.tmpl( docs ).appendTo(htmlFragment);
+ htmlFragment.append(repositories);
+ htmlFragment.append(search);
+ htmlFragment.append(general_admin);
+ $.log("main-tmpl.js loaded");
+ }
+ }
+); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js
new file mode 100644
index 000000000..653cb6590
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js
@@ -0,0 +1,879 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.main",["jquery","jquery.ui","sammy","jquery.tmpl",'i18n',"jquery.cookie","bootstrap","archiva.search",
+ "jquery.validate","jquery.json","knockout","redback.templates","archiva.templates",
+ "redback.roles","redback","archiva.general-admin","archiva.repositories",
+ "archiva.network-proxies","archiva.proxy-connectors","archiva.repository-groups","archiva.artifacts-management",
+ "archiva.proxy-connectors-rules","archiva.docs"],
+function(jquery,ui,sammy,tmpl,i18n,jqueryCookie,bootstrap,archivaSearch,jqueryValidate,jqueryJson,ko) {
+
+ /**
+ * reccord a cookie for session with the logged user
+ * @param user see user.js
+ */
+ reccordLoginCookie=function(user) {
+
+ var path = window.redbackRuntimeConfiguration.findPropertyValue("security.rememberme.path");
+ path = path ? path : "/";
+
+ var domain = window.redbackRuntimeConfiguration.findPropertyValue("security.rememberme.domain");
+ var secure = window.redbackRuntimeConfiguration.findPropertyValue("security.rememberme.secure");
+
+ var expires= Number(window.redbackRuntimeConfiguration.findPropertyValue("security.rememberme.timeout"));
+
+ var userJson=ko.toJSON(user);
+
+ $.log("reccordLoginCookie:expires:"+expires+",path:"+path+",domain:"+domain+",secure:"+secure+",user:"+userJson);
+
+ var options = null;
+ if (secure == 'true'){
+ options = {
+ expires: expires,
+ path: path,
+ domain: domain,
+ secure: secure
+ }
+ }else {
+ options = {
+ expires: expires,
+ path: path,
+ domain: domain
+ }
+ }
+
+ $.cookie('archiva_login', userJson,options);
+ };
+
+ getUserFromLoginCookie=function(){
+ var cookieContent=$.cookie('archiva_login');
+ $.log("archiva_login cookie content:"+cookieContent);
+ var user = $.parseJSON(cookieContent);
+ if(!user){
+ return null;
+ }
+ var kUser = new User(user.username, user.password, user.confirmPassword,user.fullName,user.email,user.permanent,user.validated,
+ user.timestampAccountCreation,user.timestampLastLogin,user.timestampLastPasswordChange,user.locked,
+ user.passwordChangeRequired,null,user.readOnly,user.userManagerId)
+
+ kUser.rememberme(user.rememberme);
+ return kUser;
+ };
+
+
+
+ logout=function(doScreenChange){
+ var user = getUserFromLoginCookie();
+ if(user){
+ user.logged=false;
+ reccordLoginCookie(user);
+ }
+ $("#login-link").show();
+ $("#register-link").show();
+ $("#logout-link").hide();
+ $("#change-password-link").hide();
+ // cleanup karmas
+ window.redbackModel.operatioNames=[];
+ hideElementWithKarma();
+ $("#main-content").empty();
+ $("#user-messages" ).empty();
+ $.ajax({
+ url: 'restServices/redbackServices/loginService/logout',
+ complete: function(){
+ // go to welcome on logout
+ window.sammyArchivaApplication.setLocation("#search");
+ }
+
+ });
+ };
+
+
+
+ decorateMenuWithKarma=function(user) {
+ var username = user.username;
+ $.log("decorateMenuWithKarma");
+ // we can receive an observable user so take if it's a function or not
+ if ($.isFunction(username)){
+ username = user.username();
+ }
+ var url = 'restServices/redbackServices/userService/getCurrentUserOperations';
+ $.ajax({
+ url: url,
+ success: function(data){
+ var mappedOperations = $.map(data, function(item) {
+ return mapOperation(item);
+ });
+ window.redbackModel.operatioNames = $.map(mappedOperations, function(item){
+ return item.name();
+ });
+
+ $("#topbar-menu-container").find("[redback-permissions]").each(function(element){
+ checkElementKarma(this);
+ });
+ $("#sidebar-content").find("[redback-permissions]").each(function(element){
+ checkElementKarma(this);
+ });
+ checkUrlParams();
+ }
+ });
+ };
+
+ checkElementKarma=function(element){
+ var bindingValue = $(element).attr("redback-permissions");
+ $(element).hide();
+ var neededKarmas = $(eval(bindingValue)).toArray();
+ var karmaOk = false;
+ $(neededKarmas).each(function(value){
+ if ($.inArray(neededKarmas[value],window.redbackModel.operatioNames)>=0) {
+ karmaOk = true;
+ }
+ });
+ if (karmaOk == false) {
+ $(element).hide();
+ } else {
+ $(element).show();
+ }
+ };
+
+ hideElementWithKarma=function(){
+ $("#topbar-menu-container [redback-permissions]").each(function(element){
+ $(this).hide();
+ });
+
+ $("#sidebar-content").find("[redback-permissions]").each(function(element){
+ $(this).hide();
+ });
+ $.log("hideElementWithKarma");
+ };
+
+ //------------------------------------//
+ // Change UI with appearance settings //
+ //------------------------------------//
+ updateAppearanceToolBar=function() {
+ $.ajax("restServices/archivaServices/archivaAdministrationService/registrationDisabled", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ //var disableRegistration=data.disableRegistration;
+ var topbarMenu=$("#topbar-menu");
+ if( data){
+ $.log("disableRegistration");
+ topbarMenu.find("#register-link" ).hide();
+ }
+ $.ajax("restServices/archivaServices/archivaAdministrationService/getOrganisationInformation", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var organisationLogo=topbarMenu.find("#organisation-logo");
+ if(data.url){
+ var url = data.url.startsWith("http://") || data.url.startsWith("https://") ? data.url : "http://"+data.url;
+ var link="<a href='"+url+"' class='brand'>";
+ if (data.logoLocation) {
+ link+="<img src='"+data.logoLocation+"' style='max-height: 30px'/>";
+ } else if (data.name) {
+ link+=data.name;
+ } else {
+ link+="Archiva";
+ }
+ link+="</a>";
+ organisationLogo.html(link);
+ }
+ if (!data.url && data.name){
+ organisationLogo.html("<a href='/' class='brand'>"+data.name+"</a>");
+ }
+ if (!data.url && !data.name){
+ organisationLogo.html("<a href='/' class='brand'>Archiva</a>");
+ }
+ },
+ error: function() {
+ organisationLogo.html("<a href='/' class='brand'>Archiva</a>");
+ }
+ });
+ }});
+ };
+
+
+ MainMenuViewModel=function() {
+
+ var self = this;
+ this.artifactMenuItems = ko.observableArray([
+ { text : $.i18n.prop('menu.artifacts') , id: null},
+ { text : $.i18n.prop('menu.artifacts.search') , id: "menu-find-search-a", href: "#search" , func: function(){displaySearch(this)}},
+ { text : $.i18n.prop('menu.artifacts.browse') , id: "menu-find-browse-a", href: "#browse" , func: function(){displayBrowse(true)}},
+ { text : $.i18n.prop('menu.artifacts.upload') , id: "menu-find-upload-a", href: "#upload" , redback: "{permissions: ['archiva-upload-repository']}", func: function(){displayUploadArtifact(true)}}
+ ]);
+ this.administrationMenuItems = ko.observableArray([
+ { text : $.i18n.prop('menu.administration') , id: null},
+ { text : $.i18n.prop('menu.repository.groups') , id: "menu-repository-groups-list-a" , href: "#repositorygroup" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayRepositoryGroups()}},
+ { text : $.i18n.prop('menu.repositories') , id: "menu-repositories-list-a" , href: "#repositorylist" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayRepositoriesGrid()}},
+ { text : $.i18n.prop('menu.proxy-connectors') , id: "menu-proxy-connectors-list-a" , href: "#proxyconnectors" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayProxyConnectors()}},
+ { text : $.i18n.prop('menu.proxy-connectors-rules') , id: "menu.proxy-connectors-rules-list-a" , href: "#proxyconnectorsrules" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayProxyConnectorsRules()}},
+ { text : $.i18n.prop('menu.network-proxies') , id: "menu-network-proxies-list-a" , href: "#networkproxies" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayNetworkProxies()}},
+ { text : $.i18n.prop('menu.legacy-artifact-support') , id: "menu-legacy-support-list-a" , href: "#legacy" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayLegacyArtifactPathSupport()}},
+ { text : $.i18n.prop('menu.repository-scanning') , id: "menu-repository-scanning-list-a" , href: "#scanningList" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayRepositoryScanning()}},
+ { text : $.i18n.prop('menu.network-configuration') , id: "menu-network-configuration-list-a" , href: "#network" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayNetworkConfiguration()}},
+ { text : $.i18n.prop('menu.system-status') , id: "menu-system-status-list-a" , href: "#status" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displaySystemStatus()}},
+ { text : $.i18n.prop('menu.appearance-configuration') , id: "menu-appearance-list-a" , href: "#appearance" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayAppearanceConfiguration()}},
+ { text : $.i18n.prop('menu.ui-configuration') , id: "menu-ui-configuration-list-a" , href: "#uiconfig" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayUiConfiguration()}},
+ { text : $.i18n.prop('menu.reports') , id: "menu-report-list-a" , href: "#reports" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayReportsPage()}}
+ ]);
+
+ this.usersMenuItems = ko.observableArray([
+ { text : $.i18n.prop('menu.users') , id: null},
+ { text : $.i18n.prop('menu.users.manage') , id: "menu-users-list-a", href: "#users" , redback: "{permissions: ['archiva-manage-users']}", func: function(){displayUsersGrid()}},
+ { text : $.i18n.prop('menu.users.roles') , id: "menu-roles-list-a", href: "#roles" , redback: "{permissions: ['archiva-manage-users']}", func: function(){displayRolesGrid()}},
+ { text : $.i18n.prop('menu.runtime-configuration') , id: "menu-runtime-configuration-list-a" , href: "#runtimeconfig" , redback: "{permissions: ['archiva-manage-configuration']}", func: function(){displayRuntimeConfiguration()}}
+ ]);
+
+ this.docsMenuItems = ko.observableArray([
+ { text : $.i18n.prop('menu.docs') , id: null},
+ { text : $.i18n.prop('menu.docs.rest') , id: "menu-docs-rest-list-a", href: "#docs-rest", target: "", func: function(){displayRestDocs()}},
+ { text : $.i18n.prop('menu.docs.users') , id: "menu-docs-users-list-a", href: "http://archiva.apache.org/docs/"+window.archivaRuntimeInfo.version, target: "_blank", func: function(){displayUsersDocs()}}
+ ]);
+
+ this.activeMenuId = ko.observable();
+
+ window.sammyArchivaApplication = Sammy(function () {
+
+ this.get('#quicksearch~:artifactId',function(){
+ self.activeMenuId("search");
+ $("#main-content" ).html(mediumSpinnerImg());
+ var artifactId= this.params.artifactId;
+ // user can be in a non search view so init the search view first
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.artifactId(artifactId);
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.externalAdvancedSearch();
+ },searchViewModel);
+ });
+
+ this.get('#basicsearch/:queryterms',function(){
+ self.activeMenuId("search");
+ var queryterms= this.params.queryterms;
+ $.log("queryterms:"+queryterms);
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.queryTerms(queryterms);
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.externalBasicSearch();
+ },searchViewModel);
+
+ });
+ this.get('#basicsearch~:repositoryIds/:queryterms',function(){
+ self.activeMenuId("search");
+ var queryterms= this.params.queryterms;
+ var repositoryIds = this.params.repositoryIds;
+ var repos = repositoryIds.split("~");
+ $.log("queryterms:"+queryterms+',repositoryIds:'+repositoryIds+",repos:"+repos.length);
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.queryTerms(queryterms);
+ searchRequest.repositories=repos;
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.externalBasicSearch();
+ },searchViewModel);
+ });
+
+ this.get('#basicsearch~:repositoryIds/:queryterms',function(){
+ self.activeMenuId("search");
+ var queryterms= this.params.queryterms;
+ var repositoryIds = this.params.repositoryIds;
+ var repos = repositoryIds.split("~");
+ $.log("queryterms:"+queryterms+',repositoryIds:'+repositoryIds+",repos:"+repos.length);
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.queryTerms(queryterms);
+ searchRequest.repositories=repos;
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.externalBasicSearch();
+ },searchViewModel);
+ });
+
+ this.get('#basicsearch/:queryterms',function(){
+ self.activeMenuId("search");
+ var queryterms= this.params.queryterms;
+ $.log("queryterms:"+queryterms);
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.queryTerms(queryterms);
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.externalBasicSearch();
+ },searchViewModel);
+ });
+
+ var advancedSearchRoute=function(params){
+ self.activeMenuId("search");
+ var repositoryIds = params.repositoryIds;
+ var repos = repositoryIds ? repositoryIds.split("~"):[];
+ var queryTerms = params.queryterms;
+ var terms=queryTerms?queryTerms.split('~'):[];
+ $.log("queryTerms:"+queryTerms+",terms.length:"+terms.length);
+ var groupId= terms.length>0?terms[0]:"";
+ var artifactId= terms.length>1?terms[1]:"";
+ var version= terms.length>2?terms[2]:"";
+ var classifier= terms.length>3?terms[3]:"";
+ var packaging= terms.length>4?terms[4]:"";
+ var className= terms.length>5?terms[5]:"";
+ $.log("groupId:artifactId:version:classifier:packaging:className="+groupId+':'+artifactId+':'+version+':'+classifier+':'+packaging+':'+className);
+ var searchViewModel = new SearchViewModel();
+ var searchRequest = new SearchRequest();
+ searchRequest.groupId(groupId);
+ searchRequest.artifactId(artifactId);
+ searchRequest.version(version);
+ searchRequest.classifier(classifier);
+ searchRequest.packaging(packaging);
+ searchRequest.className(className);
+ //searchRequest.repositories=repos;
+ //searchRequest.selectedRepoIds=repos;
+ searchViewModel.searchRequest(searchRequest);
+ displaySearch(function(){
+ searchViewModel.search("restServices/archivaServices/searchService/searchArtifacts",repos);
+ },searchViewModel);
+ };
+
+ this.get("#advancedsearch/:queryterms",function(){
+ advancedSearchRoute(this.params);
+ });
+
+ this.get("#advancedsearch~:repositoryIds/:queryterms",function(){
+ advancedSearchRoute(this.params);
+ });
+
+
+ this.get('#open-admin-create-box',function(){
+ $.log("#open-admin-create-box");
+ adminCreateBox();
+ });
+
+ // #artifact-(optionnal repositoryId)
+ // format groupId:artifactId org.apache.maven.plugins:maven-jar-plugin
+ // or groupId:artifactId:version org.apache.maven.plugins:maven-jar-plugin:2.3.1
+ this.get('#artifact/:groupId/:artifactId',function(context){
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ $.log("get #artifact:"+groupId+":"+artifactId);
+ self.activeMenuId("browse");
+ goToBrowseArtifactDetail(groupId,artifactId);//,null,null);
+ });
+ this.get('#artifact~:repositoryId/:groupId/:artifactId',function(context){
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var repositoryId = this.params.repositoryId;
+ self.activeMenuId("browse");
+ $.log("get #artifact:"+groupId+":"+artifactId);
+ goToBrowseArtifactDetail(groupId,artifactId,repositoryId);//,null,null);
+ });
+
+
+ var checkArtifactDetailContent=function(groupId,artifactId,version,repositoryId,tabToActivate,idContentToCheck,contentDisplayFn,classifier){
+ self.activeMenuId("browse");
+ // no need to recalculate all stuff just activate the tab
+ var htmlId = idContentToCheck?idContentToCheck:"browse_artifact_detail";
+ // olamy: cause some issues when browsing so desactivate this fix until more check
+ // navigating from dependencies list or dependency or used by of an artifact to fix in search.js
+ /*
+ var htmlIdSelect = $("#main-content").find("#"+htmlId );
+ if(htmlIdSelect.html()!=null){
+ if( $.trim(htmlIdSelect.html().length)>0){
+ $("#main-content #"+tabToActivate).tab('show');
+ $.log("checkArtifactDetailContent " + htmlId + " html not empty no calculation, tabToActivate:"+tabToActivate);
+ return;
+ }
+ }
+ */
+
+ var artifactAvailableUrl="restServices/archivaServices/browseService/artifactAvailable/"+encodeURIComponent(groupId)+"/"+encodeURIComponent(artifactId);
+ artifactAvailableUrl+="/"+encodeURIComponent(version);
+ if(classifier){
+ artifactAvailableUrl+="/"+encodeURIComponent(classifier);
+ }
+
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ artifactAvailableUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $("#main-content").html( mediumSpinnerImg());
+ $.ajax(artifactAvailableUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ // TODO take of the result true or false
+ //$.log("artifactAvailable:"+data);
+ generalDisplayArtifactDetailsVersionView(groupId,artifactId,version,repositoryId,
+ function(artifactVersionDetailViewModel){
+ $("#main-content #"+tabToActivate).tab('show');
+ if(contentDisplayFn){
+ contentDisplayFn(groupId,artifactId,version,artifactVersionDetailViewModel);
+ }
+ }
+ );
+
+ }
+ });
+
+
+ };
+
+ this.get('#artifact/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-info-content-a");
+ });
+ this.get('#artifact~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-info-content-a");
+ });
+
+ this.get('#artifact/:groupId/:artifactId/:version/:classifier',function(context){
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ var classifier= this.params.classifier;
+ checkArtifactDetailContent(groupId,artifactId,version,null,"artifact-details-info-content-a",null,null,classifier);
+ });
+
+ this.get('#artifact~:repositoryId/:groupId/:artifactId/:version/:classifier',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ var classifier= this.params.classifier;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-info-content-a",null,null,classifier);
+ });
+
+ this.get('#artifact-dependencies/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependencies-content-a");
+
+ });
+
+ this.get('#artifact-dependencies/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependencies-content-a");
+
+ });
+
+ this.get('#artifact-dependencies~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependencies-content-a");
+ });
+
+ this.get('#artifact-details-download-content/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+
+ checkArtifactDetailContent(groupId,artifactId,version,null,"artifact-details-download-content-a","artifact-details-download-content",
+ function(groupId,artifactId,version,artifactVersionDetailViewModel){
+ displayArtifactDownloadContent(artifactVersionDetailViewModel);
+ });
+
+ });
+
+ this.get('#artifact-details-download-content~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-download-content-a","artifact-details-download-content",
+ function(groupId,artifactId,version,artifactVersionDetailViewModel){
+ displayArtifactDownloadContent(artifactVersionDetailViewModel);
+ });
+ });
+
+
+ this.get('#artifact-dependency-tree/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependency-tree-content-a");
+ });
+
+ this.get('#artifact-dependency-tree~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependency-tree-content-a");
+ });
+
+ this.get('#artifact-mailing-list/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-mailing-list-content-a");
+ });
+
+ this.get('#artifact-mailing-list~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-mailing-list-content-a");
+ });
+
+
+ var calculateUsedBy=function(groupId,artifactId,version){
+ var dependeesContentDiv=$("#main-content" ).find("#artifact-details-used-by-content" );
+ var dependeesTable=dependeesContentDiv.find("#artifact-usedby-table");
+
+ dependeesContentDiv.append(mediumSpinnerImg());
+ var dependeesUrl="restServices/archivaServices/browseService/dependees/"+encodeURIComponent(groupId);
+ dependeesUrl+="/"+encodeURIComponent(artifactId);
+ dependeesUrl+="/"+encodeURIComponent(version);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ dependeesUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $.ajax(dependeesUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var artifacts=mapArtifacts(data);
+ var gridViewModel = new ko.simpleGrid.viewModel({
+ data: artifacts,
+ columns: [],
+ pageSize: 7,
+ gridUpdateCallBack: function(){
+ // no op
+ }
+ });
+ $.log("artifacts:"+artifacts.length);
+ dependeesTable.attr("data-bind",
+ "simpleGrid: gridViewModel,simpleGridTemplate:'dependees_tmpl',pageLinksId:'usedbyPagination',data:'artifacts'");
+ ko.applyBindings({artifacts:artifacts,gridViewModel:gridViewModel},dependeesContentDiv.get(0));
+ },
+ complete: function(){
+ removeMediumSpinnerImg(dependeesContentDiv);
+ }
+ });
+
+ };
+
+ this.get('#artifact-used-by/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-used-by-content-a","artifact-details-used-by-content",calculateUsedBy);
+ });
+
+ this.get('#artifact-used-by~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-used-by-content-a","artifact-details-used-by-content",calculateUsedBy);
+ });
+
+ var calculateMetadatas=function(groupId,artifactId,version,artifactVersionDetailViewModel){
+
+ var metadatasContentDiv=$("#main-content" ).find("#artifact-details-metadatas-content" );
+ var metadatasUrl="restServices/archivaServices/browseService/metadatas/"+encodeURIComponent(groupId);
+ metadatasUrl+="/"+encodeURIComponent(artifactId);
+ metadatasUrl+="/"+encodeURIComponent(version);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ metadatasUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+
+ //fixe self.entries not in the scope
+
+ $.ajax(metadatasUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var entries= $.map(data,function(e,i){
+ return new MetadataEntry( e.key, e.value,false);
+ });
+ artifactVersionDetailViewModel.entries(entries);
+ }
+ });
+ };
+
+ this.get('#artifact-metadatas/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-metadatas-content-a",null,calculateMetadatas);
+ });
+
+ this.get('#artifact-metadatas~:repositoryId/:groupId/:artifactId/:version',function(context){
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-metadatas-content-a",null,calculateMetadatas);
+ });
+
+
+ this.get('#browse/:groupId',function(context){
+ var groupId = this.params.groupId;
+ if (groupId){
+ displayBrowseGroupId(groupId);
+ } else {
+ displayBrowse(true);
+ }
+ });
+ this.get('#browse~:repositoryId/:groupId',function(context){
+ var groupId = this.params.groupId;
+ var repositoryId = this.params.repositoryId;
+ $.log("repositoryId:"+repositoryId);
+ if (groupId){
+ displayBrowseGroupId(groupId,repositoryId);
+ } else {
+ displayBrowse(true,repositoryId);
+ }
+ });
+ this.get('#browse~:repositoryId',function(context){
+ var repositoryId = this.params.repositoryId;
+ $.log("repositoryId:"+repositoryId);
+ displayBrowse(true,repositoryId);
+ });
+
+ this.get('#welcome', function () {
+ $.log("#welcome hash");
+ checkCreateAdminLink(function(){window.sammyArchivaApplication.setLocation("#search")});
+
+ });
+
+ this.get('#:folder', function () {
+ var folder = this.params.folder;
+ self.activeMenuId(folder);
+ var baseItems = self.artifactMenuItems()?self.artifactMenuItems():[];
+ ko.utils.arrayFirst(baseItems.concat(self.usersMenuItems(), self.administrationMenuItems(),self.docsMenuItems()), function(p) {
+ if ( p.href == "#"+self.activeMenuId()) {
+ screenChange();
+ p.func();
+ }
+ });
+ });
+
+ this.get("#rest-docs-archiva-rest-api/:target",function(){
+ var target=this.params.target;
+ $.log("archiva-rest-docs, target:"+target);
+ goToArchivaRestDoc(target);
+ });
+
+ this.get("#rest-docs-archiva-ui/:target",function(){
+ var target=this.params.target;
+ $.log("archiva-rest-docs-ui, target:"+target);
+ goToArchivaRestUiDoc(target);
+ });
+
+ this.get("#rest-docs-redback-rest-api/:target",function(){
+ var target=this.params.target;
+ $.log("redback-rest-docs, target:"+target);
+ goToRedbackRestDoc(target);
+ });
+
+ this.get("#managedrepositoryedit/:repositoryId",function(){
+ var repositoryId=this.params.repositoryId;
+ $.log("edit managed repository:"+repositoryId);
+ displayRepositoriesGrid(function(managedRepositoriesViewModel){managedRepositoriesViewModel.editManagedRepositoryWithId(repositoryId)});
+ });
+
+ this.get("#repositorygroupedit/:groupId",function(){
+ var groupId=this.params.groupId;
+ $.log("edit repository group:"+groupId);
+ displayRepositoryGroups(function(repositoryGroupsViewModel){repositoryGroupsViewModel.editRepositoryGroupWithId(groupId)});
+
+ });
+
+
+ });
+ };
+
+ userLoggedCallbackFn=function(user){
+ $.log("userLoggedCallbackFn:"+ (user?user.username():null));
+ var loginLink=$("#login-link");
+ var registerLink=$("#register-link");
+ var changePasswordLink=$("#change-password-link");
+ if (!user) {
+ loginLink.show();
+ registerLink.show();
+ changePasswordLink.hide();
+ checkUrlParams();
+ } else {
+ changePasswordLink.show();
+ $("#logout-link").show();
+ registerLink.hide();
+ loginLink.hide();
+ decorateMenuWithKarma(user);
+ }
+ };
+
+ checkSecurityLinks=function(){
+ userLogged(userLoggedCallbackFn);
+ };
+
+ checkCreateAdminLink=function(callbackFn){
+ $.ajax("restServices/redbackServices/userService/isAdminUserExists", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var adminExists = data;
+ window.archivaModel.adminExists=adminExists;
+ var createAdminLink=$("#create-admin-link");
+ if (adminExists == false) {
+ createAdminLink.show();
+ $("#login-link").hide();
+ $("#register-link").hide();
+ } else {
+ createAdminLink.hide();
+ }
+ if(callbackFn){
+ callbackFn()
+ }
+ $.log("adminExists:"+adminExists);
+ }
+ });
+ };
+
+ // handle url with registration link
+ checkUrlParams=function(){
+ var validateMeId = $.urlParam('validateMe');
+ if (validateMeId) {
+ validateKey(validateMeId);
+ return;
+ }
+ var resetPassword= $.urlParam('resetPassword');
+ if (resetPassword){
+ resetPasswordForm(resetPassword);
+ return;
+ }
+
+ var matches = window.location.toString().match(/^[^#]*(#.+)$/);
+ var hash = matches ? matches[1] : '';
+ $.log("location:"+window.sammyArchivaApplication.getLocation()+",hash:"+hash);
+ // by default display welcome screen
+ if(!hash){
+ window.sammyArchivaApplication.setLocation("#welcome");
+ }
+
+ };
+
+ hasKarma=function(karmaName){
+ return $.inArray(karmaName,window.redbackModel.operatioNames)>=0;
+ };
+
+ startArchivaApplication=function(){
+
+ $.log("startArchivaApplication");
+ loadRedbackTemplate();
+ loadArchivaTemplate();
+ $('#topbar-menu-container').html($("#topbar_menu_tmpl" ).tmpl());
+ $('#sidebar-content').html($("#main_menu_tmpl").tmpl());
+
+ ko.bindingHandlers.redbackP = {
+ init: function(element, valueAccessor) {
+ $(element).attr("redback-permissions",valueAccessor);
+ }
+ };
+
+ ko.applyBindings(new MainMenuViewModel());
+
+ hideElementWithKarma();
+ checkSecurityLinks();
+ checkCreateAdminLink();
+ $('#footer-content').html($('#footer-tmpl').tmpl(window.archivaRuntimeInfo));
+
+ updateAppearanceToolBar();
+
+ window.sammyArchivaApplication.run();
+
+ };
+
+ drawQuickSearchAutocomplete=function(){
+
+ $( "#quick-search-autocomplete" ).autocomplete({
+ minLength: 3,
+ delay: 600,
+ source: function(request, response){
+ $.get("restServices/archivaServices/searchService/quickSearch?queryString="+encodeURIComponent(request.term),
+ function(data) {
+ var res = mapArtifacts(data);
+ var uniqId = [];
+ var uniqArtifactIds=[];
+ for (var i= 0;i<res.length;i++){
+ if ( $.inArray(res[i].artifactId,uniqId)<0){
+ uniqId.push(res[i].artifactId);
+ uniqArtifactIds.push(res[i]);
+ }
+ }
+ response(uniqArtifactIds);
+ }
+ );
+ },
+ select: function( event, ui ) {
+ $.log("select artifactId:"+ui.item.artifactId);
+ window.sammyArchivaApplication.setLocation("#quicksearch~"+ui.item.artifactId);
+ }
+ }).data( "autocomplete" )._renderItem = function( ul, item ) {
+ return $( "<li></li>" )
+ .data( "item.autocomplete", item )
+ .append( "<a>" + item.artifactId + "</a>" )
+ .appendTo( ul );
+ };
+
+ }
+
+
+});
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/network-proxies.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/network-proxies.js
new file mode 100644
index 000000000..13a5a8cd8
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/network-proxies.js
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.network-proxies",["jquery","i18n","jquery.tmpl","bootstrap","jquery.validate","knockout"
+ ,"knockout.simpleGrid"], function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
+
+
+ NetworkProxy=function(id,protocol,host,port,username,password,useNtlm){
+ var self=this;
+ //private String id;
+ this.id = ko.observable(id);
+ this.id.subscribe(function(newValue){self.modified(true)});
+
+ //private String protocol = "http";
+ this.protocol=ko.observable(protocol);
+ this.protocol.subscribe(function(newValue){self.modified(true)});
+
+ //private String host;
+ this.host=ko.observable(host);
+ this.host.subscribe(function(newValue){self.modified(true)});
+
+ //private int port = 8080;
+ this.port=ko.observable(port);
+ this.port.subscribe(function(newValue){self.modified(true)});
+
+ //private String username;
+ this.username=ko.observable(username?username:"");
+ this.username.subscribe(function(newValue){self.modified(true)});
+
+ //private String password;
+ this.password=ko.observable(password?password:"");
+ this.password.subscribe(function(newValue){self.modified(true)});
+
+ //use NTLM proxy
+ this.useNtlm=ko.observable(useNtlm?useNtlm:false);
+ this.useNtlm.subscribe(function(newValue){self.modified(true)});
+
+ this.modified=ko.observable(false);
+ }
+
+ NetworkProxyViewModel=function(networkProxy, update, networkProxiesViewModel,bulkMode){
+ this.update=update;
+ this.networkProxy=networkProxy;
+ this.networkProxiesViewModel=networkProxiesViewModel;
+ var self=this;
+ this.bulkMode=false || bulkMode;
+
+ this.save=function(){
+ if (!$("#main-content" ).find("#network-proxy-edit-form").valid()){
+ return;
+ }
+ if (!this.bulkMode){
+ clearUserMessages();
+ }
+ if (update){
+ $.ajax("restServices/archivaServices/networkProxyService/updateNetworkProxy",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(networkProxy),
+ dataType: 'json',
+ success: function(data) {
+ $.log("update proxy id:"+self.networkProxy.id());
+ var message=$.i18n.prop('networkproxy.updated',self.networkProxy.id());
+ displaySuccessMessage(message);
+ self.networkProxy.modified(false);
+ if (!this.bulkMode){
+ activateNetworkProxiesGridTab();
+ }
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+ } else {
+
+ $.ajax("restServices/archivaServices/networkProxyService/addNetworkProxy",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(networkProxy),
+ dataType: 'json',
+ success: function(data) {
+ self.networkProxy.modified(false);
+ self.networkProxiesViewModel.networkProxies.push(self.networkProxy);
+ displaySuccessMessage($.i18n.prop('networkproxy.added',self.networkProxy.id()));
+ activateNetworkProxiesGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+
+ }
+ }
+
+ displayGrid=function(){
+ activateNetworkProxiesGridTab();
+ }
+ }
+
+ NetworkProxiesViewModel=function(){
+ this.networkProxies=ko.observableArray([]);
+
+ var self=this;
+
+ this.gridViewModel = null;
+
+ editNetworkProxy=function(networkProxy){
+ clearUserMessages();
+ $.log("editNetworkProxy");
+ var mainContent = $("#main-content");
+ mainContent.find("#network-proxies-view-tabs-li-edit a").html($.i18n.prop("edit"));
+ var viewModel = new NetworkProxyViewModel(networkProxy,true,self);
+ ko.applyBindings(viewModel,mainContent.find("#network-proxies-edit").get(0));
+ activateNetworkProxyFormValidation();
+ activateNetworkProxyEditTab();
+ mainContent.find("#network-proxy-btn-save").attr("disabled","true");
+ mainContent.find("#network-proxy-btn-save").button('toggle');
+ }
+
+ this.bulkSave=function(){
+ return getModifiedNetworkProxies().length>0;
+ }
+
+ getModifiedNetworkProxies=function(){
+ var prx = $.grep(self.networkProxies(),
+ function (networkProxy,i) {
+ return networkProxy.modified();
+ });
+ return prx;
+ }
+
+
+ updateModifiedNetworkProxies=function(){
+ var modifiedNetworkProxies = getModifiedNetworkProxies();
+
+ openDialogConfirm(function(){
+ for(var i=0;i<modifiedNetworkProxies.length;i++){
+ var viewModel = new NetworkProxyViewModel(modifiedNetworkProxies[i],true,self,false);
+ viewModel.save();
+ }
+ closeDialogConfirm();
+ },
+ $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('networkproxy.bulk.save.confirm.title'),
+ $.i18n.prop('networkproxy.bulk.save.confirm',modifiedNetworkProxies.length));
+
+
+ }
+
+ updateNetworkProxy=function(networkProxy){
+ var viewModel = new NetworkProxyViewModel(networkProxy,true,self,false);
+ viewModel.save();
+ }
+
+ removeNetworkProxy=function(networkProxy){
+ openDialogConfirm(
+ function(){
+ $.ajax("restServices/archivaServices/networkProxyService/deleteNetworkProxy/"+encodeURIComponent(networkProxy.id()),
+ {
+ type: "get",
+ success: function(data) {
+ self.networkProxies.remove(networkProxy);
+ clearUserMessages();
+ displaySuccessMessage($.i18n.prop('networkproxy.deleted',networkProxy.id()));
+ activateNetworkProxiesGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ closeDialogConfirm();
+ }
+ }
+ )}, $.i18n.prop('ok'), $.i18n.prop('cancel'), $.i18n.prop('networkproxy.delete.confirm',networkProxy.id()),
+ $("#network-proxy-delete-warning-tmpl" ).tmpl(networkProxy));
+ }
+ }
+
+
+ displayNetworkProxies=function(){
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+
+
+ loadNetworkProxies( function(data) {
+ var networkProxiesViewModel = new NetworkProxiesViewModel();
+ mainContent.html($("#networkProxiesMain").tmpl());
+ mainContent.find("#network-proxies-view-tabs a:first").tab('show');
+
+ mainContent.find("#network-proxies-view-tabs").on('show', function (e) {
+ if ($(e.target).attr("href")=="#network-proxies-edit") {
+ var viewModel = new NetworkProxyViewModel(new NetworkProxy(),false,networkProxiesViewModel);
+ ko.applyBindings(viewModel,$("#main-content" ).find("#network-proxies-edit").get(0));
+ activateNetworkProxyFormValidation();
+ clearUserMessages();
+ }
+ if ($(e.target).attr("href")=="#network-proxies-view") {
+ $("#main-content" ).find("#network-proxies-view-tabs-li-edit a").html($.i18n.prop("add"));
+ clearUserMessages();
+ }
+
+ });
+ networkProxiesViewModel.networkProxies(mapNetworkProxies(data));
+ networkProxiesViewModel.gridViewModel = new ko.simpleGrid.viewModel({
+ data: networkProxiesViewModel.networkProxies,
+ columns: [
+ {
+ headerText: $.i18n.prop('identifier'),
+ rowText: "id"
+ },
+ {
+ headerText: $.i18n.prop('protocol'),
+ rowText: "protocol"
+ },
+ {
+ headerText: $.i18n.prop('host'),
+ rowText: "host"
+ },
+ {
+ headerText: $.i18n.prop('port'),
+ rowText: "port"
+ },
+ {
+ headerText: $.i18n.prop('username'),
+ rowText: "username"
+ }
+ ],
+ pageSize: 5,
+ gridUpdateCallBack: function(networkProxy){
+ $("#main-content" ).find("#networkProxiesTable [title]").tooltip();
+ }
+ });
+ ko.applyBindings(networkProxiesViewModel,$("#main-content" ).find("#network-proxies-view").get(0));
+ }
+ )
+ }
+
+ loadNetworkProxies=function(successCallbackFn, errorCallbackFn){
+ $.ajax("restServices/archivaServices/networkProxyService/getNetworkProxies", {
+ type: "GET",
+ dataType: 'json',
+ success: successCallbackFn,
+ error: errorCallbackFn
+ });
+ }
+
+ activateNetworkProxyFormValidation=function(){
+ var editForm=$("#main-content" ).find("#network-proxy-edit-form");
+ var validator = editForm.validate({
+ rules: {id: {
+ required: true,
+ remote: {
+ url: "restServices/archivaUiServices/dataValidatorService/networkProxyIdNotExists",
+ type: "get"
+ }
+ }},
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError(editForm,validator,errorMap,errorMap);
+ }
+ });
+ validator.settings.messages["id"]=$.i18n.prop("id.required.or.alreadyexists");
+ }
+
+ activateNetworkProxiesGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#network-proxies-view-tabs-li-edit").removeClass("active");
+ mainContent.find("#network-proxies-edit").removeClass("active");
+
+ mainContent.find("#network-proxies-view-tabs-li-grid").addClass("active");
+ mainContent.find("#network-proxies-view").addClass("active");
+ mainContent.find("#network-proxies-view-tabs-li-edit a").html($.i18n.prop("add"));
+
+ }
+
+ activateNetworkProxyEditTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#network-proxies-view-tabs-li-grid").removeClass("active");
+ mainContent.find("#network-proxies-view").removeClass("active");
+
+ mainContent.find("#network-proxies-view-tabs-li-edit").addClass("active");
+ mainContent.find("#network-proxies-edit").addClass("active");
+ }
+
+ mapNetworkProxy=function(data){
+ if (data==null){
+ return null;
+ }
+ return new NetworkProxy(data.id,data.protocol,data.host,data.port,data.username,data.password,data.useNtlm);
+ }
+
+ mapNetworkProxies=function(data){
+ var mappedNetworkProxies = $.map(data, function(item) {
+ return mapNetworkProxy(item);
+ });
+ return mappedNetworkProxies;
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors-rules.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors-rules.js
new file mode 100644
index 000000000..e8b9ca74f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors-rules.js
@@ -0,0 +1,376 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.proxy-connectors-rules",["jquery","i18n","jquery.tmpl","bootstrap","jquery.ui","knockout"
+ ,"knockout.simpleGrid","knockout.sortable","archiva.proxy-connectors"],
+ function(jquery,i18n,jqueryTmpl,bootstrap,jqueryUi,ko) {
+
+ ProxyConnectorRulesViewModel=function(proxyConnectorRules,proxyConnectors){
+ var self=this;
+ self.proxyConnectorRules=ko.observableArray(proxyConnectorRules?proxyConnectorRules:[]);
+ self.proxyConnectors=ko.observableArray(proxyConnectors);
+ self.proxyConnectors.id="select";
+
+ // FIXME get that from a REST service
+ // FIXME i18n
+ this.ruleTypes=[new RuleType("BLACK_LIST","Black list","images/red-22-22.png"),new RuleType("WHITE_LIST","White list","images/green-22-22.png")];
+
+ this.findRuleType=function(proxyConnectorRule){
+ var ruleType;
+ $.each(self.ruleTypes, function(index, value) {
+ if(value.type==proxyConnectorRule.proxyConnectorRuleType()){
+ ruleType=value;
+ }
+ });
+ return ruleType;
+ }
+
+ this.findProxyConnector=function(sourceRepoId,targetRepoId){
+ for(var i=0;i<self.proxyConnectors().length;i++){
+ var proxyConnector=self.proxyConnectors()[i];
+ if(proxyConnector.sourceRepoId()==sourceRepoId && proxyConnector.targetRepoId()==targetRepoId){
+ return proxyConnector;
+ }
+ }
+ }
+
+ this.displayGrid=function(){
+ var mainContent = $("#main-content");
+
+ $.each(self.proxyConnectorRules(), function(index, value) {
+ value.ruleType=self.findRuleType(value);
+ });
+
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.proxyConnectorRules,
+ pageSize: 5,
+ gridUpdateCallBack: function(){
+ //$("#main-content" ).find("#proxy-connectors-rules-view-tabsTable" ).find("[title]").tooltip();
+ }
+ });
+
+ ko.applyBindings(self,mainContent.find("#proxy-connector-rules-view").get(0));
+
+ removeSmallSpinnerImg(mainContent);
+
+ mainContent.find("#proxy-connectors-rules-view-tabs").on('show', function (e) {
+ $.log("on show:"+$(e.target).attr("href"));
+ if ($(e.target).attr("href")=="#proxy-connector-rules-edit") {
+ var proxyConnectorRuleViewModel = new ProxyConnectorRuleViewModel(new ProxyConnectorRule(),self,false);
+ ko.applyBindings(proxyConnectorRuleViewModel,mainContent.find("#proxy-connector-rules-edit" ).get(0));
+ activateProxyConnectorRulesEditTab();
+ }
+ });
+ }
+ addProxyConnectorRule=function(proxyConnectorRule){
+ $("#proxy-connector-rule-add-btn" ).button("loading");
+ $.log("addProxyConnectorRule");
+ self.saveProxyConnectorRule(proxyConnectorRule,"restServices/archivaServices/proxyConnectorRuleService/proxyConnectorRule",true,
+ function(){
+ $("#proxy-connector-rule-add-btn" ).button("reset");
+ });
+ }
+
+ this.saveProxyConnectorRule=function(proxyConnectorRule,url,add,completeFnCallback){
+ $.log("saveProxyConnectorRule:"+url);
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $.ajax(url,
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(proxyConnectorRule),
+ dataType: 'json',
+ success: function(data) {
+ $.log("save proxyConnectorRule pattern:"+proxyConnectorRule.pattern());
+ var message=$.i18n.prop(add?'proxy-connector-rule.added':'proxy-connector-rule.updated',proxyConnectorRule.pattern());
+ displaySuccessMessage(message);
+ proxyConnectorRule.modified(false);
+ if(add){
+ // add rule type for image
+ proxyConnectorRule.ruleType=self.findRuleType(proxyConnectorRule);
+ self.proxyConnectorRules.push(proxyConnectorRule);
+ }
+ activateProxyConnectorRulesGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ removeMediumSpinnerImg(userMessages);
+ if(completeFnCallback){
+ completeFnCallback();
+ }
+ }
+ }
+ );
+ }
+
+ updateProxyConnectorRule=function(proxyConnectorRule){
+ $.log("updateProxyConnectorRule");
+ $("#main-content" ).find("#proxy-connectors-rules-edit-div").find("#proxy-connector-rule-update-btn").button("loading");
+ self.saveProxyConnectorRule(proxyConnectorRule,"restServices/archivaServices/proxyConnectorRuleService/updateProxyConnectorRule",
+ false,
+ function(){
+ $("#proxy-connector-rule-update-btn" ).button("reset");
+ }
+ );
+ }
+
+ this.deleteProxyConnectorRule=function(proxyConnectorRule){
+ $("#main-content" ).find("proxy-connectors-rules-view-tabsTable").find(".btn").button("loading");
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $.ajax("restServices/archivaServices/proxyConnectorRuleService/deleteProxyConnectorRule",
+ {
+ type:"POST",
+ contentType: 'application/json',
+ data: ko.toJSON(proxyConnectorRule),
+ dataType: 'json',
+ success:function(data){
+ var message=$.i18n.prop('proxy-connector-rule.deleted',proxyConnectorRule.pattern());
+ self.proxyConnectorRules.remove(proxyConnectorRule);
+ displaySuccessMessage(message);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ removeMediumSpinnerImg(userMessages);
+ $("#main-content" ).find("proxy-connectors-rules-view-tabsTable").find(".btn").button("reset");
+ }
+ }
+ );
+ }
+
+ removeProxyConnectorRule=function(proxyConnectorRule){
+
+ openDialogConfirm(
+ function(){self.deleteProxyConnectorRule(proxyConnectorRule);window.modalConfirmDialog.modal('hide')},
+ $.i18n.prop('ok'), $.i18n.prop('cancel'),
+ $.i18n.prop('proxy-connector-rule.delete.confirm',proxyConnectorRule.pattern()),"");
+
+ }
+
+ editProxyConnectorRule=function(proxyConnectorRule){
+ var proxyConnectorRuleViewModel=new ProxyConnectorRuleViewModel(proxyConnectorRule,self,true);
+ ko.applyBindings(proxyConnectorRuleViewModel,$("#main-content").find("#proxy-connector-rules-edit" ).get(0));
+ activateProxyConnectorRulesEditTab();
+ proxyConnectorRuleViewModel.activateRemoveChoosen(self);
+ proxyConnectorRuleViewModel.activateRemoveAvailable(self);
+ }
+
+ remove=function(){
+ $.log("remove");
+ }
+
+ }
+
+ ProxyConnectorRuleViewModel=function(proxyConnectorRule,proxyConnectorRulesViewModel,update){
+ var self=this;
+ this.proxyConnectorRule=proxyConnectorRule;
+ this.proxyConnectorRulesViewModel=proxyConnectorRulesViewModel;
+ this.availableProxyConnectors=ko.observableArray([]);
+ this.availableProxyConnectors.id="availableProxyConnectors";
+ this.update=update;
+
+ $.each(this.proxyConnectorRulesViewModel.proxyConnectors(), function(idx, value) {
+ //$.log(idx + ': ' + value.sourceRepoId() +":"+value.targetRepoId());
+ var available=true;
+ // is it in proxyConnectorRule.proxyConnectors
+ $.each(self.proxyConnectorRule.proxyConnectors(),function(index,proxyConnector){
+ if(value.sourceRepoId()==proxyConnector.sourceRepoId() && value.targetRepoId()==proxyConnector.targetRepoId()){
+ available=false;
+ }
+ });
+ if(available==true){
+ self.availableProxyConnectors.push(value);
+ }
+ });
+
+ proxyConnectorMoved=function(arg){
+ $.log("repositoryMoved:"+arg.sourceIndex+" to " + arg.targetIndex);
+ self.proxyConnectorRule.modified(true);
+ self.activateRemoveChoosen(self.proxyConnectorRulesViewModel);
+ self.activateRemoveAvailable(self.proxyConnectorRulesViewModel);
+ }
+
+ saveProxyConnectorRule=function(){
+ self.proxyConnectorRulesViewModel.saveProxyConnectorRule(self.proxyConnectorRule)
+ }
+
+ this.removeChoosen=function(proxyConnectorRulesViewModel,sourceRepoId,targetRepoId){
+ $.log("removeChoosen:"+sourceRepoId+":"+targetRepoId);
+
+ $.log("size before:"+self.proxyConnectorRule.proxyConnectors().length);
+ var proxyConnectorToRemove=null;
+ for(var i=0;i<self.proxyConnectorRule.proxyConnectors().length;i++){
+ if(self.proxyConnectorRule.proxyConnectors()[i].sourceRepoId()==sourceRepoId &&
+ self.proxyConnectorRule.proxyConnectors()[i].targetRepoId()==targetRepoId){
+ proxyConnectorToRemove=self.proxyConnectorRule.proxyConnectors()[i];
+ }
+ }
+ self.proxyConnectorRule.proxyConnectors.remove(proxyConnectorToRemove);
+ self.availableProxyConnectors.push(proxyConnectorToRemove);
+ $.log("size after:"+self.proxyConnectorRule.proxyConnectors().length);
+ var mainContent=$("#main-content");
+ mainContent.find("#proxy-connectors-rules-available-proxy-connectors" ).find("[data-source-repoId="+sourceRepoId+"][data-target-repoId="+targetRepoId+"]" ).on("click", function(){
+ self.removeAvailable(proxyConnectorRulesViewModel,$(this).attr("data-source-repoId"),$(this).attr("data-target-repoId"));
+ });
+ mainContent.find("#proxy-connectors-rules-edit-order-div" ).find("[data-source-repoId="+sourceRepoId+"][data-target-repoId="+targetRepoId+"]" ).off("click");
+ }
+
+ this.activateRemoveChoosen=function(proxyConnectorRulesViewModel){
+ $("#main-content" ).find("#proxy-connectors-rules-edit-order-div" ).find(".icon-minus-sign" ).on("click", function(){
+ self.removeChoosen(proxyConnectorRulesViewModel,$(this).attr("data-source-repoId"),$(this).attr("data-target-repoId"));
+ });
+ }
+
+ this.removeAvailable=function(proxyConnectorRulesViewModel,sourceRepoId,targetRepoId){
+ $.log("removeAvailable:"+sourceRepoId+":"+targetRepoId);
+
+ $.log("size before:"+self.availableProxyConnectors().length);
+ var proxyConnectorToAdd=null;
+ for(var i=0;i<self.availableProxyConnectors().length;i++){
+ if(self.availableProxyConnectors()[i].sourceRepoId()==sourceRepoId &&
+ self.availableProxyConnectors()[i].targetRepoId()==targetRepoId){
+ $.log("found");
+ proxyConnectorToAdd=self.availableProxyConnectors()[i];
+ }
+ }
+ self.proxyConnectorRule.proxyConnectors.push(proxyConnectorToAdd);
+ self.availableProxyConnectors.remove(proxyConnectorToAdd);
+ $.log("size after:"+self.availableProxyConnectors().length);
+ var mainContent=$("#main-content");
+ mainContent.find("#proxy-connectors-rules-edit-order-div" ).find("[data-source-repoId="+sourceRepoId+"][data-target-repoId="+targetRepoId+"]" ).on("click", function(){
+ self.removeChoosen(proxyConnectorRulesViewModel,$(this).attr("data-source-repoId"),$(this).attr("data-target-repoId"));
+ });
+ mainContent.find("#proxy-connectors-rules-available-proxy-connectors" ).find("[data-source-repoId="+sourceRepoId+"][data-target-repoId="+targetRepoId+"]" ).off("click");
+ }
+
+ this.activateRemoveAvailable=function(proxyConnectorRulesViewModel){
+ $("#main-content" ).find("#proxy-connectors-rules-available-proxy-connectors" ).find(".icon-plus-sign" ).on("click", function(){
+ self.removeAvailable(proxyConnectorRulesViewModel,$(this).attr("data-source-repoId"),$(this).attr("data-target-repoId"));
+ });
+ }
+
+ }
+
+
+ displayProxyConnectorsRules=function(){
+ $.log("displayProxyConnectorsRules");
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html($("#proxyConnectorsRulesMain").tmpl());
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ loadAllProxyConnectors(function(data){
+ var proxyConnectors = mapProxyConnectors(data);
+
+ $.ajax("restServices/archivaServices/proxyConnectorRuleService/proxyConnectorRules", {
+ type: "GET",
+ dataType: 'json',
+ success: function (data){
+ var proxyConnectorRules=mapProxyConnectorRules(data);
+ var proxyConnectorRulesViewModel = new ProxyConnectorRulesViewModel(proxyConnectorRules,proxyConnectors);
+ proxyConnectorRulesViewModel.displayGrid();
+ activateProxyConnectorRulesGridTab();
+ },
+ complete: function(data){
+ removeMediumSpinnerImg(userMessages);
+ }
+
+ });
+
+ });
+ }
+
+ ProxyConnectorRule=function(pattern,proxyConnectorRuleType,proxyConnectors){
+ //private String pattern;
+ var self=this;
+
+ this.modified=ko.observable(false);
+
+ //private String sourceRepoId;
+ this.pattern=ko.observable(pattern);
+ this.pattern.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ this.ruleType=null;
+
+ //private ProxyConnectorRuleType proxyConnectorRuleType;
+ this.proxyConnectorRuleType=ko.observable(proxyConnectorRuleType);
+ this.proxyConnectorRuleType.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private List<ProxyConnector> proxyConnectors;
+ this.proxyConnectors=ko.observableArray(proxyConnectors?proxyConnectors:[]);
+ this.proxyConnectors.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ this.ruleType=null;
+ }
+
+ mapProxyConnectorRule=function(data){
+ if (data==null){
+ return null;
+ }
+ return new ProxyConnectorRule(data.pattern, data.proxyConnectorRuleType, mapProxyConnectors(data.proxyConnectors));
+ }
+
+ mapProxyConnectorRules=function(data){
+ var mappedProxyConnectorRules = $.map(data, function(item) {
+ return mapProxyConnectorRule(item);
+ });
+ return mappedProxyConnectorRules;
+ }
+
+
+ activateProxyConnectorRulesGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#proxy-connectors-rules-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#proxy-connectors-rules-view-tabs li").removeClass("active");
+
+ mainContent.find("#proxy-connector-rules-view").addClass("active");
+ mainContent.find("#proxy-connectors-rules-view-tabs-li-grid").addClass("active");
+ mainContent.find("#proxy-connectors-rules-view-tabs-a-edit").html($.i18n.prop("add"));
+
+ }
+
+ activateProxyConnectorRulesEditTab=function(){
+ var mainContent = $("#main-content");
+
+ mainContent.find("#proxy-connectors-rules-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#proxy-connectors-rules-view-tabs > li").removeClass("active");
+
+ mainContent.find("#proxy-connector-rules-edit").addClass("active");
+ mainContent.find("#proxy-connectors-rules-view-tabs-edit").addClass("active");
+ }
+
+ RuleType=function(type,label,image){
+ this.type=type;
+ this.label=label;
+ this.image=image;
+ }
+
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors.js
new file mode 100644
index 000000000..ec6787606
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/proxy-connectors.js
@@ -0,0 +1,673 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.proxy-connectors",["jquery","i18n","jquery.tmpl","bootstrap","jquery.validate","knockout"
+ ,"knockout.simpleGrid","knockout.sortable","select2"],
+ function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
+
+ ProxyConnector=function(sourceRepoId,targetRepoId,proxyId,blackListPatterns,whiteListPatterns,policiesEntries,propertiesEntries,
+ disabled,order){
+ var self=this;
+
+ this.modified=ko.observable(false);
+
+ //private String sourceRepoId;
+ this.sourceRepoId=ko.observable(sourceRepoId);
+ this.sourceRepoId.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private String targetRepoId;
+ this.targetRepoId=ko.observable(targetRepoId);
+ this.targetRepoId.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ this.previousProxyId=proxyId;
+
+ //private String proxyId;
+ this.proxyId=ko.observable(proxyId);
+ this.proxyId.subscribe(function(newValue){
+ if(newValue!=self.previousProxyId){
+ $.log("proxyId modified:"+newValue+",previous:"+self.previousProxyId);
+ self.previousProxyId=newValue;
+ self.modified(true);
+ }
+ });
+
+ //private List<String> blackListPatterns;
+ this.blackListPatterns=ko.observableArray(blackListPatterns==null?[]:blackListPatterns);
+ this.blackListPatterns.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private List<String> whiteListPatterns;
+ this.whiteListPatterns=ko.observableArray(whiteListPatterns==null?[]:whiteListPatterns);
+ this.whiteListPatterns.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private List<PropertyEntry> policiesEntries;
+ this.policiesEntries=ko.observableArray(policiesEntries==null?new Array():policiesEntries);
+ this.policiesEntries.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private List<PropertyEntry> properties;
+ this.propertiesEntries=ko.observableArray(propertiesEntries==null?new Array():propertiesEntries);
+ this.propertiesEntries.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private boolean disabled = false;
+ this.disabled=ko.observable(disabled);
+ this.disabled.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ //private int order = 0;
+ this.order=ko.observable(order?order:0);
+ this.order.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+
+
+ this.updatePolicyEntry=function(key,value){
+ $.log("updatePolicyEntry:"+key+":"+value);
+ var found=false;
+ for(var i=0;i<self.policiesEntries().length;i++){
+ if (self.policiesEntries()[i].key==key){
+ self.policiesEntries()[i].value=value;
+ found=true;
+ self.modified(true);
+ }
+ }
+ if(!found){
+ self.policiesEntries().push(new Entry(key,value));
+ }
+ }
+
+ }
+
+ PolicyInformation=function(options,defaultOption,id,name){
+
+ var self=this;
+ this.modified=ko.observable(false);
+
+ //private List<String> options;
+ this.options=ko.observableArray(options);
+ this.options.subscribe(function(newValue){self.modified(true)});
+
+ //private String defaultOption;
+ this.defaultOption=ko.observable(defaultOption);
+ this.defaultOption.subscribe(function(newValue){self.modified(true)});
+
+ //private String id;
+ this.id=ko.observable(id);
+ this.id.subscribe(function(newValue){self.modified(true)});
+
+ //private String name;
+ this.name=ko.observable(name);
+ this.name.subscribe(function(newValue){self.modified(true)});
+
+ }
+
+ ProxyConnectorViewModel=function(proxyConnector,update,proxyConnectorsViewModel){
+ var self=this;
+ this.proxyConnector=proxyConnector;
+ this.proxyConnectorsViewModel=proxyConnectorsViewModel;
+ this.update=update;
+ this.modified=ko.observable(false);
+
+ isUpdate=function(){
+ return self.update;
+ }
+
+ getSelectedPolicyOption=function(id){
+ var policiesEntries=self.proxyConnector.policiesEntries();
+ if (policiesEntries!=null){
+ for (i=0;i<policiesEntries.length;i++){
+ var curKey = $.isFunction(policiesEntries[i].key)? policiesEntries[i].key():policiesEntries[i].key;
+ if (id==curKey){
+ return $.isFunction(policiesEntries[i].value)? policiesEntries[i].value():policiesEntries[i].value;
+ }
+ }
+ }
+ return "";
+ }
+
+ changePolicyOption=function(id){
+ var selectedOption=$("#main-content").find("#policy-"+id ).find("option:selected");
+ if (selectedOption.length>0){
+ var value = selectedOption.val();
+ $.log("changePolicyOption:"+id+":"+value);
+ self.proxyConnector.updatePolicyEntry(id,value);
+
+ }
+ }
+
+
+ getPolicyOptions=function(id){
+ var policyInformations=self.proxyConnectorsViewModel.policyInformations();
+ for(var i=0;i<policyInformations.length;i++){
+ if (policyInformations[i].id()==id){
+ return policyInformations[i].options();
+ }
+ }
+ }
+
+
+
+ addBlacklistPattern=function(){
+ var pattern = $("#main-content").find("#blacklist-value").val();
+ var tab = self.proxyConnector.blackListPatterns();
+ tab.push(pattern);
+ self.proxyConnector.blackListPatterns(tab);
+ self.proxyConnector.modified(true);
+ }
+
+ removeBlacklistPattern=function(pattern){
+ self.proxyConnector.blackListPatterns.remove(pattern);
+ self.proxyConnector.modified(true);
+ }
+
+ addWhitelistPattern=function(){
+ var pattern = $("#main-content" ).find("#whitelist-value").val();
+ var tab = self.proxyConnector.whiteListPatterns();
+ tab.push(pattern);
+ self.proxyConnector.whiteListPatterns(tab);
+ self.proxyConnector.modified(true);
+
+ }
+
+ removeWhitelistPattern=function(pattern){
+ self.proxyConnector.whiteListPatterns.remove(pattern);
+ self.proxyConnector.modified(true);
+ }
+
+ this.save=function(){
+ //FIXME data controls !!!
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $("#proxy-connector-btn-save" ).button("loading");
+ // update is delete then add
+ if (this.update){
+ $.ajax("restServices/archivaServices/proxyConnectorService/updateProxyConnector",
+ {
+ type: "POST",
+ data: ko.toJSON(self.proxyConnector),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop('proxyconnector.updated'));
+ activateProxyConnectorsGridTab();
+ self.proxyConnector.modified(false);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ $("#proxy-connector-btn-save" ).button("reset");
+ }
+ }
+ );
+ } else {
+
+ $.ajax("restServices/archivaServices/proxyConnectorService/addProxyConnector",
+ {
+ type: "POST",
+ data: ko.toJSON(self.proxyConnector),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop('proxyconnector.added'));
+ activateProxyConnectorsGridTab();
+ self.proxyConnector.modified(false);
+ self.proxyConnectorsViewModel.proxyConnectors.push(self.proxyConnector);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ $("#proxy-connector-btn-save" ).button("reset");
+ }
+ }
+ );
+ }
+ }
+
+ this.deleteProperty=function(key){
+ for(var i=0;i<self.proxyConnector.propertiesEntries().length;i++){
+ var entry=self.proxyConnector.propertiesEntries()[i];
+ if (entry.key()==key()){
+ self.proxyConnector.propertiesEntries.remove(entry);
+ self.proxyConnector.modified(true);
+ }
+ }
+
+ }
+
+ this.addProperty=function(){
+ var mainContent=$("#main-content");
+ var key=mainContent.find("#property-key").val();
+ var value=mainContent.find("#property-value").val();
+ var oldTab = self.proxyConnector.propertiesEntries();
+ oldTab.push(new Entry(key,value));
+ self.proxyConnector.propertiesEntries(oldTab);
+ mainContent.find("#property-key").val("");
+ mainContent.find("#property-value").val("");
+ self.proxyConnector.modified(true);
+ }
+
+ displayGrid=function(){
+ activateProxyConnectorsGridTab();
+ }
+ }
+
+ ProxyConnectorsViewModel=function(){
+ var self=this;
+ this.proxyConnectors=ko.observableArray([]);
+ this.proxyConnectors.subscribe(function(newValue){
+ $.log("ProxyConnectorsViewModel#proxyConnectors modified");
+ self.proxyConnectors().sort(function(a,b){
+ if ( a.sourceRepoId()== b.sourceRepoId()) return a.order() - b.order();
+ return (a.sourceRepoId() > b.sourceRepoId())? -1:1;
+ });
+ });
+ this.policyInformations=ko.observableArray([]);
+ this.managedRepositories=ko.observableArray([]);
+ this.remoteRepositories=ko.observableArray([]);
+ this.networkProxies=ko.observableArray([]);
+
+ this.bulkSave=function(){
+ return getModifiedProxyConnectors().length>0;
+ }
+
+ getModifiedProxyConnectors=function(){
+ var prx = $.grep(self.proxyConnectors(),
+ function (proxyConnector,i) {
+ return proxyConnector.modified();
+ });
+ return prx;
+ }
+
+ this.updateModifiedProxyConnectors=function(){
+ var modifiedProxyConnectors = getModifiedProxyConnectors();
+
+ openDialogConfirm(function(){
+ for(var i=0;i<modifiedProxyConnectors.length;i++){
+ var viewModel = new ProxyConnectorViewModel(modifiedProxyConnectors[i],true,self,false);
+ viewModel.save();
+ }
+ closeDialogConfirm();
+ },
+ $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('proxy-connectors.bulk.save.confirm.title'),
+ $.i18n.prop('proxy.connector.bulk.save.confirm',modifiedProxyConnectors.length));
+ }
+
+ updateProxyConnector=function(proxyConnector){
+ var viewModel = new ProxyConnectorViewModel(proxyConnector,true,self,false);
+ viewModel.save();
+ }
+
+ editProxyConnector=function(proxyConnector){
+ var proxyConnectorViewModel=new ProxyConnectorViewModel(proxyConnector,true,self);
+ var mainContent = $("#main-content");
+ mainContent.find("#proxy-connectors-edit").html($("#proxy-connector-edit-form-tmpl").tmpl());
+ ko.applyBindings(proxyConnectorViewModel,mainContent.find("#proxy-connectors-edit").get(0));
+ activateProxyConnectorsEditTab();
+ mainContent.find("#proxy-connectors-view-tabs-li-edit a").html($.i18n.prop("edit"));
+ }
+
+ deleteProxyConnector=function(proxyConnector){
+
+ openDialogConfirm(
+ function(){
+ clearUserMessages();
+ removeProxyConnector(proxyConnector,function(){
+ displaySuccessMessage($.i18n.prop('proxyconnector.removed'));
+ self.proxyConnectors.remove(proxyConnector);
+ closeDialogConfirm();
+ })}, $.i18n.prop('ok'), $.i18n.prop('cancel'), $.i18n.prop('proxyconnector.delete.confirm'),
+ $("#proxy-connector-delete-warning-tmpl").tmpl(proxyConnector));
+
+
+ }
+
+
+ getManagedRepository=function(id){
+ return findManagedRepository(id,self.managedRepositories());
+ }
+
+ getRemoteRepository=function(id){
+ var remoteRepository=$.grep(self.remoteRepositories(),
+ function(repo,idx){
+ return repo.id()==id;
+ }
+ );
+ return ($.isArray(remoteRepository) && remoteRepository.length>0) ? remoteRepository[0]:new RemoteRepository();
+ }
+
+ getProxyConnector=function(sourceRepoId,targetRepoId){
+ var proxyConnectors=$.grep(self.proxyConnectors(),
+ function(proxyConnector,idx){
+ return proxyConnector.sourceRepoId()==sourceRepoId
+ && proxyConnector.targetRepoId()==targetRepoId;
+ }
+ );
+ var res = ($.isArray(proxyConnectors) && proxyConnectors.length>0) ? proxyConnectors[0]:new ProxyConnector();
+ return res;
+ }
+ showSettings=function(){
+ $.log("showSettings");
+ $("#body_content" ).find(".popover" ).hide();
+ //$("#main-content").find("[id^='proxy-connectors-grid-remoterepo-settings-edit-']" ).popover("hide");
+ }
+ buildSettings=function(proxyConnector){
+ var tmplHtml = $("#proxy-connectors-remote-settings-popover-tmpl")
+ .tmpl({
+ proxyConnectorsViewModel: self,
+ proxyConnector:ko.toJS(proxyConnector)
+ } ).html();
+
+ var targetImg = $(("#proxy-connectors-grid-remoterepo-settings-edit-")
+ +proxyConnector.sourceRepoId().replace(/\./g,"\\\.")+"-"+proxyConnector.targetRepoId().replace(/\./g,"\\\."));
+ return tmplHtml;
+ }
+
+ this.displaySettings=function(sourceRepoId,targetRepoId,targetContentStartId, targetImgStartId){
+ var proxyConnector=getProxyConnector(sourceRepoId,targetRepoId);
+ showSettings(proxyConnector,targetContentStartId,targetImgStartId);
+ }
+
+ this.findPolicyInformationName=function(id){
+ for(var i=0;i<self.policyInformations().length;i++){
+ if (id==self.policyInformations()[i].id()){
+ return self.policyInformations()[i].name();
+ }
+ }
+ return null;
+ }
+
+ orderChangeAware=function(proxyConnector){
+ return findProxyConnectorsWithSourceId(proxyConnector).length>1;
+ }
+
+ findProxyConnectorsWithSourceId=function(proxyConnector){
+ return $.grep(self.proxyConnectors(),function(curProxyConnector,idx){
+ return curProxyConnector.sourceRepoId()==proxyConnector.sourceRepoId();
+ }
+ );
+ }
+
+ displayOrderEdit=function(proxyConnector){
+ var proxyConnectors=findProxyConnectorsWithSourceId(proxyConnector);
+ $.log("displayOrderEdit:"+proxyConnector.sourceRepoId()+",number:"+proxyConnectors.length);
+
+ var managedRepository = getManagedRepository(proxyConnector.sourceRepoId());
+ var proxyConnectorEditOrderViewModel=new ProxyConnectorEditOrderViewModel(proxyConnectors,self,managedRepository);
+ ko.applyBindings(proxyConnectorEditOrderViewModel,$("#main-content").find("#proxy-connector-edit-order").get(0));
+ activateProxyConnectorsEditOrderTab();
+ }
+
+ this.displayGrid=function(){
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.proxyConnectors,
+ pageSize: 5,
+ gridUpdateCallBack: function(){
+ $("#main-content" ).find("#proxyConnectorsTable" ).find("[title]").tooltip();
+ }
+ });
+ var mainContent = $("#main-content");
+
+ ko.applyBindings(this,mainContent.find("#proxy-connectors-view").get(0));
+ var prxGrids=mainContent.find("[id^='proxy-connectors-grid-remoterepo-settings-edit-']");
+ prxGrids.popover();
+ removeSmallSpinnerImg();
+ mainContent.find("#proxy-connectors-view-tabs #proxy-connectors-view-tabs-a-network-proxies-grid").tab('show');
+
+ mainContent.find("#proxy-connectors-view-tabs").on('show', function (e) {
+ $.log("on show:"+$(e.target).attr("href"));
+ if ($(e.target).attr("href")=="#proxy-connectors-edit") {
+ $.log("#proxy-connectors-edit");
+ var proxyConnector=new ProxyConnector();
+ var defaultPolicies=new Array();
+ // populate with defaut policies options
+ for (i=0;i<self.policyInformations().length;i++){
+ defaultPolicies.push(new Entry(self.policyInformations()[i].id(),self.policyInformations()[i].defaultOption));
+ }
+ proxyConnector.policiesEntries(defaultPolicies);
+ var proxyConnectorViewModel=new ProxyConnectorViewModel(proxyConnector,false,self);
+ mainContent.find("#proxy-connectors-edit").html($("#proxy-connector-edit-form-tmpl").tmpl());
+ ko.applyBindings(proxyConnectorViewModel,mainContent.find("#proxy-connectors-edit").get(0));
+ mainContent.find("#sourceRepoId" ).select2();
+ mainContent.find("#targetRepoId" ).select2();
+ }
+ if ($(e.target).attr("href")=="#proxy-connectors-view") {
+ $("#proxy-connectors-view-tabs-a-network-proxies-grid").html($.i18n.prop("proxy-connectors.grid.tab.title"));
+ mainContent.find("#proxy-connectors-view-tabs-li-edit a").html($.i18n.prop("add"));
+ }
+ if ($(e.target).attr("href")=="#proxy-connectors-edit-order") {
+ activateProxyConnectorsEditOrderTab();
+ }
+
+ });
+ }
+
+ }
+
+ ProxyConnectorEditOrderViewModel=function(proxyConnectors,proxyConnectorsViewModel,managedRepository){
+ var self=this;
+ this.proxyConnectors=ko.observableArray(proxyConnectors);
+ this.proxyConnectorsViewModel=proxyConnectorsViewModel;
+ this.managedRepository=managedRepository;
+ proxyConnectorMoved=function(arg){
+ $.log("proxyConnectorMoved:"+arg.sourceIndex+" to " + arg.targetIndex);
+ // if only 1 move just update two whereas update all with the new order
+ if (arg.targetIndex-arg.sourceIndex==1){
+ self.proxyConnectors()[arg.targetIndex].order(arg.targetIndex+1);
+ self.proxyConnectors()[arg.sourceIndex].order(arg.sourceIndex+1);
+ } else {
+ for (i=0;i<self.proxyConnectors().length;i++){
+ self.proxyConnectors()[i].order(i+1);
+ }
+ }
+ }
+
+ this.findRemoteRepository=function(id){
+ $.log("findRemoteRepository:"+id());
+ for(var i=0;i<self.proxyConnectorsViewModel.remoteRepositories().length;i++){
+ if (self.proxyConnectorsViewModel.remoteRepositories()[i].id()==id()){
+ return self.proxyConnectorsViewModel.remoteRepositories()[i];
+ }
+ }
+ return null;
+ }
+
+ this.updateModifiedProxyConnectors=function(){
+ self.proxyConnectorsViewModel.updateModifiedProxyConnectors();
+ }
+
+ displaySettings=function(sourceRepoId,targetRepoId){
+ $.log("ProxyConnectorEditOrderViewModel#showSettings:"+sourceRepoId+"-"+targetRepoId);
+ self.proxyConnectorsViewModel.displaySettings(sourceRepoId,targetRepoId,
+ "#proxy-connectors-order-remoterepo-settings-content-",
+ "#proxy-connectors-order-remoterepo-settings-edit-");
+ }
+
+ }
+
+ displayProxyConnectors=function(){
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html($("#proxyConnectorsMain").tmpl());
+ mainContent.append(smallSpinnerImg());
+
+ this.proxyConnectorsViewModel = new ProxyConnectorsViewModel();
+ var self=this;
+
+ loadManagedRepositories(function(data) {
+ self.proxyConnectorsViewModel.managedRepositories(mapManagedRepositories(data));
+
+ loadRemoteRepositories(function(data) {
+ self.proxyConnectorsViewModel.remoteRepositories(mapRemoteRepositories(data));
+
+ loadNetworkProxies(function(data) {
+ self.proxyConnectorsViewModel.networkProxies(mapNetworkProxies(data));
+
+ loadAllPolicies( function(data) {
+ self.proxyConnectorsViewModel.policyInformations(mapPolicyInformations(data));
+
+ loadAllProxyConnectors( function(data) {
+ self.proxyConnectorsViewModel.proxyConnectors(mapProxyConnectors(data));
+ self.proxyConnectorsViewModel.displayGrid();
+ });
+
+ });
+
+ });
+
+ });
+
+ });
+
+ }
+
+ loadAllPolicies=function(successCallBackFn,errorCallBackFn){
+ $.ajax("restServices/archivaServices/proxyConnectorService/allPolicies", {
+ type: "GET",
+ dataType: 'json',
+ success: successCallBackFn,
+ error: errorCallBackFn
+ }
+ );
+ }
+
+ loadAllProxyConnectors=function(successCallBackFn,errorCallBackFn){
+ $.ajax("restServices/archivaServices/proxyConnectorService/getProxyConnectors", {
+ type: "GET",
+ dataType: 'json',
+ success: successCallBackFn,
+ error: errorCallBackFn
+ });
+ }
+
+ activateProxyConnectorsGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#proxy-connectors-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#proxy-connectors-view-tabs li").removeClass("active");
+
+ mainContent.find("#proxy-connectors-view").addClass("active");
+ mainContent.find("#proxy-connectors-view-tabs-li-grid").addClass("active");
+ mainContent.find("#proxy-connectors-view-tabs-li-edit a").html($.i18n.prop("add"));
+
+ }
+
+ activateProxyConnectorsEditTab=function(){
+ var mainContent = $("#main-content");
+
+ mainContent.find("#proxy-connectors-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#proxy-connectors-view-tabs li").removeClass("active");
+
+ mainContent.find("#proxy-connectors-edit").addClass("active");
+ mainContent.find("#proxy-connectors-view-tabs-li-edit").addClass("active");
+ }
+
+ activateProxyConnectorsEditOrderTab=function(){
+ var mainContent = $("#main-content");
+
+ mainContent.find("#proxy-connectors-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#proxy-connectors-view-tabs li").removeClass("active");
+
+ mainContent.find("#proxy-connector-edit-order").addClass("active");
+ mainContent.find("#proxy-connectors-view-tabs-li-edit-order").addClass("active");
+ }
+
+ mapProxyConnector=function(data){
+ if (data==null){
+ return null;
+ }
+ var policiesEntries = data.policiesEntries == null ? []: $.each(data.policiesEntries,function(item){
+ return new Entry(item.key, item.value);
+ });
+ if (!$.isArray(policiesEntries)){
+ policiesEntries=[];
+ }
+ var propertiesEntries = data.propertiesEntries == null ? []: $.each(data.propertiesEntries,function(item){
+ return new Entry(item.key, item.value);
+ });
+ if (!$.isArray(propertiesEntries)){
+ propertiesEntries=[];
+ }
+ return new ProxyConnector(data.sourceRepoId,data.targetRepoId,data.proxyId,mapStringArray(data.blackListPatterns),
+ mapStringArray(data.whiteListPatterns),policiesEntries,propertiesEntries,
+ data.disabled,data.order);
+ }
+
+ mapProxyConnectors=function(data){
+ var mappedProxyConnectors = $.map(data, function(item) {
+ return mapProxyConnector(item);
+ });
+ return mappedProxyConnectors;
+ }
+
+ mapPolicyInformation=function(data){
+ if (data==null){
+ return null;
+ }
+ var policyInformation = new PolicyInformation(mapStringArray(data.options),data.defaultOption,data.id,data.name);
+ $.log("policyInformation.options:"+policyInformation.options());
+ return policyInformation;
+ }
+
+ mapPolicyInformations=function(data){
+ return $.map(data, function(item) {
+ return mapPolicyInformation(item);
+ });
+ }
+
+ removeProxyConnector=function(proxyConnector,fnSuccessCallback){
+ clearUserMessages();
+ var url="restServices/archivaServices/proxyConnectorService/removeProxyConnector?";
+ url += "sourceRepoId="+encodeURIComponent(proxyConnector.sourceRepoId());
+ url += "&targetRepoId="+encodeURIComponent(proxyConnector.targetRepoId());
+ $.ajax(url,
+ {
+ type: "GET",
+ contentType: 'application/json',
+ success: function(data) {
+ fnSuccessCallback();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+
+ }
+
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repositories.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repositories.js
new file mode 100644
index 000000000..498cc95e9
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repositories.js
@@ -0,0 +1,1304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.repositories",["jquery","i18n","jquery.tmpl","bootstrap","jquery.validate","knockout","knockout.simpleGrid"],
+function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
+
+ // FIXME this must be dynamic if we do a plugin mechanism with dynamic repositories types
+ // FIXME i18n
+
+ ManagedRepositoryType=function(type,label){
+ this.type=type;
+ this.label=label;
+ }
+
+ window.managedRepositoryTypes = [
+ new ManagedRepositoryType("default","Maven 2.x Repository"),
+ new ManagedRepositoryType("legacy", "Maven 1.x Repository")
+ ];
+
+ ManagedRepository=function(id,name,layout,indexDirectory,location,snapshots,releases,blockRedeployments,cronExpression,
+ scanned,daysOlder,retentionCount,deleteReleasedSnapshots,stageRepoNeeded,description,
+ skipPackedIndexCreation,feedsUrl,url){
+
+ var self=this;
+
+ //private String id;
+ this.id=ko.observable(id);
+ this.id.subscribe(function(newValue){self.modified(true)});
+
+ //private String name;
+ this.name=ko.observable(name);
+ this.name.subscribe(function(newValue){self.modified(true)});
+
+ //private String layout = "default";
+ this.layout=ko.observable(layout);
+ this.layout.subscribe(function(newValue){self.modified(true)});
+
+ //private String indexDirectory;
+ this.indexDirectory=ko.observable(indexDirectory);
+ this.indexDirectory.subscribe(function(newValue){self.modified(true)});
+
+ //private String location;
+ this.location=ko.observable(location);
+ this.location.subscribe(function(newValue){self.modified(true)});
+
+ //private String cronExpression = "0 0 * * * ?";
+ this.cronExpression=ko.observable(cronExpression);
+ this.cronExpression.subscribe(function(newValue){self.modified(true)});
+
+ //private ManagedRepository stagingRepository;
+
+ //private int daysOlder = 100;
+ this.daysOlder=ko.observable(daysOlder);
+ this.daysOlder.subscribe(function(newValue){self.modified(true)});
+
+ //private int retentionCount = 2;
+ this.retentionCount=ko.observable(retentionCount);
+ this.retentionCount.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean scanned = true;
+ this.scanned=ko.observable(scanned?scanned:true);
+ this.scanned.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean deleteReleasedSnapshots;
+ this.deleteReleasedSnapshots=ko.observable(deleteReleasedSnapshots);
+ this.deleteReleasedSnapshots.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean stageRepoNeeded;
+ this.stageRepoNeeded=ko.observable(stageRepoNeeded);
+ this.stageRepoNeeded.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean snapshots = false;
+ this.snapshots=ko.observable(snapshots?snapshots:false);
+ this.snapshots.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean releases = true;
+ this.releases=ko.observable(releases?releases:false);
+ this.releases.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean blockRedeployments = false;
+ this.blockRedeployments=ko.observable(blockRedeployments?blockRedeployments:false);
+ this.blockRedeployments.subscribe(function(newValue){self.modified(true)});
+
+ //private String name;
+ this.description=ko.observable(description);
+ this.description.subscribe(function(newValue){self.modified(true)});
+
+ this.skipPackedIndexCreation=ko.observable(skipPackedIndexCreation?skipPackedIndexCreation:false);
+ this.skipPackedIndexCreation.subscribe(function(newValue){self.modified(true)});
+
+ this.feedsUrl=feedsUrl;
+
+ this.url=url;
+
+ this.getTypeLabel=function(){
+ for(var i=0;i<window.managedRepositoryTypes.length;i++){
+ if (window.managedRepositoryTypes[i].type==self.layout()){
+ return window.managedRepositoryTypes[i].label;
+ }
+ }
+ return "no label";
+ }
+
+ this.modified=ko.observable(false);
+ }
+
+ ArchivaRepositoryStatistics=function(scanEndTime,scanStartTime,totalArtifactCount,totalArtifactFileSize,totalFileCount,
+ totalGroupCount,totalProjectCount,newFileCount,duration,managedRepository,lastScanDate){
+ //private Date scanEndTime;
+ this.scanEndTime = ko.observable(scanEndTime);
+
+ //private Date scanStartTime;
+ this.scanStartTime = ko.observable(scanStartTime);
+
+ //private long totalArtifactCount;
+ this.totalArtifactCount = ko.observable(totalArtifactCount);
+
+ //private long totalArtifactFileSize;
+ this.totalArtifactFileSize = ko.observable(totalArtifactFileSize);
+
+ //private long totalFileCount;
+ this.totalFileCount = ko.observable(totalFileCount);
+
+ //private long totalGroupCount;
+ this.totalGroupCount = ko.observable(totalGroupCount);
+
+ //private long totalProjectCount;
+ this.totalProjectCount = ko.observable(totalProjectCount);
+
+ //private long newFileCount;
+ this.newFileCount = ko.observable(newFileCount);
+
+ this.duration = ko.observable(duration);
+
+ this.managedRepository = managedRepository;
+
+ this.lastScanDate=ko.observable(lastScanDate);
+ }
+
+ mapManagedRepositories=function(data,applicationUrl){
+ var mappedManagedRepositories = $.map(data, function(item) {
+ var managedRepository = mapManagedRepository(item);
+ managedRepository.feedsUrl=applicationUrl+"/feeds/"+managedRepository.id();
+ managedRepository.url=applicationUrl+"/repository/"+managedRepository.id()
+ return managedRepository;
+ });
+ return mappedManagedRepositories;
+ }
+ mapManagedRepository=function(data){
+ if (data==null){
+ return null;
+ }
+ return new ManagedRepository(data.id,data.name,data.layout,data.indexDirectory,data.location,data.snapshots
+ ,data.releases,
+ data.blockRedeployments,data.cronExpression,
+ data.scanned,data.daysOlder,data.retentionCount,data.deleteReleasedSnapshots,
+ data.stageRepoNeeded,data.description,data.skipPackedIndexCreation);
+ }
+
+ mapArchivaRepositoryStatistics=function(data){
+ if (data==null){
+ return null;
+ }
+ return new ArchivaRepositoryStatistics(data.scanEndTime,data.scanStartTime,data.totalArtifactCount,data.totalArtifactFileSize,
+ data.totalFileCount,data.totalGroupCount,data.totalProjectCount,data.newFileCount,
+ data.duration,data.managedRepository,data.lastScanDate)
+ }
+
+ ManagedRepositoryViewModel=function(managedRepository, update, managedRepositoriesViewModel){
+ this.managedRepository=managedRepository;
+ this.managedRepositoriesViewModel = managedRepositoriesViewModel;
+ this.update = update;
+
+ var self = this;
+
+ this.availableLayouts = window.managedRepositoryTypes;
+
+ showCronExpressionDoc=function(){
+ //$.log("showCronExpressionDoc") ;
+ }
+
+ this.save=function(){
+ $.log('managedrepo save');
+ var valid = $("#main-content").find("#managed-repository-edit-form").valid();
+ if (valid==false) {
+ return;
+ }
+ $.log("save:"+this.managedRepository.name());
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $("#managed-repository-save-button" ).button('loading');
+ if (this.update){
+ $.ajax("restServices/archivaServices/managedRepositoriesService/updateManagedRepository",
+ {
+ type: "POST",
+ data: ko.toJSON(this.managedRepository),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop('managedrepository.updated',self.managedRepository.id()));
+ activateManagedRepositoriesGridTab();
+ self.managedRepository.modified(false);
+ },
+ complete: function(){
+ $("#managed-repository-save-button" ).button('reset');
+ removeMediumSpinnerImg(userMessages);
+ }
+ }
+ );
+ } else {
+ var url="restServices/archivaServices/managedRepositoriesService/fileLocationExists";
+ url+="?fileLocation="+encodeURIComponent(self.managedRepository.location());
+ $.ajax(url,
+ {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ if (data){
+ var completeCallbackFn = function(){window.modalConfirmDialog.modal('hide')};
+ openDialogConfirm(
+ function(){addManagedRepository(self.managedRepository,completeCallbackFn)},
+ $.i18n.prop('ok'), $.i18n.prop('cancel'),
+ $.i18n.prop('managedrepository.add.title'),
+ $("#managed-repository-location-warning-tmpl").tmpl(self.managedRepository));
+ }else{
+ addManagedRepository(self.managedRepository);
+ }
+ },
+ complete: function(){
+ $("#managed-repository-save-button" ).button('reset');
+ removeMediumSpinnerImg(userMessages);
+ }
+ });
+ }
+ }
+
+ addManagedRepository=function(managedRepository,completeCallbackFn){
+ var curManagedRepository=managedRepository;
+ var callbackFn = completeCallbackFn;
+ var dataJson=ko.toJSON(managedRepository);
+ $.log("managedRepository.release:"+managedRepository.releases()+",dataJson:"+dataJson);
+ $.ajax("restServices/archivaServices/managedRepositoriesService/addManagedRepository",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: dataJson,
+ dataType: 'json',
+ success: function(data) {
+ if (managedRepository.stageRepoNeeded()){
+ $.log("stageRepoNeeded:"+managedRepository.stageRepoNeeded());
+ // reload all to see the new staged repo
+ loadManagedRepositories(function(data){
+ self.managedRepositoriesViewModel.managedRepositories(mapManagedRepositories(data));
+ });
+ } else {
+ curManagedRepository.location(data.location);
+ self.managedRepositoriesViewModel.managedRepositories.push(curManagedRepository);
+ }
+
+ displaySuccessMessage($.i18n.prop('managedrepository.added',curManagedRepository.id()));
+ curManagedRepository.modified(false);
+ activateManagedRepositoriesGridTab();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ if(callbackFn){
+ callbackFn();
+ }
+ }
+ }
+ );
+ }
+
+ displayGrid=function(){
+ activateManagedRepositoriesGridTab();
+ }
+
+ }
+
+ activateManagedRepositoryFormValidation=function(){
+ var validator = $("#main-content" ).find("#managed-repository-edit-form").validate({
+ rules: {
+ daysOlder : {
+ digits: true,
+ min: 1
+ },
+ retentionCount : {
+ digits: true,
+ min: 1,
+ max: 100
+ },
+ cronExpression: {
+ required: true,
+ remote: {
+ url: "restServices/archivaServices/commonServices/validateCronExpression",
+ type: "get"
+ }
+ },
+ id: {
+ required: true,
+ remote: {
+ url: "restServices/archivaUiServices/dataValidatorService/managedRepositoryIdNotExists",
+ type: "get"
+ }
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #managed-repository-edit-form",validator,errorMap,errorMap);
+ }
+ });
+ validator.settings.messages["cronExpression"]=$.i18n.prop("cronExpression.notvalid");
+ validator.settings.messages["id"]=$.i18n.prop("id.required.or.alreadyexists");
+ }
+
+ ManagedRepositoriesViewModel=function(){
+ this.managedRepositories=ko.observableArray([]);
+
+ this.gridViewModel = null;
+ var self = this;
+
+ editManagedRepository=function(managedRepository){
+ var mainContent = $("#main-content");
+ var viewModel = new ManagedRepositoryViewModel(managedRepository,true,self);
+ ko.applyBindings(viewModel,mainContent.find("#managed-repository-edit").get(0));
+ activateManagedRepositoryEditTab();
+ mainContent.find("#managed-repository-edit-li a").html($.i18n.prop('edit'));
+ activateManagedRepositoryFormValidation();
+ activatePopoverDoc();
+ }
+
+ this.editManagedRepositoryWithId=function(managedRepositoryId){
+ $.each(self.managedRepositories(), function(index, value) {
+ if(value.id()==managedRepositoryId){
+ editManagedRepository(value);
+ }
+ });
+ }
+
+ scanNow=function(managedRepository){
+ clearUserMessages();
+ openDialogConfirm(
+ function(){
+ $("#dialog-confirm-modal" ).find("#modal-login-footer").append(smallSpinnerImg());
+ var checked = $("#managed-repository-scan-now-all").get(0).checked;
+ var url = "restServices/archivaServices/repositoriesService/scanRepositoryNow?";
+ url += "repositoryId="+encodeURIComponent(managedRepository.id());
+ url += "&fullScan="+(checked==true?"true":"false");
+ $.ajax(url,
+ {
+ type: "GET",
+ beforeSend:function(){
+ displayInfoMessage($.i18n.prop("managedrepository.scan.started",managedRepository.id()));
+ closeDialogConfirm();
+ },
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop("managedrepository.scanned",managedRepository.name()));
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ removeSmallSpinnerImg();
+ closeDialogConfirm();
+ }
+ }
+ );
+ },
+ $.i18n.prop("ok"),
+ $.i18n.prop("cancel"),
+ $.i18n.prop("managedrepository.scan.now"),
+ $("#managed-repository-scan-now-modal-tmpl").tmpl(managedRepository));
+
+ }
+
+ removeManagedRepository=function(managedRepository){
+ clearUserMessages();
+ openDialogConfirm(
+ function(){
+ var url = "restServices/archivaServices/managedRepositoriesService/deleteManagedRepository?";
+ url += "repositoryId="+encodeURIComponent(managedRepository.id());
+ var checked = $("#managedrepository-deletecontent").get(0).checked;
+ url += "&deleteContent="+(checked==true?"true":"false");
+ var dialogText=$("#dialog-confirm-modal-body-text" );
+ dialogText.html(mediumSpinnerImg());
+ $.ajax(url,
+ {
+ type: "GET",
+ success: function(data) {
+ self.managedRepositories.remove(managedRepository);
+ displaySuccessMessage($.i18n.prop("managedrepository.deleted",managedRepository.name()));
+
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ removeMediumSpinnerImg(dialogText);
+ closeDialogConfirm();
+ }
+ }
+ );
+
+ },
+ $.i18n.prop("ok"),
+ $.i18n.prop("cancel"),
+ $.i18n.prop("managedrepository.delete.confirm",managedRepository.name()),
+ $("#managed-repository-delete-warning-tmpl").tmpl(managedRepository));
+ }
+
+ updateManagedRepository=function(managedRepository){
+ var managedRepositoryViewModel = new ManagedRepositoryViewModel(managedRepository,true,this);
+ managedRepositoryViewModel.save();
+ }
+
+ this.bulkSave=function(){
+ $.log("bulkSave");
+ return getModifiedManagedRepositories().length>0;
+ }
+
+ getModifiedManagedRepositories=function(){
+ var prx = $.grep(self.managedRepositories(),
+ function (managedRepository,i) {
+ return managedRepository.modified();
+ });
+ return prx;
+ }
+ updateModifiedManagedRepositories=function(){
+ var repos = getModifiedManagedRepositories();
+
+ openDialogConfirm(function(){
+ for (i=0;i<repos.length;i++){
+ updateManagedRepository(repos[i]);
+ }
+ closeDialogConfirm();
+ },
+ $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('managed.repository.bulk.save.confirm.title'),
+ $.i18n.prop('managed.repository.bulk.save.confirm',repos.length));
+ }
+
+ directoriesScan=function(managedRepository){
+ $.log("directoriesScan:"+managedRepository.id());
+ clearUserMessages();
+ var url = "restServices/archivaServices/repositoriesService/scanRepositoryDirectoriesNow/"+managedRepository.id();
+ $.ajax(url,
+ {
+ type: "GET",
+ dataType: 'json',
+ beforeSend:function(){
+ displayInfoMessage($.i18n.prop("managedrepository.scan.directories.started", managedRepository.id()));
+ },
+ success: function(data) {
+ $.log(" scanRepositoryDirectoriesNow finished ");
+ displaySuccessMessage( $.i18n.prop("managedrepository.scan.directories.finished", managedRepository.id()));
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ removeSmallSpinnerImg();
+ }
+
+ }
+ );
+ }
+
+ showStats=function(managedRepository){
+ if ($(calculatePopoverId(managedRepository)).html()){
+ // we ask stats all the time ? if no uncomment return
+ //return;
+ $("#managedrepository-stats-"+escapeDot(managedRepository.id())).append(smallSpinnerImg());
+ }
+ var curRepo=managedRepository;
+ var url = "restServices/archivaServices/managedRepositoriesService/getManagedRepositoryStatistics/"+managedRepository.id();
+ url+="/"+encodeURIComponent(usedLang());
+ $.ajax(url,
+ {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ if (data==null){
+ return;
+ }
+ var archivaRepositoryStatistics=mapArchivaRepositoryStatistics(data);
+ archivaRepositoryStatistics.managedRepository=curRepo;
+ var mainContent = $("#main-content");
+ mainContent.find("#managedrepository-stats-"+escapeDot(curRepo.id())).append($("#managed-repository-stats-tmpl").tmpl(archivaRepositoryStatistics));
+ mainContent.find("#managedrepository-stats-img-"+escapeDot(curRepo.id())).attr("data-content",$(calculatePopoverId(curRepo)).html());
+ mainContent.find("#managedrepository-stats-img-"+escapeDot(curRepo.id())).popover(
+ {
+ placement: "left",
+ html: true,
+ trigger:'manual'
+ }
+ );
+
+ mainContent.find("#managedrepository-stats-img-"+escapeDot(curRepo.id())).popover('show');
+ removeSmallSpinnerImg();
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ }
+ }
+ );
+ }
+
+ calculatePopoverId=function(managedRepository){
+ return "#main-content #managedrepository-stats-"+escapeDot(managedRepository.id()) + " #managedrepository-stats-"+escapeDot(managedRepository.id())+"-popover";
+ }
+
+ hideStats=function(managedRepository){
+ $("#body_content" ).find(".popover" ).hide();
+ }
+
+ showPomSnippet=function(managedRepository){
+ var mainContent = $("#main-content");
+ mainContent.find("#managed-repositories-pom-snippet").html(mediumSpinnerImg());
+ mainContent.find('#managed-repositories-pom-snippet').show();
+ var url = "restServices/archivaServices/managedRepositoriesService/getPomSnippet/"+encodeURIComponent(managedRepository.id());
+ $.ajax(url,
+ {
+ type: "GET",
+ dataType: 'text',
+ success: function(data) {
+ $("#managed-repositories-pom-snippet").html($("#pom-snippet-tmpl").tmpl(data));
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ }
+ }
+ );
+
+ }
+
+ mergeRepo=function(managedRepository){
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ // is there any artifacts to merge ?
+ var artifactsNumberUrl = "restServices/archivaServices/browseService/artifacts/"+encodeURIComponent(managedRepository.id());
+ $.ajax(artifactsNumberUrl,{
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ var artifacts=mapArtifacts(data);
+ $.log("artifactsNumber for '" + managedRepository.id() + "': " + artifacts.length);
+
+ if (artifacts<1){
+ displayWarningMessage($.i18n.prop("managedrepository.merge.noartifacts", managedRepository.id()));
+ return;
+ }
+
+ $.log("merge repo open dialog");
+ var dialogMergeRepo=$("#dialog-modal-merge-repo");
+ if (window.modalMergeRepoDialog==null) {
+ window.modalMergeRepoDialog = dialogMergeRepo.modal();
+
+ }
+
+ loadManagedRepositories(function(data){
+
+ var managedRepositories = $.map(mapManagedRepositories(data), function(item) {
+ return item.id()==managedRepository.id()?null:item;
+ });
+ $("#dialog-modal-merge-repo-body-text").html($("#merge-repo-dialog-content" )
+ .tmpl({sourceRepoId:managedRepository.id(),repositories:managedRepositories}));
+ window.modalMergeRepoDialog.modal('show');
+ });
+
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ }
+ }
+ );
+
+ }
+
+
+ }
+
+
+ mergeRepositories=function(sourceRepository,targetRepository){
+ $.log("mergeRepositories:"+sourceRepository+":"+targetRepository);
+
+ var mergeRepoDialogBodyId="dialog-modal-merge-repo-body-text";
+ var mergeRepoDialogBody=$("#"+mergeRepoDialogBodyId);
+ mergeRepoDialogBody.html(mediumSpinnerImg());
+
+ // check conflicts
+ var url = "restServices/archivaServices/mergeRepositoriesService/mergeConflictedArtifacts/"+encodeURIComponent(sourceRepository);
+ url+="/"+encodeURIComponent(targetRepository);
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ var artifacts=mapArtifacts(data);
+ if (artifacts && artifacts.length){
+ // we have conflicts ask to skip or not
+ $.log("conflicts:"+artifacts.length);
+ displayWarningMessage($.i18n.prop("managedrepository.merge.conflicts", artifacts.length),"dialog-modal-merge-repo-body-text");
+ $.tmpl($("#merge-repo-skip-conflicts").html(),
+ { artifacts:artifacts, sourceRepository: sourceRepository, targetRepository:targetRepository })
+ .appendTo( "#dialog-modal-merge-repo-body-text" );
+ $("#dialog-modal-merge-repo-header-title" ).html($.i18n.prop("managedrepository.merge.conflicts.header",sourceRepository,targetRepository));
+ } else {
+ doMerge(sourceRepository,targetRepository,false);
+ }
+ },
+ complete: function(){
+ $.log("complete removeMediumSpinnerImg");
+ removeMediumSpinnerImg("#dialog-modal-merge-repo-body-text");
+ }
+ });
+
+
+
+ }
+
+ doMerge=function(sourceRepository,targetRepository,skipConflicts){
+ $.log("doMerge:"+sourceRepository+" to " + targetRepository + ", skipConflicts: " + skipConflicts);
+ window.modalMergeRepoDialog.modal('hide');
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ var url = "restServices/archivaServices/mergeRepositoriesService/mergeRepositories/"+encodeURIComponent(sourceRepository);
+ url+="/"+encodeURIComponent(targetRepository);
+ url+="/"+skipConflicts;
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data){
+ displaySuccessMessage($.i18n.prop("managedrepository.merge.success", sourceRepository,targetRepository));
+ },
+ complete: function(){
+ removeMediumSpinnerImg(userMessages);
+ }
+ });
+ }
+
+ activateManagedRepositoriesGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#managed-repository-edit-li").removeClass("active");
+ mainContent.find("#managed-repository-edit").removeClass("active");
+
+ mainContent.find("#managed-repositories-view-li").addClass("active");
+ mainContent.find("#managed-repositories-view").addClass("active");
+ mainContent.find("#managed-repository-edit-li a").html($.i18n.prop("add"));
+ }
+
+ activateManagedRepositoryEditTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#managed-repositories-view-li").removeClass("active");
+ mainContent.find("#managed-repositories-view").removeClass("active");
+
+ mainContent.find("#managed-repository-edit-li").addClass("active");
+ mainContent.find("#managed-repository-edit").addClass("active");
+ }
+
+
+ //---------------------------
+ // Remote repositories part
+ //---------------------------
+
+
+
+ RemoteRepository=function(id,name,layout,indexDirectory,url,userName,password,timeout,downloadRemoteIndex,remoteIndexUrl,
+ remoteDownloadNetworkProxyId,cronExpression,remoteDownloadTimeout,downloadRemoteIndexOnStartup,
+ description,extraParametersEntries,extraHeadersEntries){
+
+ var self=this;
+
+ //private String id;
+ this.id=ko.observable(id);
+ this.id.subscribe(function(newValue){self.modified(true)});
+
+ //private String name;
+ this.name=ko.observable(name);
+ this.name.subscribe(function(newValue){self.modified(true)});
+
+ //private String layout = "default";
+ this.layout=ko.observable(layout);
+ this.layout.subscribe(function(newValue){self.modified(true)});
+
+ //private String indexDirectory;
+ this.indexDirectory=ko.observable(indexDirectory);
+ this.indexDirectory.subscribe(function(newValue){self.modified(true)});
+
+ //private String url;
+ this.url=ko.observable(url);
+ this.url.subscribe(function(newValue){self.modified(true)});
+
+ //private String userName;
+ this.userName=ko.observable(userName);
+ this.userName.subscribe(function(newValue){self.modified(true)});
+
+ //private String password;
+ this.password=ko.observable(password);
+ this.password.subscribe(function(newValue){self.modified(true)});
+
+ //private int timeout = 60;
+ this.timeout=ko.observable(timeout);
+ this.timeout.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean downloadRemoteIndex = false;
+ this.downloadRemoteIndex=ko.observable(downloadRemoteIndex?false:downloadRemoteIndex);
+ this.downloadRemoteIndex.subscribe(function(newValue){self.modified(true)});
+
+ //private String remoteIndexUrl = ".index";
+ this.remoteIndexUrl=ko.observable(remoteIndexUrl);
+ this.remoteIndexUrl.subscribe(function(newValue){self.modified(true)});
+
+ //private String remoteDownloadNetworkProxyId;
+ this.remoteDownloadNetworkProxyId=ko.observable(remoteDownloadNetworkProxyId);
+ this.remoteDownloadNetworkProxyId.subscribe(function(newValue){self.modified(true)});
+
+ //private String cronExpression = "0 0 08 ? * SUN";
+ this.cronExpression=ko.observable(cronExpression);
+ this.cronExpression.subscribe(function(newValue){self.modified(true)});
+
+ //private int remoteDownloadTimeout = 300;
+ this.remoteDownloadTimeout=ko.observable(remoteDownloadTimeout);
+ this.remoteDownloadTimeout.subscribe(function(newValue){self.modified(true)});
+
+ //private boolean downloadRemoteIndexOnStartup = false;
+ this.downloadRemoteIndexOnStartup=ko.observable(downloadRemoteIndexOnStartup?false:downloadRemoteIndexOnStartup);
+ this.downloadRemoteIndexOnStartup.subscribe(function(newValue){self.modified(true)});
+
+ this.description=ko.observable(description);
+ this.description.subscribe(function(newValue){self.modified(true)});
+
+ this.getTypeLabel=function(){
+ for(var i=0;i<window.managedRepositoryTypes.length;i++){
+ if (window.managedRepositoryTypes[i].type==self.layout()){
+ return window.managedRepositoryTypes[i].label;
+ }
+ }
+ return "no label";
+ }
+
+ this.extraParametersEntries=ko.observableArray(extraParametersEntries==null?new Array():extraParametersEntries);
+ this.extraParametersEntries.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ this.extraHeadersEntries=ko.observableArray(extraHeadersEntries==null?new Array():extraHeadersEntries);
+ this.extraHeadersEntries.subscribe(function(newValue){
+ self.modified(true);
+ });
+
+ this.modified=ko.observable(false);
+ }
+
+ mapRemoteRepository=function(data){
+ if (data==null){
+ return null;
+ }
+
+ var extraParametersEntries = data.extraParametersEntries == null ? []: $.each(data.extraParametersEntries,function(item){
+ return new Entry(item.key, item.value);
+ });
+ if (!$.isArray(extraParametersEntries)){
+ extraParametersEntries=[];
+ }
+
+ var extraHeadersEntries = data.extraHeadersEntries == null ? []: $.each(data.extraHeadersEntries,function(item){
+ return new Entry(item.key, item.value);
+ });
+ if (!$.isArray(extraHeadersEntries)){
+ extraHeadersEntries=[];
+ }
+
+ return new RemoteRepository(data.id,data.name,data.layout,data.indexDirectory,data.url,data.userName,data.password,
+ data.timeout,data.downloadRemoteIndex,data.remoteIndexUrl,data.remoteDownloadNetworkProxyId,
+ data.cronExpression,data.remoteDownloadTimeout,data.downloadRemoteIndexOnStartup,data.description,
+ extraParametersEntries,extraHeadersEntries);
+ }
+
+ mapRemoteRepositories=function(data){
+ var mappedRemoteRepositories = $.map(data, function(item) {
+ return mapRemoteRepository(item);
+ });
+ return mappedRemoteRepositories;
+ }
+
+ RemoteRepositoryViewModel=function(remoteRepository, update, remoteRepositoriesViewModel){
+ this.remoteRepository=remoteRepository;
+ this.remoteRepositoriesViewModel = remoteRepositoriesViewModel;
+ this.networkProxies=ko.observableArray([]);
+ this.update = update;
+
+ var self = this;
+
+ this.availableLayouts = window.managedRepositoryTypes;
+
+ this.save=function(){
+ var valid = $("#main-content" ).find("#remote-repository-edit-form").valid();
+ if (valid==false) {
+ return;
+ }
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $("#remote-repository-save-button" ).button('loading');
+ if (update){
+ $.ajax("restServices/archivaServices/remoteRepositoriesService/updateRemoteRepository",
+ {
+ type: "POST",
+ data: ko.toJSON(this.remoteRepository),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ displaySuccessMessage($.i18n.prop('remoterepository.updated',self.remoteRepository.id()));
+ activateRemoteRepositoriesGridTab();
+ self.remoteRepository.modified(false);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ $("#remote-repository-save-button" ).button('reset');
+ removeMediumSpinnerImg(userMessages);
+ }
+ }
+ );
+ }else {
+ $.ajax("restServices/archivaServices/remoteRepositoriesService/addRemoteRepository",
+ {
+ type: "POST",
+ data: ko.toJSON(this.remoteRepository),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ self.remoteRepository.modified(false);
+ self.remoteRepositoriesViewModel.remoteRepositories.push(self.remoteRepository);
+ displaySuccessMessage($.i18n.prop('remoterepository.added'));
+ activateRemoteRepositoriesGridTab();
+ removeMediumSpinnerImg(userMessages);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+ }
+ }
+
+ displayGrid=function(){
+ activateRemoteRepositoriesGridTab();
+ }
+
+ addExtraParameter=function(){
+
+ var mainContent=$("#main-content");
+ mainContent.find("#extra-parameters-error" ).empty();
+ var key=mainContent.find("#extraParameter-key").val();
+ if($.trim(key).length<1){
+ displayErrorMessage( $.i18n.prop("key.empty.error.message"),"extra-parameters-error");
+ return;
+ }
+ var value=mainContent.find("#extraParameter-value").val();
+ $.log("addExtraParameter="+key+":"+value);
+ var oldTab = self.remoteRepository.extraParametersEntries();
+ oldTab.push(new Entry(key,value));
+ self.remoteRepository.extraParametersEntries(oldTab);
+ mainContent.find("#extraParameter-key").val("");
+ mainContent.find("#extraParameter-value").val("");
+ self.remoteRepository.modified(true);
+ }
+
+ deleteExtraParameter=function(key){
+ for(var i=0;i<self.remoteRepository.extraParametersEntries().length;i++){
+ var entry=self.remoteRepository.extraParametersEntries()[i];
+ if (entry.key==key){
+ self.remoteRepository.extraParametersEntries.remove(entry);
+ self.remoteRepository.modified(true);
+ }
+ }
+ }
+
+ addExtraHeader=function(){
+
+ var mainContent=$("#main-content");
+ mainContent.find("#extra-headers-error" ).empty();
+ var key=mainContent.find("#extraHeader-key").val();
+ if( $.trim(key).length<1){
+ if($.trim(key).length<1){
+ displayErrorMessage( $.i18n.prop("key.empty.error.message"),"extra-headers-error");
+ return;
+ }
+ }
+ var value=mainContent.find("#extraHeader-value").val();
+ $.log("addExtraParameter="+key+":"+value);
+ var oldTab = self.remoteRepository.extraHeadersEntries();
+ oldTab.push(new Entry(key,value));
+ self.remoteRepository.extraHeadersEntries(oldTab);
+ mainContent.find("#extraHeader-key").val("");
+ mainContent.find("#extraHeader-value").val("");
+ self.remoteRepository.modified(true);
+ }
+
+ deleteExtraHeader=function(key){
+ for(var i=0;i<self.remoteRepository.extraHeadersEntries().length;i++){
+ var entry=self.remoteRepository.extraHeadersEntries()[i];
+ if (entry.key==key){
+ self.remoteRepository.extraHeadersEntries.remove(entry);
+ self.remoteRepository.modified(true);
+ }
+ }
+ }
+
+ }
+
+ RemoteRepositoriesViewModel=function(){
+ this.remoteRepositories=ko.observableArray([]);
+ this.applicationUrl=null;
+ this.gridViewModel = null;
+ var self = this;
+
+ editRemoteRepository=function(remoteRepository){
+ $.log("editRemoteRepository");
+ $.ajax("restServices/archivaServices/networkProxyService/getNetworkProxies", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var viewModel = new RemoteRepositoryViewModel(remoteRepository,true,self);
+ viewModel.networkProxies(mapNetworkProxies(data));
+ var mainContent = $("#main-content");
+
+ ko.applyBindings(viewModel,mainContent.find("#remote-repository-edit").get(0));
+ activateRemoteRepositoryEditTab();
+ mainContent.find("#remote-repository-edit-li a").html($.i18n.prop('edit'));
+ activateRemoteRepositoryFormValidation(false);
+ activatePopoverDoc();
+ }
+ })
+
+ }
+
+ removeRemoteRepository=function(remoteRepository){
+ clearUserMessages();
+ openDialogConfirm(
+ function(){
+ var dialogText=$("#dialog-confirm-modal-body-text" );
+ dialogText.html(mediumSpinnerImg());
+ $.ajax("restServices/archivaServices/remoteRepositoriesService/deleteRemoteRepository/"+encodeURIComponent(remoteRepository.id()),
+ {
+ type: "GET",
+ success: function(data) {
+ self.remoteRepositories.remove(remoteRepository);
+ displaySuccessMessage($.i18n.prop('remoterepository.deleted',remoteRepository.id()));
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(){
+ removeMediumSpinnerImg(dialogText);
+ closeDialogConfirm();
+ }
+ }
+ )}, $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('remoterepository.delete.confirm',remoteRepository.id()),
+ $("#remote-repository-delete-modal-tmpl").tmpl(remoteRepository));
+
+ }
+
+ this.bulkSave=function(){
+ return getModifiedRemoteRepositories().length>0;
+ }
+
+ getModifiedRemoteRepositories=function(){
+ var prx = $.grep(self.remoteRepositories(),
+ function (remoteRepository,i) {
+ return remoteRepository.modified();
+ });
+ return prx;
+ }
+
+ updateModifiedRemoteRepositories=function(){
+ var modifiedRemoteRepositories = getModifiedRemoteRepositories();
+
+ openDialogConfirm(function(){
+ for(var i=0;i<modifiedRemoteRepositories.length;i++){
+ updateRemoteRepository(modifiedRemoteRepositories[i]);
+ }
+ closeDialogConfirm();
+ },
+ $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('remoterepositories.bulk.save.confirm.title'),
+ $.i18n.prop('remoterepositories.bulk.save.confirm',modifiedRemoteRepositories.length));
+ }
+
+ updateRemoteRepository=function(remoteRepository){
+ var viewModel = new RemoteRepositoryViewModel(remoteRepository,true,self);
+ viewModel.save();
+ }
+
+ scheduleDownloadRemoteIndex=function(remoteRepository){
+ openDialogConfirm(
+ function(){
+
+ var url = "restServices/archivaServices/repositoriesService/scheduleDownloadRemoteIndex?";
+ url += "repositoryId="+encodeURIComponent(remoteRepository.id());
+
+ var now = $("#remoterepository-scan-now").get(0).checked;
+
+ var full = $("#remoterepository-scan-full").get(0).checked;
+
+ url += "&now="+(now==true?"true":"false");
+ url += "&fullDownload="+(full==true?"true":"false");
+ $.ajax(url,
+ {
+ type: "GET",
+ success: function(data) {
+ clearUserMessages();
+ displaySuccessMessage($.i18n.prop("remoterepository.download.remote.scheduled",remoteRepository.name()));
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete: function(){
+ closeDialogConfirm();
+ }
+ }
+ );
+
+ },
+ $.i18n.prop("ok"),
+ $.i18n.prop("cancel"),
+ $.i18n.prop("remoterepository.download.remote.confirm",remoteRepository.name()),
+ $("#remote-repository-scan-modal-tmpl").tmpl(remoteRepository));
+ }
+ }
+
+ /**
+ *
+ * @param validateId to validate if id already exists: not needed for update !
+ */
+ activateRemoteRepositoryFormValidation=function(validateId){
+ // FIXME find a way to activate cronExpression validation only if downloadRemote is activated !
+ var validator = null;
+ if (validateId){
+ validator = $("#main-content" ).find("#remote-repository-edit-form").validate({
+ rules: {
+ id: {
+ required: true,
+ remote: {
+ url: "restServices/archivaUiServices/dataValidatorService/remoteRepositoryIdNotExists",
+ type: "get"
+ }
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #remote-repository-edit-form",validator,errorMap,errorMap);
+ }
+ });
+ } else {
+ validator = $("#main-content" ).find("#remote-repository-edit-form").validate({
+ rules: {
+ id: {
+ required: true
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #remote-repository-edit-form",validator,errorMap,errorMap);
+ }
+ });
+ }
+ validator.settings.messages["cronExpression"]=$.i18n.prop("cronExpression.notvalid");
+ validator.settings.messages["id"]=$.i18n.prop("id.required.or.alreadyexists");
+ }
+
+ activateRemoteRepositoriesGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#remote-repository-edit-li").removeClass("active");
+ mainContent.find("#remote-repository-edit").removeClass("active");
+
+ mainContent.find("#remote-repositories-view-li").addClass("active");
+ mainContent.find("#remote-repositories-view").addClass("active");
+ mainContent.find("#remote-repository-edit-li a").html($.i18n.prop("add"));
+ }
+
+ activateRemoteRepositoryEditTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#remote-repositories-view-li").removeClass("active");
+ mainContent.find("#remote-repositories-view").removeClass("active");
+
+ mainContent.find("#remote-repository-edit-li").addClass("active");
+ mainContent.find("#remote-repository-edit").addClass("active");
+ }
+
+ //---------------------------
+ // Screen loading
+ //---------------------------
+
+ /**
+ *
+ * @param successFnManagedRepositories function called with param managedRepositoriesViewModel when managed repositories grid has been displayed
+ * @param successFnRemoteRepositories function called with param remoteRepositoriesViewModel when remote repositories grid has been displayed
+ */
+ displayRepositoriesGrid=function(successFnManagedRepositories,successFnRemoteRepositories){
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ mainContent.html($("#repositoriesMain").tmpl());
+ mainContent.find("#repositories-tabs a:first").tab("show");
+
+ mainContent.find("#managed-repositories-content").append(mediumSpinnerImg());
+ mainContent.find("#remote-repositories-content").append(mediumSpinnerImg());
+
+ var managedRepositoriesViewModel = new ManagedRepositoriesViewModel();
+ var remoteRepositoriesViewModel = new RemoteRepositoriesViewModel();
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+ $.log("applicationUrl:"+applicationUrl);
+ loadManagedRepositories(function(data) {
+
+
+ managedRepositoriesViewModel.managedRepositories(
+ mapManagedRepositories(data,applicationUrl?applicationUrl:window.location.toString().substringBeforeLast("/")));
+
+ managedRepositoriesViewModel.gridViewModel = new ko.simpleGrid.viewModel({
+ data: managedRepositoriesViewModel.managedRepositories,
+ columns: [
+ {
+ headerText: $.i18n.prop('identifier'),
+ rowText: "id"
+ },
+ {
+ headerText: $.i18n.prop('name'),
+ rowText: "name"
+ },
+ {
+ headerText: $.i18n.prop('type'),
+ rowText: "getTypeLabel",
+ // FIXME i18n
+ title: "Repository type (default is Maven 2)"
+ }
+ ],
+ pageSize: 5,
+ gridUpdateCallBack: function(){
+ // a bit ugly
+ //$("#main-content" ).find("#managed-repositories-table").find("[title]").tooltip({animation:"false"});
+ }
+ });
+ var mainContent = $("#main-content");
+ ko.applyBindings(managedRepositoriesViewModel,mainContent.find("#managed-repositories-view").get(0));
+ activatePopoverDoc();
+ mainContent.find("#managed-repositories-pills #managed-repositories-view-a").tab('show');
+ removeMediumSpinnerImg(mainContent.find("#managed-repositories-content"));
+ activateManagedRepositoriesGridTab();
+ if(successFnManagedRepositories){
+ successFnManagedRepositories(managedRepositoriesViewModel);
+ }
+ });
+
+ loadRemoteRepositories(function(data) {
+ remoteRepositoriesViewModel.remoteRepositories(mapRemoteRepositories(data));
+ remoteRepositoriesViewModel.gridViewModel = new ko.simpleGrid.viewModel({
+ data: remoteRepositoriesViewModel.remoteRepositories,
+ columns: [
+ {
+ headerText: $.i18n.prop('identifier'),
+ rowText: "id"
+ },
+ {
+ headerText: $.i18n.prop('name'),
+ rowText: "name"
+ },
+ {
+ headerText: $.i18n.prop('url'),
+ rowText: "url"
+ },
+ {
+ headerText: $.i18n.prop('type'),
+ rowText: "getTypeLabel",
+ // FIXME i18n
+ title: "Repository type (default is Maven 2)"
+ }
+ ],
+ pageSize: 5,
+ gridUpdateCallBack: function(){
+ //$("#main-content" ).find("#remote-repositories-table").find("[title]").tooltip();
+ }
+ });
+ var mainContent = $("#main-content");
+ ko.applyBindings(remoteRepositoriesViewModel,mainContent.find("#remote-repositories-view").get(0));
+ mainContent.find("#remote-repositories-pills #remote-repositories-view-a").tab('show')
+ removeMediumSpinnerImg(mainContent.find("#remote-repositories-content"));
+ activatePopoverDoc();
+ if(successFnRemoteRepositories){
+ successFnRemoteRepositories(managedRepositoriesViewModel);
+ }
+ });
+ }
+ }
+ );
+
+
+ mainContent.find("#managed-repositories-pills").on('show', function (e) {
+ var mainContent = $("#main-content");
+ if ($(e.target).attr("href")=="#managed-repository-edit") {
+ var managedRepo=new ManagedRepository();
+ managedRepo.cronExpression("0 0 * * * ?");
+ var viewModel = new ManagedRepositoryViewModel(managedRepo,false,managedRepositoriesViewModel);
+ ko.applyBindings(viewModel,mainContent.find("#managed-repository-edit").get(0));
+ activateManagedRepositoryFormValidation();
+ activatePopoverDoc();
+ }
+ if ($(e.target).attr("href")=="#managed-repositories-view") {
+ mainContent.find("#managed-repository-edit-li a").html($.i18n.prop("add"));
+ }
+
+ });
+
+ mainContent.find("#remote-repositories-pills").on('show', function (e) {
+ if ($(e.target).attr("href")=="#remote-repository-edit") {
+ $.ajax("restServices/archivaServices/networkProxyService/getNetworkProxies", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var remoteRepo=new RemoteRepository();
+ remoteRepo.cronExpression("0 0 08 ? * SUN");
+ var viewModel = new RemoteRepositoryViewModel(remoteRepo,false,remoteRepositoriesViewModel);
+ viewModel.networkProxies(mapNetworkProxies(data));
+ ko.applyBindings(viewModel,mainContent.find("#remote-repository-edit").get(0));
+ activateRemoteRepositoryFormValidation(true);
+ activatePopoverDoc();
+ }
+ })
+ }
+ if ($(e.target).attr("href")=="#remote-repositories-view") {
+ $("#main-content" ).find("#remote-repository-edit-li" ).find("a").html($.i18n.prop("add"));
+ }
+
+ });
+
+ }
+
+ loadManagedRepositories=function(successCallBackFn,errorCallBackFn){
+ $.ajax("restServices/archivaServices/managedRepositoriesService/getManagedRepositories", {
+ type: "GET",
+ dataType: 'json',
+ success: successCallBackFn,
+ error: errorCallBackFn
+ });
+ }
+
+ loadRemoteRepositories=function(successCallBackFn,errorCallBackFn){
+ $.ajax("restServices/archivaServices/remoteRepositoriesService/getRemoteRepositories", {
+ type: "GET",
+ dataType: 'json',
+ success: successCallBackFn,
+ error: errorCallBackFn
+ });
+ }
+
+ findManagedRepository=function(id,managedRepositories){
+ var managedRepository=$.grep(managedRepositories,
+ function(repo,idx){
+ return repo.id()==id;
+ }
+ );
+ return ($.isArray(managedRepository) && managedRepository.length>0) ? managedRepository[0]:new ManagedRepository();
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repository-groups.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repository-groups.js
new file mode 100644
index 000000000..98cdd9323
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/repository-groups.js
@@ -0,0 +1,385 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.repository-groups",["jquery","i18n","jquery.tmpl","bootstrap","jquery.validate","jquery.ui","knockout"
+ ,"knockout.simpleGrid","knockout.sortable"],
+function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,jqueryUi,ko) {
+
+ RepositoryGroup=function(id,repositories){
+
+ var self=this;
+
+ //private String id;
+ this.id=ko.observable(id);
+ this.id.subscribe(function(newValue){self.modified(true)});
+
+ // private List<String> repositories;
+ this.repositories=ko.observableArray(repositories);
+ this.repositories.subscribe(function(newValue){self.modified(true)});
+
+ // to store managedRepositories description not sended to server
+ this.managedRepositories=ko.observableArray([]);
+ this.managedRepositories.subscribe(function(newValue){self.modified(true)});
+
+ this.modified=ko.observable(false);
+ }
+
+ RepositoryGroupViewModel=function(repositoryGroup,update,repositoryGroupsViewModel){
+ var self = this;
+ this.repositoryGroup=repositoryGroup;
+ this.update=update;
+ this.repositoryGroupsViewModel=repositoryGroupsViewModel;
+ this.availableRepositories=ko.observableArray([]);
+ this.applicationUrl=null;
+
+ for (var i=0;i<repositoryGroupsViewModel.managedRepositories().length;i++){
+ if ( $.inArray(repositoryGroupsViewModel.managedRepositories()[i].id(),this.repositoryGroup.repositories())<0){
+ this.availableRepositories.push(repositoryGroupsViewModel.managedRepositories()[i]);
+ }
+ }
+
+ repositoryMoved=function(arg){
+ $.log("repositoryMoved:"+arg.sourceIndex+" to " + arg.targetIndex);
+ var repositories=[];
+ for(var i=0;i<self.repositoryGroup.managedRepositories().length;i++){
+ repositories.push(self.repositoryGroup.managedRepositories()[i].id());
+ }
+ self.repositoryGroup.repositories(repositories);
+ self.repositoryGroup.modified(true);
+ var mainContent=$("#main-content");
+ mainContent.find("#repository-groups-edit-available-repositories").find(".icon-plus-sign" ).off("click");
+ mainContent.find("#repository-groups-edit-order-div").find(".icon-minus-sign" ).off("click");
+ self.renderSortableAvailables(self.repositoryGroupsViewModel);
+ self.renderSortableChoosed(self.repositoryGroupsViewModel);
+ }
+
+ this.saveRepositoryGroup=function(repositoryGroup){
+ if (self.update){
+ self.repositoryGroupsViewModel.saveRepositoryGroup(repositoryGroup);
+ } else {
+ self.repositoryGroupsViewModel.addRepositoryGroup(repositoryGroup);
+ }
+ }
+
+ this.removeRepository=function(id){
+ $.log("removeRepository:"+id);
+ }
+
+ this.removeAvailable=function(idVal){
+ for (var i=0;i<self.repositoryGroupsViewModel.managedRepositories().length;i++){
+ if(self.repositoryGroupsViewModel.managedRepositories()[i].id()==idVal){
+ self.availableRepositories.remove(repositoryGroupsViewModel.managedRepositories()[i]);
+ }
+ }
+
+ for(var i= 0;i<self.repositoryGroupsViewModel.managedRepositories().length;i++){
+ if(self.repositoryGroupsViewModel.managedRepositories()[i].id()==idVal){
+ $.log("find repo to add");
+ self.repositoryGroup.repositories.push(idVal);
+ self.repositoryGroup.managedRepositories.push(findManagedRepository(idVal,self.repositoryGroupsViewModel.managedRepositories()));
+ }
+ }
+ $("#main-content").find("#repository-groups-edit-order-div").find("#minus-"+idVal ).on("click",function(){
+ var idVal = $(this).attr("id");
+ idVal=idVal.substringAfterFirst("minus-");
+ self.removeChoosed(idVal);
+ });
+ }
+
+ this.renderSortableAvailables=function(repositoryGroupsViewModel){
+ $("#main-content").find("#repository-groups-edit-available-repositories").find(".icon-plus-sign" ).on("click",function(){
+ var idVal = $(this).attr("id");
+ idVal=idVal.substringAfterFirst("plus-");
+ self.removeAvailable(idVal);
+ });
+ }
+
+ this.removeChoosed=function(idVal){
+ for (var i=0;i<self.repositoryGroupsViewModel.managedRepositories().length;i++){
+ if(self.repositoryGroupsViewModel.managedRepositories()[i].id()==idVal){
+ self.availableRepositories.push(repositoryGroupsViewModel.managedRepositories()[i]);
+ }
+ }
+
+ for(var i= 0;i<self.repositoryGroup.repositories().length;i++){
+ if(self.repositoryGroup.repositories()[i]==idVal){
+ self.repositoryGroup.repositories.remove(self.repositoryGroup.repositories()[i]);
+ self.repositoryGroup.managedRepositories.remove(findManagedRepository(idVal,self.repositoryGroupsViewModel.managedRepositories()));
+ }
+ }
+ $("#main-content").find("#repository-groups-edit-available-repositories").find("#plus-"+idVal ).on("click",function(){
+ var idVal = $(this).attr("id");
+ idVal=idVal.substringAfterFirst("plus-");
+ self.removeAvailable(idVal);
+ });
+ }
+
+ this.renderSortableChoosed=function(repositoryGroupsViewModel){
+ $("#main-content").find("#repository-groups-edit-order-div").find(".icon-minus-sign" ).on("click",function(){
+ var idVal = $(this).attr("id");
+ idVal=idVal.substringAfterFirst("minus-");
+ self.removeChoosed(idVal);
+ });
+ }
+ }
+
+ RepositoryGroupsViewModel=function(){
+ var self=this;
+ this.repositoryGroups=ko.observableArray([]);
+ this.managedRepositories=ko.observableArray([]);
+ this.applicationUrl="";
+
+ this.removeFromList=function(managedRepository){
+ $.log("removeFromList");
+ }
+
+ this.findManagedRepository=function(id){
+ return findManagedRepository(id,self.managedRepositories());
+ }
+ this.deleteRepositoryGroup=function(repositoryGroup){
+ openDialogConfirm(
+ function(){self.removeRepositoryGroup(repositoryGroup);window.modalConfirmDialog.modal('hide')},
+ $.i18n.prop('ok'), $.i18n.prop('cancel'),
+ $.i18n.prop('repository.group.delete.confirm',repositoryGroup.id()),
+ $("#repository-group-delete-warning-tmpl").tmpl(self.repositoryGroup));
+ }
+ this.removeRepositoryGroup=function(repositoryGroup){
+ clearUserMessages();
+ $.ajax("restServices/archivaServices/repositoryGroupService/deleteRepositoryGroup/"+encodeURIComponent(repositoryGroup.id()),
+ {
+ type: "GET",
+ success: function(data) {
+ var message=$.i18n.prop('repository.group.deleted',repositoryGroup.id());
+ displaySuccessMessage(message);
+ self.repositoryGroups.remove(repositoryGroup);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+ }
+
+ this.editRepositoryGroup=function(repositoryGroup){
+
+ var mainContent=$("#main-content");
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+ $.log("editRepositoryGroup:"+repositoryGroup.id()+",repositories:"+repositoryGroup.repositories().length+",managed:"+repositoryGroup.managedRepositories().length);
+ var repositoryGroupViewModel=new RepositoryGroupViewModel(repositoryGroup,true,self);
+ repositoryGroupViewModel.applicationUrl=applicationUrl;
+ activateRepositoryGroupEditTab();
+ ko.applyBindings(repositoryGroupViewModel,mainContent.find("#repository-groups-edit" ).get(0));
+ repositoryGroupViewModel.renderSortableChoosed(self);
+ repositoryGroupViewModel.renderSortableAvailables(self);
+ mainContent.find("#repository-groups-view-tabs-li-edit" ).find("a").html($.i18n.prop("edit"));
+ }
+ });
+ }
+
+ this.editRepositoryGroupWithId=function(repositoryGroupId){
+
+ $.each(self.repositoryGroups(), function(index, value) {
+ if(value.id()==repositoryGroupId){
+ self.editRepositoryGroup(value);
+ }
+ });
+ }
+
+ this.saveRepositoryGroup=function(repositoryGroup){
+ clearUserMessages();
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ $("#repository-group-save" ).button('loading');
+ $.ajax("restServices/archivaServices/repositoryGroupService/updateRepositoryGroup",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data:ko.toJSON(repositoryGroup),
+ dataType: 'json',
+ success: function(data) {
+ $.log("update repositoryGroup id:"+repositoryGroup.id());
+ var message=$.i18n.prop('repository.group.updated',repositoryGroup.id());
+ displaySuccessMessage(message);
+ repositoryGroup.modified(false);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function(data){
+ $("#repository-group-save" ).button('reset');
+ removeMediumSpinnerImg(userMessages);
+ }
+ }
+ );
+
+ }
+
+ this.addRepositoryGroup=function(repositoryGroup){
+ clearUserMessages();
+ $.ajax("restServices/archivaServices/repositoryGroupService/addRepositoryGroup",
+ {
+ type: "POST",
+ contentType: 'application/json',
+ data: ko.toJSON(repositoryGroup),
+ dataType: 'json',
+ success: function(data) {
+ $.log("update repositoryGroup id:"+repositoryGroup.id());
+ var message=$.i18n.prop('repository.group.added',repositoryGroup.id());
+ displaySuccessMessage(message);
+ repositoryGroup.modified(false);
+ self.repositoryGroups.push(repositoryGroup);
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ }
+ }
+ );
+
+ }
+
+ getManagedRepository=function(id){
+ $.log("getManagedRepository:"+id);
+ return findManagedRepository(self.managedRepositories());
+ }
+
+ }
+
+ displayRepositoryGroups=function(successFn){
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ this.repositoryGroupsViewModel=new RepositoryGroupsViewModel();
+ var self=this;
+
+ loadManagedRepositories(function(data) {
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+
+ self.repositoryGroupsViewModel.managedRepositories(mapManagedRepositories(data,applicationUrl));
+ self.repositoryGroupsViewModel.applicationUrl=applicationUrl;
+ $.ajax("restServices/archivaServices/repositoryGroupService/getRepositoriesGroups", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedRepositoryGroups=mapRepositoryGroups(data);
+ for(var i=0;i<mappedRepositoryGroups.length;i++){
+ mappedRepositoryGroups[i]
+ .managedRepositories(self.mapManagedRepositoriesToRepositoryGroup(mappedRepositoryGroups[i]));
+ mappedRepositoryGroups[i].modified(false);
+ $.log("mappedRepositoryGroups.repositories().length:"+mappedRepositoryGroups[i].repositories().length);
+ }
+ mainContent.html($("#repositoryGroupsMain").tmpl());
+ self.repositoryGroupsViewModel.repositoryGroups(mappedRepositoryGroups);
+ $.log("displayRepositoryGroups#applyBindings before");
+ ko.applyBindings(self.repositoryGroupsViewModel,mainContent.find("#repository-groups-view" ).get(0));
+ $.log("displayRepositoryGroups#applyBindings after");
+
+ mainContent.find("#repository-groups-view-tabs").on('show', function (e) {
+ if ($(e.target).attr("href")=="#repository-groups-edit") {
+ var repositoryGroup = new RepositoryGroup();
+ var repositoryGroupViewModel=new RepositoryGroupViewModel(repositoryGroup,false,self.repositoryGroupsViewModel);
+
+ activateRepositoryGroupEditTab();
+ ko.applyBindings(repositoryGroupViewModel,mainContent.find("#repository-groups-edit" ).get(0));
+ repositoryGroupViewModel.renderSortableChoosed(self.repositoryGroupsViewModel);
+ repositoryGroupViewModel.renderSortableAvailables(self.repositoryGroupsViewModel);
+ }
+ if ($(e.target).attr("href")=="#repository-groups-view") {
+ mainContent.find("#repository-groups-view-tabs-li-edit a").html($.i18n.prop("add"));
+ clearUserMessages();
+ }
+
+ });
+
+ if(successFn){
+ successFn(self.repositoryGroupsViewModel);
+ }
+
+ }
+ }
+ );
+
+ }
+ });
+ });
+
+ this.mapManagedRepositoriesToRepositoryGroup=function(repositoryGroup){
+ $.log("mapManagedRepositoriesToRepositoryGroup");
+ var managedRepositories=new Array();
+ if (!repositoryGroup.repositories()) {
+ repositoryGroup.repositories(new Array());
+ return managedRepositories;
+ }
+ for(var i=0;i<repositoryGroup.repositories().length;i++){
+ managedRepositories.push(self.repositoryGroupsViewModel.findManagedRepository(repositoryGroup.repositories()[i]));
+ }
+ $.log("end mapManagedRepositoriesToRepositoryGroup");
+ return managedRepositories;
+ }
+
+ }
+
+
+
+ activateRepositoryGroupsGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#repository-groups-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#repository-groups-view-tabs li").removeClass("active");
+
+ mainContent.find("#repository-groups-view").addClass("active");
+ mainContent.find("#repository-groups-view-tabs-li-grid").addClass("active");
+ mainContent.find("#repository-groups-view-tabs-li-edit a").html($.i18n.prop("add"));
+
+ }
+
+ activateRepositoryGroupEditTab=function(){
+ var mainContent = $("#main-content");
+
+ mainContent.find("#repository-groups-view-tabs-content div[class*='tab-pane']").removeClass("active");
+ mainContent.find("#repository-groups-view-tabs li").removeClass("active");
+
+ mainContent.find("#repository-groups-edit").addClass("active");
+ mainContent.find("#repository-groups-view-tabs-li-edit").addClass("active");
+ }
+
+ mapRepositoryGroups=function(data){
+ if (data == null){
+ return new Array();
+ }
+ var mappedRepositoryGroups = $.map(data, function(item) {
+ return mapRepositoryGroup(item);
+ });
+ return mappedRepositoryGroups;
+ }
+
+ mapRepositoryGroup=function(data){
+ return new RepositoryGroup(data.id, mapStringArray(data.repositories));
+ }
+
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js
new file mode 100644
index 000000000..5c7175241
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js
@@ -0,0 +1,2102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("archiva.search",["jquery","i18n","jquery.tmpl","select2","knockout","knockout.simpleGrid","jqueryFileTree","prettify"]
+, function(jquery,i18n,jqueryTmpl,select2,ko,koSimpleGrid) {
+
+ //-----------------------------------------
+ // browse part
+ //-----------------------------------------
+
+ BrowseViewModel=function(browseResultEntries,parentBrowseViewModel,groupId,repositoryId,feedsUrl){
+ var self=this;
+ this.browseResultEntries=browseResultEntries;
+ this.parentBrowseViewModel=parentBrowseViewModel;
+ this.groupId=groupId;
+ this.repositoryId=repositoryId;
+ this.feedsUrl=feedsUrl;
+ displayGroupId=function(groupId){
+ $.log("BrowseViewModel#displayGroupId,self.repositoryId:"+self.repositoryId);
+ if(self.repositoryId){
+ window.sammyArchivaApplication.setLocation("#browse~"+self.repositoryId+"/"+groupId);
+ } else {
+ window.sammyArchivaApplication.setLocation("#browse/"+groupId);
+ }
+ }
+ displayParentGroupId=function(){
+ $.log("called displayParentGroupId groupId:"+self.parentBrowseViewModel.groupId);
+ // if null parent is root level
+ if (self.parentBrowseViewModel.groupId){
+ displayGroupDetail(self.parentBrowseViewModel.groupId,self.parentBrowseViewModel);
+ } else {
+ browseRoot();
+ }
+ }
+
+ breadCrumbEntries=function(){
+ // root level ?
+ if (!self.parentBrowseViewModel){
+ return [];
+ }
+ return calculateBreadCrumbEntries(self.groupId);
+ }
+
+ displayProjectEntry=function(id){
+
+ // value org.apache.maven/maven-archiver
+ // artifactId can contains .
+ // value org.apache.aries/org.apache.aries.util
+ // split this org.apache.maven and maven-archiver
+ var artifactId = id.substring((self.groupId+'.').length,id.length);//.split(".");
+ var selectedRepo=getSelectedBrowsingRepository();
+
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+self.groupId+"/"+artifactId;
+
+ window.sammyArchivaApplication.setLocation(location);
+
+ }
+
+ displayEntry=function(value){
+ if (self.groupId){
+ return value.substr(self.groupId.length+1,value.length-self.groupId.length);
+ }
+ return value;
+ }
+
+ deleteKarma=function(){
+ return hasKarma('archiva-delete-artifact');
+ }
+
+ deleteProject=function(groupId,projectId){
+ $.log("deleteProject:"+groupId+"/"+projectId);
+
+ var repoId=getSelectedBrowsingRepository();
+ if(!repoId){
+ var escapedGroupId=escapeDot(groupId );
+ var selected = $("#main-content" ).find("#delete-"+escapedGroupId );
+ selected.attr("data-content",$.i18n.prop('projectId.delete.missing.repoId'))
+ selected.popover({
+ html:true,
+ template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>',
+ placement:'top',
+ trigger:'manual'});
+ selected.popover('show');
+ selected.mouseover(function(){
+ selected.popover("destroy");
+ });
+ return;
+ }
+
+
+ var previousHash=getUrlHash();
+ $.log("previousHash:"+previousHash);
+ openDialogConfirm(function(){
+ $("#dialog-confirm-modal-ok").button('loading');
+ $.ajax({
+ url:"restServices/archivaServices/repositoriesService/project/"+repoId+"/"+groupId+"/"+projectId,
+ type:"DELETE",
+ dataType:"json",
+ success:function(data){
+ window.sammyArchivaApplication.setLocation(previousHash);
+ refreshContent();
+ displaySuccessMessage( $.i18n.prop("projectId.deleted", groupId,projectId));
+ },
+ error:function(data){
+ displayRestError(data,"user-messages");
+ },
+ complete:function(){
+ $("#dialog-confirm-modal-ok").button('reset');
+ closeDialogConfirm();
+ }
+ });
+ }, $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('projectId.delete.confirm.title'),
+ $.i18n.prop('projectId.delete.confirm.save',groupId,projectId));
+ }
+ }
+
+ deleteGroupId=function(groupId){
+
+ var repoId=getSelectedBrowsingRepository();
+ if(!repoId){
+ var escapedGroupId=escapeDot(groupId );
+ var selected = $("#main-content" ).find("#delete-"+escapedGroupId );
+ selected.attr("data-content",$.i18n.prop('groupId.delete.missing.repoId'))
+ selected.popover({
+ html:true,
+ template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>',
+ placement:'top',
+ trigger:'manual'});
+ selected.popover('show');
+ selected.mouseover(function(){
+ selected.popover("destroy");
+ });
+ return;
+ }
+ var previousHash=getUrlHash();
+ $.log("previousHash:"+previousHash);
+ openDialogConfirm(function(){
+ $("#dialog-confirm-modal-ok").button('loading');
+ $.ajax({
+ url:"restServices/archivaServices/repositoriesService/deleteGroupId?groupId="+groupId+"&repositoryId="+repoId,
+ type:"GET",
+ dataType:"json",
+ success:function(data){
+ window.sammyArchivaApplication.setLocation(previousHash);
+ refreshContent();
+ displaySuccessMessage( $.i18n.prop("groupdId.deleted", groupId));
+ },
+ error:function(data){
+ displayRestError(data,"user-messages");
+ },
+ complete:function(){
+ $("#dialog-confirm-modal-ok").button('reset');
+ closeDialogConfirm();
+ }
+ });
+ }, $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('groupId.delete.confirm.title'),
+ $.i18n.prop('groupId.delete.confirm.save',groupId));
+
+ }
+
+ calculateBreadCrumbEntries=function(groupId){
+ if (!groupId){
+ return [];
+ }
+ var splitted = groupId.split(".");
+ var breadCrumbEntries=[];
+ var curGroupId="";
+ for (var i=0;i<splitted.length;i++){
+ curGroupId+=splitted[i];
+ breadCrumbEntries.push(new BreadCrumbEntry(curGroupId,splitted[i]));
+ curGroupId+="."
+ }
+ return breadCrumbEntries;
+ }
+
+ displayGroupDetail=function(groupId,parentBrowseViewModel,restUrl,repositoryId,feedsUrl){
+ var mainContent = $("#main-content");
+ mainContent.find("#browse_artifact_detail").hide();
+ var browseResult=mainContent.find("#browse_result");
+ browseResult.show();
+ mainContent.find("#browse_artifact" ).hide();
+ var browseBreadCrumb=mainContent.find("#browse_breadcrumb");
+ mainContent.find("#main_browse_result_content").hide( "slide", {}, 300,
+ function(){
+ browseResult.html(mediumSpinnerImg());
+ browseBreadCrumb.html(smallSpinnerImg());
+ mainContent.find("#main_browse_result_content").show();
+ var url = "";
+ if (!restUrl) {
+ url="restServices/archivaServices/browseService/browseGroupId/"+encodeURIComponent(groupId);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ url+="?repositoryId="+selectedRepo;
+ }
+ } else {
+ url=restUrl;
+ }
+
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var browseResultEntries = mapBrowseResultEntries(data);
+ var browseViewModel = new BrowseViewModel(browseResultEntries,parentBrowseViewModel,groupId,repositoryId,feedsUrl);
+ ko.applyBindings(browseViewModel,browseBreadCrumb.get(0));
+ ko.applyBindings(browseViewModel,browseResult.get(0));
+ enableAutocompleBrowse(groupId);
+ }
+ });
+ }
+ );
+ }
+
+ ArtifactDetailViewModel=function(groupId,artifactId){
+ var self=this;
+ this.versions=ko.observableArray([]);
+ this.projectVersionMetadata=null;
+ this.groupId=groupId;
+ this.artifactId=artifactId;
+ breadCrumbEntries=function(){
+ var entries = calculateBreadCrumbEntries(self.groupId);
+ entries.push(new BreadCrumbEntry("foo",self.artifactId));
+ return entries;
+ }
+ displayArtifactInfo=function(){
+ if ($("#main-content").find("#artifact-info:visible" ).length>0) {
+ $("#main-content").find("#artifact-info" ).hide();
+ } else {
+ $("#main-content").find("#artifact-info" ).show();
+ }
+ }
+
+ deleteVersion=function(version){
+ var repoId=getSelectedBrowsingRepository();
+ if(!repoId){
+ var escapedVersion=escapeDot(version);
+ var selected = $("#main-content" ).find("#delete-"+escapedVersion );
+ selected.attr("data-content",$.i18n.prop('version.delete.missing.repoId'))
+ selected.popover({
+ html:true,
+ template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>',
+ placement:'top',
+ trigger:'manual'});
+ selected.popover('show');
+ selected.mouseover(function(){
+ selected.popover("destroy");
+ });
+ return;
+ }
+
+ clearUserMessages();
+ var artifact = new Artifact(repoId,null,self.groupId,self.artifactId,repoId,version);
+ openDialogConfirm(function(){
+ var url = "restServices/archivaServices/repositoriesService/projectVersion/"+repoId;
+ url+="/"+encodeURIComponent(self.groupId)+"/"+encodeURIComponent(self.artifactId);
+ url+="/"+encodeURIComponent(version);
+ $("#dialog-confirm-modal-ok").button('loading');
+ $.ajax({
+ url:url,
+ type:"DELETE",
+ success:function(data){
+ self.versions.remove(version);
+ refreshContent();
+ displaySuccessMessage( $.i18n.prop('artifact.deleted'));
+ },
+ error:function(data){
+ displayRestError( data,"user-messages");
+ },
+ complete:function(){
+ $("#dialog-confirm-modal-ok").button('reset');
+ closeDialogConfirm();
+ }
+ });
+ }, $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('artifact.delete.confirm.title'),
+ $.i18n.prop('artifact.delete.confirm.save'));
+ }
+
+ displayArtifactVersionDetail=function(version){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+version;
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ displayGroupId=function(groupId){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#browse";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId;
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ }
+
+ displayArtifactVersionDetailViewModel=function(groupId,artifactId,version){
+ $.log("displayArtifactVersionDetailViewModel:"+groupId+":"+artifactId+":"+version);
+ var artifactVersionDetailViewModel = new ArtifactVersionDetailViewModel (groupId,artifactId,version)
+ artifactVersionDetailViewModel.display();
+ }
+
+
+ ArtifactVersionDetailViewModel=function(groupId,artifactId,version,repositoryId){
+ var mainContent = $("#main-content");
+ var self=this;
+ this.groupId=groupId;
+ this.artifactId=artifactId;
+ this.version=version;
+ this.projectVersionMetadata=null;
+ this.entries=ko.observableArray([]);
+ this.repositoryId=repositoryId;
+
+ displayGroupId=function(groupId){
+ var location ="#browse";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+groupId;
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ displayParent=function(){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+self.projectVersionMetadata.mavenFacet.parent.groupId+"/"+self.projectVersionMetadata.mavenFacet.parent.artifactId;
+ location+="/"+self.projectVersionMetadata.mavenFacet.parent.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+
+ }
+
+ breadCrumbEntries=function(){
+ var entries = calculateBreadCrumbEntries(self.groupId);
+ var artifactBreadCrumbEntry = new BreadCrumbEntry(self.groupId,self.artifactId);
+ artifactBreadCrumbEntry.artifactId=self.artifactId;
+ artifactBreadCrumbEntry.artifact=true;
+ entries.push(artifactBreadCrumbEntry);
+ entries.push(new BreadCrumbEntry("foo",self.version));
+ return entries;
+ }
+
+ this.display=function(afterCallbackFn){
+ mainContent.find("#browse_breadcrumb").hide("slide", {}, 300,function(){
+ mainContent.find("#browse_artifact").hide("slide", {}, 300,function(){
+
+ mainContent.find("#browse_artifact_detail").show();
+ mainContent.find("#browse_artifact_detail").html(mediumSpinnerImg());
+ mainContent.find("#browse_breadcrumb" ).show();
+ mainContent.find("#browse_breadcrumb" ).html(mediumSpinnerImg());
+ var metadataUrl="restServices/archivaServices/browseService/projectVersionMetadata/"+encodeURIComponent(groupId)+"/"+encodeURIComponent(artifactId);
+ metadataUrl+="/"+encodeURIComponent(version);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ metadataUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+
+ $.ajax(metadataUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ self.projectVersionMetadata=mapProjectVersionMetadata(data);
+
+ //pagination for dependencies
+ self.projectVersionMetadata.dependencies=ko.observableArray(self.projectVersionMetadata.dependencies?self.projectVersionMetadata.dependencies:[]);
+ self.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.projectVersionMetadata.dependencies(),
+ columns: [],
+ pageSize: 7,
+ gridUpdateCallBack: function(){
+ // nope
+ }
+ });
+
+ ko.applyBindings(self,mainContent.find("#browse_artifact_detail" ).get(0));
+ ko.applyBindings(self,mainContent.find("#browse_breadcrumb" ).get(0));
+ mainContent.find("#browse-autocomplete" ).hide();
+ mainContent.find("#browse-autocomplete-divider" ).hide();
+
+ //calculate tree content
+ var treeContentDiv=mainContent.find("#artifact-details-dependency-tree-content" );
+ if( $.trim(treeContentDiv.html()).length<1){
+ treeContentDiv.html(mediumSpinnerImg());
+ var treeDependencyUrl="restServices/archivaServices/browseService/treeEntries/"+encodeURIComponent(groupId);
+ treeDependencyUrl+="/"+encodeURIComponent(artifactId);
+ treeDependencyUrl+="/"+encodeURIComponent(version);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ treeDependencyUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $.ajax(treeDependencyUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var treeEntries = mapTreeEntries(data);
+ treeContentDiv.html($("#dependency_tree_tmpl" ).tmpl({treeEntries: treeEntries}));
+ }
+ });
+ }
+
+
+ mainContent.find("#artifact-details-tabs").on('show', function (e) {
+ $.log("e.target:"+e.target);
+ if ($(e.target).attr("data-target")=="#artifact-details-info-content") {
+ var location ="#artifact";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
+
+ if ($(e.target).attr("data-target")=="#artifact-details-dependencies-content") {
+ var location ="#artifact-dependencies";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
+ if ($(e.target).attr("data-target")=="#artifact-details-dependency-tree-content") {
+ var location ="#artifact-dependency-tree";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
+ if ($(e.target).attr("data-target")=="#artifact-details-used-by-content") {
+ var location ="#artifact-used-by";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
+ if ($(e.target).attr("href")=="#artifact-details-metadatas-content") {
+ var location ="#artifact-metadatas";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
+ if ($(e.target).attr("href")=="#artifact-details-download-content") {
+ var location ="#artifact-details-download-content";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+ if ($(e.target).attr("href")=="#artifact-details-files-content") {
+ var location ="#artifact-details-files-content";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+ if ($(e.target).attr("href")=="#artifact-details-mailing-list-content") {
+ var location ="#artifact-mailing-list";
+ if (self.repositoryId){
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+ });
+ if(afterCallbackFn){
+ afterCallbackFn(self);
+ }
+ }
+
+ });
+
+ });
+ });
+ }
+
+
+
+ displayGroup=function(groupId){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#browse";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ displayArtifactDetailView=function(groupId, artifactId){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId+"/"+artifactId;
+
+ window.sammyArchivaApplication.setLocation(location);
+
+ }
+
+ displayArtifactVersionDetailViewModel=function(groupId,artifactId,version){
+ $.log("ArtifactVersionDetailViewModel#displayArtifactVersionDetailViewModel:"+groupId+":"+artifactId+":"+version);
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId+"/"+artifactId+"/"+version;
+
+ self.groupId=groupId;
+ self.artifactId=artifactId;
+ self.version=version;
+ $("#main-content" ).find("#browse_artifact_detail" ).empty();
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+
+ addProperty=function(){
+ self.entries.push(new MetadataEntry("","",true));
+ }
+
+ deleteProperty=function(entry){
+ var metadatasUrl="restServices/archivaServices/browseService/metadata/"+encodeURIComponent(groupId);
+ metadatasUrl+="/"+encodeURIComponent(artifactId);
+ metadatasUrl+="/"+encodeURIComponent(version);
+ metadatasUrl+="/"+encodeURIComponent(entry.key());
+ var selectedRepo=getSelectedBrowsingRepository();
+
+ if(!selectedRepo){
+ clearUserMessages();
+ displayErrorMessage($.i18n.prop('repository.selected.missing'));
+ return;
+ }
+
+ metadatasUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+
+ $.ajax(metadatasUrl, {
+ type: "DELETE",
+ dataType: 'json',
+ success: function(data) {
+ clearUserMessages();
+ displaySuccessMessage( $.i18n.prop("artifact.metadata.deleted"));
+ self.entries.remove(entry);
+ }
+ });
+
+ }
+
+ hasSavePropertyKarma=function(){
+ return hasKarma("archiva-add-metadata");
+ }
+
+ hasDeletePropertyKarma=function(){
+ return hasKarma("archiva-delete-metadata");
+ }
+
+ saveProperty=function(entry){
+ if($.trim(entry.key() ).length<1){
+ clearUserMessages();
+ displayErrorMessage( $.i18n.prop("artifact.metadata.key.mandatory"));
+ return;
+ }
+ if($.trim(entry.value() ).length<1){
+ clearUserMessages();
+ displayErrorMessage( $.i18n.prop("artifact.metadata.value.mandatory"));
+ return;
+ }
+
+ var selectedRepo=getSelectedBrowsingRepository();
+
+ if(!selectedRepo){
+ clearUserMessages();
+ displayErrorMessage($.i18n.prop('repository.selected.missing'));
+ return;
+ }
+
+ var metadatasUrl="restServices/archivaServices/browseService/metadata/"+encodeURIComponent(groupId);
+ metadatasUrl+="/"+encodeURIComponent(artifactId);
+ metadatasUrl+="/"+encodeURIComponent(version);
+ metadatasUrl+="/"+encodeURIComponent(entry.key());
+ metadatasUrl+="/"+encodeURIComponent(entry.value());
+
+ if (selectedRepo){
+ metadatasUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $.ajax(metadatasUrl, {
+ type: "PUT",
+ dataType: 'json',
+ success: function(data) {
+ clearUserMessages();
+ displaySuccessMessage( $.i18n.prop("artifact.metadata.added"));
+ entry.editable(false);
+ entry.modified(false);
+ }
+ });
+ }
+
+
+ this.gridMetatadasViewModel = new ko.simpleGrid.viewModel({
+ data: self.entries,
+ pageSize: 10
+ });
+
+ }
+
+ ArtifactDetailsDownloadViewModel=function(artifacts, artifactVersionDetailViewModel){
+ this.artifacts=ko.observableArray(artifacts);
+ this.artifactVersionDetailViewModel=artifactVersionDetailViewModel;
+ var self=this;
+ deleteArtifact=function(artifact){
+
+ clearUserMessages();
+
+ openDialogConfirm(function(){
+ $("#dialog-confirm-modal-ok").button('loading');
+ $.ajax({
+ url:"restServices/archivaServices/repositoriesService/deleteArtifact",
+ type:"POST",
+ dataType:"json",
+ contentType: 'application/json',
+ data: ko.toJSON(artifact),
+ success:function(data){
+ self.artifacts.remove(artifact);
+ displaySuccessMessage( $.i18n.prop('artifact.deleted'));
+ $("#main-content").find("#artifact-details-download-content" ).html(smallSpinnerImg());
+ // reload datas from server
+ var artifactDownloadInfosUrl = "restServices/archivaServices/browseService/artifactDownloadInfos/"+encodeURIComponent(self.artifactVersionDetailViewModel.groupId);
+ artifactDownloadInfosUrl+="/"+encodeURIComponent(self.artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(self.artifactVersionDetailViewModel.version);
+ artifactDownloadInfosUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+
+ $.get(artifactDownloadInfosUrl,function(data){
+ self.artifacts(mapArtifacts(data));
+ });
+
+ },
+ error:function(data){
+ displayRestError(data,"user-messages");
+ },
+ complete:function(){
+ $("#dialog-confirm-modal-ok").button('reset');
+ closeDialogConfirm();
+ }
+ });
+ }, $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('artifact.delete.confirm.title'),
+ $.i18n.prop('artifact.delete.confirm.save'));
+
+ }
+
+ this.deleteKarma = hasKarma('archiva-delete-artifact');
+
+ }
+
+ displayArtifactDownloadContent=function(artifactVersionDetailViewModel){
+ var mainContent=$("#main-content");
+ mainContent.find("#artifact-details-download-content" ).html(smallSpinnerImg());
+ var artifactDownloadInfosUrl = "restServices/archivaServices/browseService/artifactDownloadInfos/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ artifactDownloadInfosUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(artifactVersionDetailViewModel.version);
+ artifactDownloadInfosUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ $.get(artifactDownloadInfosUrl,function(data){
+ var artifactDetailsDownloadViewModel = new ArtifactDetailsDownloadViewModel(mapArtifacts(data),artifactVersionDetailViewModel);
+ mainContent.find("#artifact-details-download-content" ).attr("data-bind",'template:{name:"artifact-details-download-content_tmpl"}');
+ ko.applyBindings(artifactDetailsDownloadViewModel,mainContent.find("#artifact-details-download-content" ).get(0));
+
+
+ mainContent.find("#artifact-download-list-files li img" ).on("click",function(){
+ mainContent.find("#artifact_content_tree").empty();
+ var contentText = mainContent.find("#artifact-content-text" );
+ contentText.empty();
+ var idValue = $(this ).attr("id");
+ var splitted = idValue.split(":");
+
+ var classifier=splitted[0];
+ var version=splitted[1];
+ var type = splitted[2];
+
+ $.log("click:" + idValue + " -> " + classifier + ":" + type + ":" + version);
+ if (type=="pom"){
+ $.log("show pom");
+ var pomContentUrl = "restServices/archivaServices/browseService/artifactContentText/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ pomContentUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ pomContentUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ pomContentUrl+="&t=pom";
+ contentText.html(mediumSpinnerImg());
+ $.ajax({
+ url: pomContentUrl,
+ success: function(data) {
+ var text = data.content.replace(/</g,'&lt;');
+ text=text.replace(/>/g,"&gt;");
+ contentText.html(text);
+ prettyPrint();
+ // olamy do not move to anchor to not loose nav history
+ //goToAnchor("artifact-content-text-header");
+ //window.location.href=window.location+"#artifact-content-text-header";
+ }
+ });
+ return;
+ }
+ var entriesUrl = "restServices/archivaServices/browseService/artifactContentEntries/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ entriesUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ entriesUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ if(classifier){
+ entriesUrl+="&c="+encodeURIComponent(classifier);
+ }
+ $("#main-content").find("#artifact_content_tree").fileTree({
+ script: entriesUrl,
+ root: ""
+ },function(file) {
+ $.log("file:"+file.substringBeforeLast("/")+',classifier:'+classifier);
+ var fileContentUrl = "restServices/archivaServices/browseService/artifactContentText/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ fileContentUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ fileContentUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ if(type){
+ fileContentUrl+="&t="+encodeURIComponent(type);
+ }
+ if(classifier){
+ fileContentUrl+="&c="+encodeURIComponent(classifier);
+ }
+ fileContentUrl+="&p="+encodeURIComponent(file.substringBeforeLast("/"));
+ $.ajax({
+ url: fileContentUrl,
+ success: function(data) {
+ var text = data.content.replace(/</g,'&lt;');
+ text=text.replace(/>/g,"&gt;");
+ mainContent.find("#artifact-content-text" ).html(smallSpinnerImg());
+ mainContent.find("#artifact-content-text" ).html(text);
+ prettyPrint();
+ // olamy do not move to anchor to not loose nav history
+ //goToAnchor("artifact-content-text-header");
+ //window.location.href=window.location+"#artifact-content-text-header";
+ }
+ });
+ }
+ );
+ });
+
+
+ });
+ return;
+ }
+
+ displayArtifactFilesContent=function(artifactVersionDetailViewModel){
+ var mainContent = $("#main-content");
+ mainContent.find("#artifact-details-files-content" ).html(smallSpinnerImg());
+ var artifactDownloadInfosUrl = "restServices/archivaServices/browseService/artifactDownloadInfos/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ artifactDownloadInfosUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(artifactVersionDetailViewModel.version);
+ artifactDownloadInfosUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+
+ $.get(artifactDownloadInfosUrl,function(data){
+ $("#artifact-details-files-content" ).html($("#artifact-details-files-content_tmpl").tmpl({artifactDownloadInfos:data}));
+ mainContent.find("#artifact-content-list-files li" ).on("click",function(){
+ mainContent.find("#artifact_content_tree").empty();
+ var contentText = mainContent.find("#artifact-content-text" );
+ contentText.empty();
+ var idValue = $(this ).attr("id");
+ var splitted = idValue.split(":");
+
+ var classifier=splitted[0];
+ var version=splitted[1];
+ var type = splitted[2];
+
+ $.log("click:" + idValue + " -> " + classifier + ":" + type + ":" + version);
+ if (type=="pom"){
+ $.log("show pom");
+ var pomContentUrl = "restServices/archivaServices/browseService/artifactContentText/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ pomContentUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ pomContentUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ pomContentUrl+="&t=pom";
+ contentText.html(mediumSpinnerImg());
+ $.ajax({
+ url: pomContentUrl,
+ success: function(data) {
+ var text = data.content.replace(/</g,'&lt;');
+ text=text.replace(/>/g,"&gt;");
+ contentText.html(text);
+ prettyPrint();
+ // olamy do not move to anchor to not loose nav history
+ //goToAnchor("artifact-content-text-header");
+ //window.location.href=window.location+"#artifact-content-text-header";
+ }
+ });
+ return;
+ }
+ var entriesUrl = "restServices/archivaServices/browseService/artifactContentEntries/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ entriesUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ entriesUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ if(classifier){
+ entriesUrl+="&c="+encodeURIComponent(classifier);
+ }
+ $("#main-content").find("#artifact_content_tree").fileTree({
+ script: entriesUrl,
+ root: ""
+ },function(file) {
+ $.log("file:"+file.substringBeforeLast("/")+',classifier:'+classifier);
+ var fileContentUrl = "restServices/archivaServices/browseService/artifactContentText/"+encodeURIComponent(artifactVersionDetailViewModel.groupId);
+ fileContentUrl+="/"+encodeURIComponent(artifactVersionDetailViewModel.artifactId)+"/"+encodeURIComponent(version);
+ fileContentUrl+="?repositoryId="+encodeURIComponent(getSelectedBrowsingRepository());
+ if(type){
+ fileContentUrl+="&t="+encodeURIComponent(type);
+ }
+ if(classifier){
+ fileContentUrl+="&c="+encodeURIComponent(classifier);
+ }
+ fileContentUrl+="&p="+encodeURIComponent(file.substringBeforeLast("/"));
+ $.ajax({
+ url: fileContentUrl,
+ success: function(data) {
+ var text = data.content.replace(/</g,'&lt;');
+ text=text.replace(/>/g,"&gt;");
+ mainContent.find("#artifact-content-text" ).html(smallSpinnerImg());
+ mainContent.find("#artifact-content-text" ).html(text);
+ prettyPrint();
+ // olamy do not move to anchor to not loose nav history
+ //goToAnchor("artifact-content-text-header");
+ //window.location.href=window.location+"#artifact-content-text-header";
+ }
+ });
+ }
+ );
+ });
+
+ });
+
+ }
+
+ ArtifactContentEntry=function(path,file,depth){
+ this.path=path;
+ this.file=file;
+ this.depth=depth;
+ }
+
+ mapArtifactContentEntries=function(data){
+ if(data==null){
+ return [];
+ }
+ if ( $.isArray(data)){
+ return $.map(data,function(e){
+ return new ArtifactContentEntry(e.path,e.file,e.depth);
+ })
+ }
+ return new ArtifactContentEntry(data.path,data.file,data.depth);
+ }
+
+ MetadataEntry=function(key,value,editable){
+ var self=this;
+ this.key=ko.observable(key);
+ this.key.subscribe(function(newValue){self.modified(true)});
+ this.value=ko.observable(value);
+ this.value.subscribe(function(newValue){self.modified(true)});
+ this.editable=ko.observable(editable);
+ this.modified=ko.observable(false)
+ }
+
+ TreeEntry=function(artifact,childs){
+ this.artifact=artifact;
+ this.childs=childs;
+ }
+
+ mapTreeEntries=function(data){
+ if (data==null){
+ return [];
+ }
+ return $.map(data,function(e) {
+ return new TreeEntry(mapArtifact(e.artifact),mapTreeEntries(e.childs));
+ })
+ }
+
+ /**
+ * display groupId note #main-content must contains browse-tmpl
+ * @param groupId
+ */
+ generalDisplayGroup=function(groupId) {
+ $.log("generalDisplayGroup");
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#browse";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ /**
+ * display groupId/artifactId detail note #main-content must contains browse-tmpl
+ * @param groupId
+ * @param artifactId
+ */
+ generalDisplayArtifactDetailView=function(groupId, artifactId){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId+"/"+artifactId;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ /**
+ * display groupId/artifactId/version detail note #main-content must contains browse-tmpl
+ * @param groupId
+ * @param artifactId
+ * @param version
+ */
+ generalDisplayArtifactVersionDetailViewModel=function(groupId,artifactId,version){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId+"/"+artifactId+"/"+version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ goToBrowseArtifactDetail=function(groupId, artifactId,repositoryId){
+ $.log("goToBrowseArtifactDetail:"+groupId+":"+artifactId);
+ //displayBrowseGroupId(groupId,null,null);
+ displayArtifactDetail(groupId,artifactId,null,null,repositoryId);
+ }
+
+ /**
+ *
+ */
+ displayBrowseGroupId=function(groupId,repositoryId,artifactId){
+ clearUserMessages();
+ $.log("displayBrowseGroupId:"+groupId+":"+repositoryId);
+ userRepositoriesCall(
+ function(data){
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+
+ var mainContent = $("#main-content");
+ mainContent.html($("#browse-tmpl" ).tmpl());
+ mainContent.find("#browse_result").html(mediumSpinnerImg());
+ var parentBrowseViewModel=new BrowseViewModel(null,null,null,repositoryId);
+ var url="restServices/archivaServices/browseService/browseGroupId/"+encodeURIComponent(groupId);
+ var feedsUrl=applicationUrl?applicationUrl:window.location.toString().substringBeforeLast("/").substringBeforeLast("/");
+ if (repositoryId){
+ url+="?repositoryId="+repositoryId;
+ // we are browsing a groupId so 2 substringBeforeLast
+
+ feedsUrl+="/feeds/"+repositoryId;
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:repositoryId,feedsUrl:feedsUrl}));
+ }else{
+ feedsUrl+="/feeds";
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:"",feedsUrl:null}));
+ }
+ displayGroupDetail(groupId,parentBrowseViewModel,url,repositoryId,feedsUrl);
+
+ }
+ });
+
+ }
+ );
+
+ }
+
+ goToArtifactDetail=function(groupId,artifactId){
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+groupId+"/"+artifactId;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ /**
+ *
+ * @param groupId
+ * @param artifactId
+ * @param parentBrowseViewModel
+ * @param restUrl
+ * @param repositoryId
+ */
+ displayArtifactDetail=function(groupId,artifactId,parentBrowseViewModel,restUrl,repositoryId){
+ $.log("displayArtifactDetail:"+groupId+":"+artifactId);
+ var artifactDetailViewModel=new ArtifactDetailViewModel(groupId,artifactId);
+ var mainContent = $("#main-content");
+
+ mainContent.html($("#browse-tmpl" ).tmpl());
+
+ userRepositoriesCall(
+ function(data){
+
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+
+ var feedsUrl=applicationUrl?applicationUrl:window.location.toString().substringBeforeLast("/").substringBeforeLast("/");
+ feedsUrl+="/feeds/"+repositoryId;
+
+
+ if(repositoryId){
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:repositoryId,feedsUrl:feedsUrl}));
+ } else {
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:'',feedsUrl:null}));
+ }
+
+ mainContent.find("#browse_artifact_detail" ).hide();
+ mainContent.find("#browse_result").hide();
+ mainContent.find("#main_browse_result_content").hide("slide", {}, 300,function(){
+ mainContent.find("#browse_breadcrumb").html(smallSpinnerImg());
+ mainContent.find("#browse_artifact").show();
+ mainContent.find("#browse_artifact").html(mediumSpinnerImg());
+ mainContent.find("#main_browse_result_content").show();
+ var metadataUrl="restServices/archivaServices/browseService/projectVersionMetadata/"+encodeURIComponent(groupId)+"/"+encodeURIComponent(artifactId);
+ var versionsListUrl="restServices/archivaServices/browseService/versionsList/"+encodeURIComponent(groupId)+"/"+encodeURIComponent(artifactId);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ metadataUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ versionsListUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $.ajax(metadataUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ artifactDetailViewModel.projectVersionMetadata=mapProjectVersionMetadata(data);
+ $.ajax(versionsListUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ artifactDetailViewModel.versions=ko.observableArray( mapVersionsList(data));
+ ko.applyBindings(artifactDetailViewModel,mainContent.find("#browse_artifact").get(0));
+ ko.applyBindings(artifactDetailViewModel,mainContent.find("#browse_breadcrumb").get(0));
+
+ }
+ });
+ }
+ });
+ });
+ }})
+ });
+
+ }
+
+ browseRoot=function(){
+ var selectedRepo=getSelectedBrowsingRepository();
+
+ if(selectedRepo) {
+ window.sammyArchivaApplication.setLocation("#browse~"+selectedRepo);
+ } else {
+ window.sammyArchivaApplication.setLocation("#browse");
+ }
+ }
+
+ /**
+ * call from menu entry to display root level
+ * @param freshView redisplay everything
+ * @param repositoryId if any repository selected
+ */
+ displayBrowse=function(freshView,repositoryId){
+ screenChange();
+ var mainContent = $("#main-content");
+ if(freshView){
+ mainContent.html($("#browse-tmpl" ).tmpl());
+ }
+ mainContent.find("#browse_artifact_detail").hide();
+ mainContent.find("#browse_artifact" ).hide();
+ mainContent.find("#browse_result").html(mediumSpinnerImg());
+
+
+ userRepositoriesCall(
+ function(data) {
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+
+ var feedsUrl=applicationUrl?applicationUrl:window.location.toString().substringBeforeLast("/").substringBeforeLast("/");
+ feedsUrl+="/feeds/"+repositoryId;
+
+
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:repositoryId,feedsUrl:feedsUrl}));
+ var url="restServices/archivaServices/browseService/rootGroups";
+ if(repositoryId){
+ url+="?repositoryId="+repositoryId;
+ }
+ $.ajax(url, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var browseResultEntries = mapBrowseResultEntries(data);
+ var browseViewModel = new BrowseViewModel(browseResultEntries,null,null,repositoryId);
+ ko.applyBindings(browseViewModel,mainContent.find("#browse_breadcrumb").get(0));
+ ko.applyBindings(browseViewModel,mainContent.find("#browse_result").get(0));
+ enableAutocompleBrowse();
+ }
+ });
+
+ }}
+ )
+
+ }
+ )
+
+ }
+
+ changeBrowseRepository=function(){
+ var selectedRepository=getSelectedBrowsingRepository();
+ // #browse~internal/org.apache.maven
+ // or #artifact~snapshots/org.apache.maven.plugins/maven-compiler-plugin
+ var currentHash=window.location.hash;
+ $.log("currentHash:"+currentHash);
+ var newLocation = currentHash.substringBeforeFirst("/");
+ // maybe the current hash contains a repositoryId so remove it
+ if (newLocation.indexOf("~")>-1){
+ newLocation=currentHash.substringBeforeFirst("~");
+ }
+ if (selectedRepository){
+ newLocation+="~"+selectedRepository;
+ }
+ newLocation += currentHash.substringAfterFirst("/");
+ // do we have extra path after repository ?
+
+ $.log("changeBrowseRepository:"+newLocation);
+ window.sammyArchivaApplication.setLocation(newLocation);
+ }
+
+ getSelectedBrowsingRepository=function(){
+ var selectedOption=$("#main-content").find("#select_browse_repository").find("option:selected" );
+ if (selectedOption.length>0){
+ var repoId=selectedOption.val();
+ return repoId;
+ }
+ return "";
+ }
+
+ enableAutocompleBrowse=function(groupId){
+ $("#select_browse_repository" ).select2({width: "resolve"});
+ // browse-autocomplete
+ var url="restServices/archivaServices/browseService/rootGroups";
+ if (groupId){
+ url="restServices/archivaServices/browseService/browseGroupId/"+encodeURIComponent(groupId);
+ }
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ url+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $( "#main-content").find("#browse-autocomplete" ).autocomplete({
+ minLength: 2,
+ source: function(request, response){
+ var query = "";
+ if (request.term.indexOf('.')<0&&!groupId){
+ // try with rootGroups then filtered
+ $.get(url,
+ function(data) {
+ var browseResultEntries = mapBrowseResultEntries(data);
+
+ var filetered = [];
+ for(var i=0;i<browseResultEntries.length;i++){
+ if (browseResultEntries[i].name.startsWith(request.term)){
+ if (groupId){
+ $.log("groupId:"+groupId+",browseResultEntry.name:"+browseResultEntries[i].name);
+ if (browseResultEntries[i].name.startsWith(groupId)) {
+ filetered.push(browseResultEntries[i]);
+ }
+
+ } else {
+ filetered.push(browseResultEntries[i]);
+ }
+ }
+ }
+ response(filetered);
+
+ }
+ );
+ return;
+ }
+ var dotEnd=request.term.endsWith(".");
+ // org.apache. requets with org.apache
+ // org.apa request with org before last dot and filter response with startsWith
+ if (request.term.indexOf(".")>=0){
+ if (dotEnd){
+ query= groupId?groupId+'.'+request.term.substring(0, request.term.length-1):request.term.substring(0, request.term.length-1);
+ } else {
+ // substring before last
+ query=groupId?groupId+'.'+request.term.substringBeforeLast("."):request.term.substringBeforeLast(".");
+ }
+ } else {
+ query=groupId?groupId:request.term;
+ }
+ var browseUrl="restServices/archivaServices/browseService/browseGroupId/"+encodeURIComponent(query);
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ browseUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
+ }
+ $.get(browseUrl,
+ function(data) {
+ var browseResultEntries = mapBrowseResultEntries(data);
+ if (dotEnd){
+ response(browseResultEntries);
+ } else {
+ var filetered = [];
+ for(var i=0;i<browseResultEntries.length;i++){
+ if (groupId){
+ if (browseResultEntries[i].name.startsWith(groupId+'.'+request.term)){
+ filetered.push(browseResultEntries[i]);
+ }
+ } else {
+ if (browseResultEntries[i].name.startsWith(request.term)){
+ filetered.push(browseResultEntries[i]);
+ }
+ }
+ }
+ response(filetered);
+ }
+ }
+ );
+ },
+ select: function( event, ui ) {
+ $.log("ui.item.label:"+ui.item.name);
+ if (ui.item.project){
+ // value org.apache.maven/maven-archiver
+ // split this org.apache.maven and maven-archiver
+ var id=ui.item.name;
+ var values = id.split(".");
+ var groupId="";
+ for (var i = 0;i<values.length-1;i++){
+ groupId+=values[i];
+ if (i<values.length-2)groupId+=".";
+ }
+ var artifactId=values[values.length-1];
+ goToArtifactDetail(groupId,artifactId);
+ } else {
+ var selectedRepo=getSelectedBrowsingRepository();
+ var location ="#browse";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+ui.item.name;
+ window.sammyArchivaApplication.setLocation(location);
+ }
+ return false;
+ }
+ }).data( "autocomplete" )._renderItem = function( ul, item ) {
+ return $( "<li></li>" )
+ .data( "item.autocomplete", item )
+ .append( groupId ? "<a>" + item.name.substring(groupId.length+1, item.name.length) + "</a>": "<a>" + item.name + "</a>" )
+ .appendTo( ul );
+ };
+ }
+
+ /**
+ *
+ * @param groupId
+ */
+ displayBrowseGroupIdFromAutoComplete=function(groupId){
+ clearUserMessages();
+ var mainContent = $("#main-content");
+ mainContent.find("#browse_result").html(mediumSpinnerImg());
+ var parentBrowseViewModel=new BrowseViewModel(null,null,null);
+ displayGroupDetail(groupId,parentBrowseViewModel,null);
+ }
+
+ displayBrowseArtifactDetail=function(groupId, artifactId){
+ $.log("displayBrowseArtifactDetail");
+ window.sammyArchivaApplication.setLocation("#artifact/"+groupId+"/"+artifactId);
+ }
+
+ mapBrowseResultEntries=function(data){
+ $.log("mapBrowseResultEntries");
+ if (data.browseResultEntries) {
+ return $.isArray(data.browseResultEntries) ?
+ $.map(data.browseResultEntries,function(item){
+ return new BrowseResultEntry(item.name, item.project);
+ } ).sort(function(a, b){return a.name.localeCompare(b.name)}): [data.browseResultEntries];
+ }
+ return [];
+ }
+
+ BrowseResultEntry=function(name,project){
+ this.name=name;
+ this.project=project;
+ }
+
+ BreadCrumbEntry=function(groupId,displayValue){
+ this.groupId=groupId;
+ this.displayValue=displayValue;
+ this.artifactId=null;
+ this.artifact=false;
+ this.version=null;
+ }
+ mapVersionsList=function(data){
+ if (data){
+ if (data.versions){
+ return $.isArray(data.versions)? $.map(data.versions,function(item){return item})
+ :[data.versions];
+ }
+
+ }
+ return [];
+ }
+ mapProjectVersionMetadata=function(data){
+ if (data){
+ var projectVersionMetadata =
+ new ProjectVersionMetadata(data.id,data.url,
+ data.name,data.description,
+ null,null,null,null,null,null,null,data.incomplete);
+
+ if (data.organization){
+ projectVersionMetadata.organization=new Organization(data.organization.name,data.organization.url);
+ }
+ if (data.issueManagement){
+ projectVersionMetadata.issueManagement=
+ new IssueManagement(data.issueManagement.system,data.issueManagement.url);
+ }
+ if (data.scm){
+ projectVersionMetadata.scm=
+ new Scm(data.scm.connection,data.scm.developerConnection,data.scm.url);
+ }
+ if (data.ciManagement){
+ projectVersionMetadata.ciManagement=new CiManagement(data.ciManagement.system,data.ciManagement.url);
+ }
+ if (data.licenses){
+ projectVersionMetadata.licenses=
+ $.isArray(data.licenses) ? $.map(data.licenses,function(item){
+ return new License(item.name,item.url);
+ }):[data.licenses];
+ }
+ if (data.mailingLists){
+ var mailingLists =
+ $.isArray(data.mailingLists) ? $.map(data.mailingLists,function(item){
+ return new MailingList(item.mainArchiveUrl,item.otherArchives,item.name,item.postAddress,
+ item.subscribeAddress,item.unsubscribeAddress);
+ }):[data.mailingLists];
+ projectVersionMetadata.mailingLists=mailingLists;
+ }
+ if (data.dependencies){
+ var dependencies =
+ $.isArray(data.dependencies) ? $.map(data.dependencies,function(item){
+ return new Dependency(item.classifier,item.optional,item.scope,item.systemPath,item.type,
+ item.artifactId,item.groupId,item.version);
+ }):[data.dependencies];
+ projectVersionMetadata.dependencies=dependencies;
+ }
+ // maven facet currently only for packaging
+ if(data.facetList){
+ if( $.isArray(data.facetList)){
+ for (var i=0;i<data.facetList.length;i++){
+ if(data.facetList[i].facetId=='org.apache.archiva.metadata.repository.storage.maven2.project'){
+ projectVersionMetadata.mavenFacet=new MavenFacet(data.facetList[i].packaging,data.facetList[i].parent);
+ }
+ }
+ } else {
+ if(data.facetList.facetId=='org.apache.archiva.metadata.repository.storage.maven2.project'){
+ projectVersionMetadata.mavenFacet=new MavenFacet(data.facetList.packaging,data.facetList.parent);
+ }
+ }
+ }
+ return projectVersionMetadata;
+ }
+ return new ProjectVersionMetadata();
+ }
+
+ MavenFacet=function(packaging,parent){
+ this.packaging=packaging;
+ if(parent){
+ this.parent={groupId:parent.groupId,artifactId:parent.artifactId,version:parent.version};
+ }
+
+ }
+
+ ProjectVersionMetadata=function(id,url,name,description,organization,issueManagement,scm,ciManagement,licenses,
+ mailingLists,dependencies,incomplete){
+ // private String id;
+ this.id=id;
+
+ // private String url;
+ this.url=url
+
+ //private String name;
+ this.name=name;
+
+ //private String description;
+ this.description=description;
+
+ //private Organization organization;
+ this.organization=organization;
+
+ //private IssueManagement issueManagement;
+ this.issueManagement=issueManagement;
+
+ //private Scm scm;
+ this.scm=scm;
+
+ //private CiManagement ciManagement;
+ this.ciManagement=ciManagement;
+
+ //private List<License> licenses = new ArrayList<License>();
+ this.licenses=licenses;
+
+ //private List<MailingList> mailingLists = new ArrayList<MailingList>();
+ this.mailingLists=mailingLists;
+
+ //private List<Dependency> dependencies = new ArrayList<Dependency>();
+ this.dependencies=dependencies;
+
+ //private boolean incomplete;
+ this.incomplete=incomplete;
+
+ this.mavenFacet=null;
+
+ }
+
+ Organization=function(name,url){
+ //private String name;
+ this.name=name;
+
+ //private String url;
+ this.url=url;
+ }
+
+ IssueManagement=function(system,url) {
+ //private String system;
+ this.system=system;
+
+ //private String url;
+ this.url=url;
+ }
+
+ Scm=function(connection,developerConnection,url) {
+ //private String connection;
+ this.connection=connection;
+
+ //private String developerConnection;
+ this.developerConnection=developerConnection;
+
+ //private String url;
+ this.url=url;
+ }
+
+ CiManagement=function(system,url) {
+ //private String system;
+ this.system=system;
+
+ //private String url;
+ this.url=url;
+ }
+
+ License=function(name,url){
+ this.name=name;
+ this.url=url;
+ }
+
+ MailingList=function(mainArchiveUrl,otherArchives,name,postAddress,subscribeAddress,unsubscribeAddress){
+ //private String mainArchiveUrl;
+ this.mainArchiveUrl=mainArchiveUrl;
+
+ //private List<String> otherArchives;
+ this.otherArchives=otherArchives;
+
+ //private String name;
+ this.name=name;
+
+ //private String postAddress;
+ this.postAddress=postAddress;
+
+ //private String subscribeAddress;
+ this.subscribeAddress=subscribeAddress;
+
+ //private String unsubscribeAddress;
+ this.unsubscribeAddress=unsubscribeAddress;
+ }
+
+ Dependency=function(classifier,optional,scope,systemPath,type,artifactId,groupId,version){
+ var self=this;
+ //private String classifier;
+ this.classifier=classifier;
+
+ //private boolean optional;
+ this.optional=optional;
+
+ //private String scope;
+ this.scope=scope;
+
+ //private String systemPath;
+ this.systemPath=systemPath;
+
+ //private String type;
+ this.type=type;
+
+ //private String artifactId;
+ this.artifactId=artifactId;
+
+ //private String groupId;
+ this.groupId=groupId;
+
+ //private String version;
+ this.version=version;
+
+ this.crumbEntries=function(){
+ return calculateCrumbEntries(self.groupId,self.artifactId,self.version);
+ }
+
+ }
+
+ //-----------------------------------------
+ // search part
+ //-----------------------------------------
+ Artifact=function(context,url,groupId,artifactId,repositoryId,version,prefix,goals,bundleVersion,bundleSymbolicName,
+ bundleExportPackage,bundleExportService,bundleDescription,bundleName,bundleLicense,bundleDocUrl,
+ bundleImportPackage,bundleRequireBundle,classifier,packaging,fileExtension,size){
+
+ var self=this;
+
+ //private String context;
+ this.context=context;
+
+ //private String url;
+ this.url=url;
+
+ //private String groupId;
+ this.groupId=groupId;
+
+ //private String artifactId;
+ this.artifactId=artifactId;
+
+ //private String repositoryId;
+ this.repositoryId=repositoryId;
+
+ //private String version;
+ this.version=version;
+
+ //Plugin goal prefix (only if packaging is "maven-plugin")
+ //private String prefix;
+ this.prefix=prefix;
+
+ //Plugin goals (only if packaging is "maven-plugin")
+ //private List<String> goals;
+ this.goals=goals;
+
+ //private String bundleVersion;
+ this.bundleVersion=bundleVersion;
+
+ // contains osgi metadata Bundle-SymbolicName if available
+ //private String bundleSymbolicName;
+ this.bundleSymbolicName=bundleSymbolicName;
+
+ //contains osgi metadata Export-Package if available
+ //private String bundleExportPackage;
+ this.bundleExportPackage=bundleExportPackage;
+
+ //contains osgi metadata Export-Service if available
+ //private String bundleExportService;
+ this.bundleExportService=bundleExportService;
+
+ ///contains osgi metadata Bundle-Description if available
+ //private String bundleDescription;
+ this.bundleDescription=bundleDescription;
+
+ // contains osgi metadata Bundle-Name if available
+ //private String bundleName;
+ this.bundleName=bundleName;
+
+ //contains osgi metadata Bundle-License if available
+ //private String bundleLicense;
+ this.bundleLicense=bundleLicense;
+
+ ///contains osgi metadata Bundle-DocURL if available
+ //private String bundleDocUrl;
+ this.bundleDocUrl=bundleDocUrl;
+
+ // contains osgi metadata Import-Package if available
+ //private String bundleImportPackage;
+ this.bundleImportPackage=bundleImportPackage;
+
+ ///contains osgi metadata Require-Bundle if available
+ //private String bundleRequireBundle;
+ this.bundleRequireBundle=bundleRequireBundle;
+
+ //private String classifier;
+ this.classifier=classifier;
+
+ //private String packaging;
+ this.packaging=packaging;
+
+ //file extension of the artifact
+ //private String fileExtension;
+ this.fileExtension=fileExtension;
+
+ this.size=size;
+
+ this.crumbEntries=function(){
+ return calculateCrumbEntries(self.groupId,self.artifactId,self.version);
+ }
+
+ }
+
+ calculateCrumbEntries=function(groupId,artifactId,version){
+ var splitted = groupId.split(".");
+ var breadCrumbEntries=[];
+ var curGroupId="";
+ for (var i=0;i<splitted.length;i++){
+ curGroupId+=splitted[i];
+ breadCrumbEntries.push(new BreadCrumbEntry(curGroupId,splitted[i]));
+ curGroupId+="."
+ }
+ var crumbEntryArtifact=new BreadCrumbEntry(groupId,artifactId);
+ crumbEntryArtifact.artifactId=artifactId;
+ crumbEntryArtifact.artifact=true;
+ breadCrumbEntries.push(crumbEntryArtifact);
+
+ var crumbEntryVersion=new BreadCrumbEntry(groupId,version);
+ crumbEntryVersion.artifactId=artifactId;
+ crumbEntryVersion.artifact=false;
+ crumbEntryVersion.version=version;
+ breadCrumbEntries.push(crumbEntryVersion);
+
+ return breadCrumbEntries;
+ }
+
+ mapArtifacts=function(data){
+ if (data){
+ return $.isArray(data)? $.map(data,function(item){return mapArtifact(item)}) : [data];
+ }
+ return [];
+ }
+
+ mapArtifact=function(data){
+ if(data){
+ return new Artifact(data.context,data.url,data.groupId,data.artifactId,data.repositoryId,data.version,data.prefix,
+ data.goals,data.bundleVersion,data.bundleSymbolicName,
+ data.bundleExportPackage,data.bundleExportService,data.bundleDescription,data.bundleName,
+ data.bundleLicense,data.bundleDocUrl,
+ data.bundleImportPackage,data.bundleRequireBundle,data.classifier,data.packaging,data.fileExtension,data.size);
+ }
+ return null;
+ }
+
+ SearchRequest=function(){
+
+ this.queryTerms=ko.observable();
+
+ //private String groupId;
+ this.groupId=ko.observable();
+
+ //private String artifactId;
+ this.artifactId=ko.observable();
+
+ //private String version;
+ this.version=ko.observable();
+
+ //private String packaging;
+ this.packaging=ko.observable();
+
+ //private String className;
+ this.className=ko.observable();
+
+ //private List<String> repositories = new ArrayList<String>();
+ this.repositories=ko.observableArray([]);
+
+ //private String bundleVersion;
+ this.bundleVersion=ko.observable();
+
+ //private String bundleSymbolicName;
+ this.bundleSymbolicName=ko.observable();
+
+ //private String bundleExportPackage;
+ this.bundleExportPackage=ko.observable();
+
+ //private String bundleExportService;
+ this.bundleExportService=ko.observable();
+
+ this.bundleImportPackage=ko.observable();
+
+ this.bundleRequireBundle=ko.observable();
+
+ //private String classifier;
+ this.classifier=ko.observable();
+
+ //private boolean includePomArtifacts = false;
+ this.includePomArtifacts=ko.observable(false);
+
+ this.classifier=ko.observable();
+ }
+
+ applyAutocompleteOnHeader=function(property,resultViewModel){
+ $( "#main-content").find("#search-filter-auto-"+property ).autocomplete({
+ minLength: 0,
+ source: function(request, response){
+ var founds=[];
+ $(resultViewModel.artifacts()).each(function(idx,artifact){
+ if(artifact[property] && artifact[property].startsWith(request.term)){
+ founds.push(artifact[property]);
+ }
+ });
+ response(unifyArray(founds,true));
+ },
+ select: function( event, ui ) {
+ $.log("property:"+property+','+ui.item.value);
+ var artifacts=[];
+ $(resultViewModel.artifacts()).each(function(idx,artifact){
+ if(artifact[property] && artifact[property].startsWith(ui.item.value)){
+ artifacts.push(artifact);
+ }
+ });
+ $.log("property:"+property+','+ui.item.value+",size:"+artifacts.length);
+ resultViewModel.artifacts(artifacts);
+ return false;
+ }
+ });
+ }
+
+ /**
+ * search results view model: display a grid with autocomplete filtering on grid headers
+ * @param artifacts
+ */
+ ResultViewModel=function(artifacts){
+ var self=this;
+ this.originalArtifacts=artifacts;
+ this.artifacts=ko.observableArray(artifacts);
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: self.artifacts,
+ columns: [
+ {
+ headerText: $.i18n.prop('search.artifact.results.groupId'),
+ rowText: "groupId",
+ id: "groupId"
+ },
+ {
+ headerText: $.i18n.prop('search.artifact.results.artifactId'),
+ rowText: "artifactId",
+ id: "artifactId"
+ },
+ {
+ headerText: $.i18n.prop('search.artifact.results.version'),
+ rowText: "version",
+ id: "version"
+ },
+ {
+ headerText: $.i18n.prop('search.artifact.results.classifier'),
+ rowText: "classifier",
+ id: "classifier"
+ }
+ ],
+ pageSize: 10,
+ gridUpdateCallBack: function(){
+ applyAutocompleteOnHeader('groupId',self);
+ applyAutocompleteOnHeader('artifactId',self);
+ applyAutocompleteOnHeader('version',self);
+ applyAutocompleteOnHeader('classifier',self);
+ }
+ });
+
+ groupIdView=function(artifact){
+ displayBrowseGroupId(artifact.groupId);
+ }
+ artifactIdView=function(artifact){
+ displayBrowseArtifactDetail(artifact.groupId,artifact.artifactId,null,null);
+ }
+ artifactDetailView=function(artifact){
+
+ var selectedRepo=getSelectedBrowsingRepository();
+
+ var location ="#artifact";
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+artifact.groupId+"/"+artifact.artifactId+"/"+artifact.version;
+
+ if(artifact.classifier){
+ location+="/"+artifact.classifier;
+ }
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+ }
+
+ generalDisplayArtifactDetailsVersionView=function(groupId,artifactId,version,repositoryId,afterCallbackFn){
+ var mainContent=$("#main-content");
+ mainContent.html($("#browse-tmpl" ).tmpl());
+ mainContent.find("#browse_result" ).hide();
+ mainContent.find("#browse_artifact_detail").show();
+ mainContent.find("#browse_artifact_detail").html(mediumSpinnerImg());
+ mainContent.find("#browse_breadcrumb" ).show();
+ mainContent.find("#browse_breadcrumb" ).html(mediumSpinnerImg());
+
+ userRepositoriesCall(
+ function(data) {
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(applicationUrl){
+
+ var feedsUrl=applicationUrl?applicationUrl:window.location.toString().substringBeforeLast("/").substringBeforeLast("/");
+ feedsUrl+="/feeds/"+repositoryId;
+ mainContent.find("#selected_repository" ).html($("#selected_repository_tmpl" )
+ .tmpl({repositories:data,selected:repositoryId,feedsUrl:feedsUrl}));
+ var artifactVersionDetailViewModel=new ArtifactVersionDetailViewModel(groupId,artifactId,version,repositoryId);
+ artifactVersionDetailViewModel.display(afterCallbackFn);
+ }})
+ }
+ );
+
+ }
+
+ userRepositoriesCall=function(successCallbackFn){
+ $.ajax("restServices/archivaServices/browseService/userRepositories", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ successCallbackFn(data);
+ }
+ });
+ }
+
+ /**
+ * View model used for search response and filtering
+ */
+ SearchViewModel=function(){
+ var self=this;
+ var mainContent=$("#main-content");
+ this.searchRequest=ko.observable(new SearchRequest());
+ this.observableRepoIds=ko.observableArray([]);
+ this.selectedRepoIds=[];
+ this.resultViewModel=new ResultViewModel([]);
+ basicSearch=function(){
+ var queryTerm=this.searchRequest().queryTerms();
+ if ($.trim(queryTerm).length<1){
+ var errorList=[{
+ message: $.i18n.prop("search.artifact.search.form.terms.empty"),
+ element: $("#main-content").find("#search-basic-form").find("#search-terms" ).get(0)
+ }];
+ customShowError("#main-content #search-basic-form", null, null, errorList);
+ return;
+ } else {
+ // cleanup previours error message
+ customShowError("#main-content #search-basic-form", null, null, []);
+ }
+ var location="#basicsearch";
+
+ self.selectedRepoIds=[];
+ mainContent.find("#search-basic-repositories" )
+ .find(".chzn-choices li span").each(function(i,span){
+ self.selectedRepoIds.push($(span).html());
+ }
+ );
+
+ if (self.selectedRepoIds.length>0){
+ $.log("selectedRepoIds:"+self.selectedRepoIds.length);
+ $(self.selectedRepoIds).each(function(index, Element){
+ location+="~"+self.selectedRepoIds[index];
+ });
+ }
+ location+="/"+queryTerm;
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ this.externalBasicSearch=function(){
+ var queryTerm=this.searchRequest().queryTerms();
+ self.search("restServices/archivaServices/searchService/quickSearchWithRepositories",this.searchRequest().repositories);
+ }
+
+ /**
+ * use from autocomplete search
+ */
+ this.externalAdvancedSearch=function(){
+ this.search("restServices/archivaServices/searchService/searchArtifacts");
+ }
+ advancedSearch=function(){
+ var location="#advancedsearch";
+
+ self.selectedRepoIds=[];
+ mainContent.find("#search-basic-repositories" )
+ .find(".chzn-choices li span").each(function(i,span){
+ self.selectedRepoIds.push($(span).html());
+ }
+ );
+
+ if (self.selectedRepoIds.length>0){
+ $.log("selectedRepoIds:"+self.selectedRepoIds.length);
+ $(self.selectedRepoIds).each(function(index, Element){
+ location+="~"+self.selectedRepoIds[index];
+ });
+ }
+ location+="/";
+ if(self.searchRequest().groupId()){
+ location+=self.searchRequest().groupId();
+ }/*else{
+ location+='~';
+ }*/
+ if(self.searchRequest().artifactId()){
+ location+='~'+self.searchRequest().artifactId();
+ }else{
+ location+='~';
+ }
+ if(self.searchRequest().version()){
+ location+='~'+self.searchRequest().version();
+ }else{
+ location+='~';
+ }
+ if(self.searchRequest().classifier()){
+ location+='~'+self.searchRequest().classifier();
+ }else{
+ location+='~';
+ }
+ if(self.searchRequest().packaging()){
+ location+='~'+self.searchRequest().packaging();
+ }else{
+ location+='~';
+ }
+ if(self.searchRequest().className()){
+ location+='~'+self.searchRequest().className();
+ }else{
+ location+='~';
+ }
+
+ $.log("location:"+location);
+ window.sammyArchivaApplication.setLocation(location);
+ }
+ removeFilter=function(){
+ $.log("removeFilter:"+self.resultViewModel.originalArtifacts.length);
+ self.resultViewModel.artifacts(self.resultViewModel.originalArtifacts);
+ }
+ this.search=function(url,repositoriesIds){
+
+ var searchResultsGrid=mainContent.find("#search-results" ).find("#search-results-grid" );
+ mainContent.find("#btn-basic-search" ).button("loading");
+ mainContent.find("#btn-advanced-search" ).button("loading");
+ var userMessages=$("#user-messages");
+ userMessages.html(mediumSpinnerImg());
+ if (repositoriesIds){
+ self.selectedRepoIds=repositoriesIds;
+ } else {
+ self.selectedRepoIds=[];
+ mainContent.find("#search-basic-repositories" )
+ .find(".chzn-choices li span").each(function(i,span){
+ self.selectedRepoIds.push($(span).html());
+ }
+ );
+ }
+ this.searchRequest().repositories=this.selectedRepoIds;
+ $.ajax(url,
+ {
+ type: "POST",
+ data: ko.toJSON(this.searchRequest),
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(data) {
+ clearUserMessages();
+ var artifacts=mapArtifacts(data);
+ $.log("search#ajax call success:artifacts.length:"+artifacts.length);
+ if (artifacts.length<1){
+ displayWarningMessage( $.i18n.prop("search.artifact.noresults"));
+ return;
+ } else {
+ self.resultViewModel.originalArtifacts=artifacts;
+ $.log("search#ajax call success:self.resultViewModel.originalArtifacts:"+self.resultViewModel.originalArtifacts.length);
+ self.resultViewModel.artifacts(artifacts);
+ if (!searchResultsGrid.attr("data-bind")){
+ $.log('!searchResultsGrid.attr("data-bind")');
+ searchResultsGrid.attr("data-bind",
+ "simpleGrid: gridViewModel,simpleGridTemplate:'search-results-view-grid-tmpl',pageLinksId:'search-results-view-grid-pagination'");
+ ko.applyBindings(self.resultViewModel,searchResultsGrid.get(0));
+ ko.applyBindings(self,mainContent.find("#remove-filter-id" ).get(0));
+ mainContent.find("#search-result-number-div").attr("data-bind","template:{name:'search-result-number-div-tmpl'}");
+ ko.applyBindings(self,mainContent.find("#search-result-number-div" ).get(0));
+ }
+
+ activateSearchResultsTab();
+ }
+ },
+ error: function(data) {
+ var res = $.parseJSON(data.responseText);
+ displayRestError(res);
+ },
+ complete:function() {
+ mainContent.find("#btn-basic-search" ).button("reset");
+ mainContent.find("#btn-advanced-search" ).button("reset");
+ removeMediumSpinnerImg(userMessages);
+ }
+ }
+ );
+ }
+
+ }
+
+ activateSearchResultsTab=function(){
+ var mainContent=$("#main-content");
+ mainContent.find("#search-form-collapse").removeClass("active");
+ mainContent.find("#search-results").addClass("active");
+
+ mainContent.find("#search-form-collapse-li").removeClass("active");
+ mainContent.find("#search-results-li" ).addClass("active");
+
+ }
+
+ /**
+ * display a search result (collection of Artifacts) in a grid
+ * see template with id #search-artifacts-div-tmpl
+ * @param successCallbackFn can be a callback function called on success getting observable repositories.
+ * @param searchViewModelCurrent model to reuse if not null whereas a new one is created.
+ */
+ displaySearch=function(successCallbackFn,searchViewModelCurrent){
+ screenChange();
+ var mainContent=$("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ $.ajax("restServices/archivaServices/searchService/observableRepoIds", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ mainContent.html($("#search-artifacts-div-tmpl" ).tmpl());
+ var searchViewModel;
+ if (searchViewModelCurrent){
+ $.log("searchViewModelCurrent not null");
+ searchViewModel=searchViewModelCurrent
+ }else {
+ $.log("searchViewModelCurrent null");
+ searchViewModel=new SearchViewModel();
+ }
+ var repos=mapStringList(data);
+ $.log("repos:"+repos);
+ searchViewModel.observableRepoIds(repos);
+ ko.applyBindings(searchViewModel,mainContent.find("#search-artifacts-div").get(0));
+ mainContent.find("#search-basic-repositories-select" ).select2();
+ if (successCallbackFn && $.isFunction(successCallbackFn)) successCallbackFn();
+ }
+ });
+
+ }
+
+
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/startup.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/startup.js
new file mode 100644
index 000000000..65cb7a4cc
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/startup.js
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+define("startup",["jquery","sammy","utils"],
+function(jquery,sammy,utils) {
+
+ // define a container object with various datas
+ window.archivaModel = {};
+
+ //$.log("devMode:"+window.archivaDevMode);
+
+
+
+ // no cache for ajax queries as we get datas from servers so preventing caching !!
+ jQuery.ajaxSetup( {
+ cache: false,//!window.archivaDevMode
+ dataType: 'json',
+ statusCode: {
+ 403: function() {
+ removeSmallSpinnerImg();
+ removeMediumSpinnerImg("#main-content");
+ clearUserMessages();
+ displayErrorMessage($.i18n.prop('authz.karma.needed'));
+ userLogged(function(user){
+ userLoggedCallbackFn(user);
+ },function(){
+ $.log("not logged");
+ loginBox();
+ });
+ },
+ 500: function(data){
+ $.log("error 500:"+data.responseText);
+ removeSmallSpinnerImg();
+ removeMediumSpinnerImg("#main-content");
+ clearUserMessages();
+ displayRestError($.parseJSON(data.responseText));
+ }
+ }
+ });
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/utils.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/utils.js
new file mode 100644
index 000000000..76963b69a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/utils.js
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require(["jquery","jquery.tmpl","i18n","knockout"], function(jquery,jqueryTmpl,i18n,ko) {
+
+ loadi18n=function(loadCallback){
+ $.log("loadi18n");
+ var browserLang = usedLang();
+ $.log("use browserLang:"+browserLang);
+
+ var options = {
+ cache:false,
+ mode: 'map',
+ encoding:'utf-8',
+ callback: loadCallback
+ };
+ loadAndParseFile("restServices/archivaServices/commonServices/getAllI18nResources?locale="+browserLang,options );
+ }
+
+ /**
+ * log message in the console
+ */
+ $.log = (function(message) {
+ if ( !window.archivaJavascriptLog ){
+ return;
+ }
+ Sammy.log(message);
+ /*return;
+ if (typeof window.console != 'undefined' && typeof window.console.log != 'undefined') {
+ console.log(message);
+ } else {
+ // do nothing no console
+ }*/
+ });
+
+ /**
+ * return value of a param in the url
+ * @param name
+ */
+ $.urlParam = function(name){
+ var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
+ if (results) {
+ return results[1] || 0;
+ }
+ return null;
+ }
+
+ usedLang=function(){
+ var browserLang = $.i18n.browserLang();
+ var requestLang = $.urlParam('request_lang');
+ if (requestLang) {
+ browserLang=requestLang;
+ }
+ return browserLang;
+ }
+
+ /**
+ * display a success message
+ * @param text the success text
+ * @param idToAppend the id to append the success box
+ */
+ displaySuccessMessage=function(text,idToAppend){
+ var textId = idToAppend ? $("#"+idToAppend) : $("#user-messages");
+ $.tmpl($("#alert-message-success").html(), { "message" : text }).appendTo( textId );
+ $(textId).focus();
+ }
+
+ /**
+ * display an error message
+ * @param text the success text
+ * @param idToAppend the id to append the success box
+ */
+ displayErrorMessage=function(text,idToAppend){
+ var textId = idToAppend ? $("#"+idToAppend) : $("#user-messages");
+ $.tmpl($("#alert-message-error").html(), { "message" : text }).appendTo( textId );
+ $(textId).focus();
+ }
+
+ /**
+ * display a warning message
+ * @param text the success text
+ * @param idToAppend the id to append the success box
+ */
+ displayWarningMessage=function(text,idToAppend){
+ var textId = idToAppend ? $("#"+idToAppend) : $("#user-messages");
+ $.tmpl($("#alert-message-warning").html(), { "message" : text }).appendTo( textId );
+ $(textId).focus();
+ }
+
+ displayInfoMessage=function(text,idToAppend){
+ var textId = idToAppend ? $("#"+idToAppend) : $("#user-messages");
+ $.tmpl($("#alert-message-info").html(), { "message" : text }).appendTo( textId );
+ $(textId).focus();
+ }
+
+ getUrlHash=function(){
+ var matches = window.location.toString().match(/^[^#]*(#.+)$/);
+ return matches ? matches[1] : null;
+ }
+
+ refreshContent=function(){
+ var currentHash=getUrlHash();
+ $.log("getUrlHash:"+currentHash);
+ window.sammyArchivaApplication.runRoute('get',currentHash);
+
+ }
+
+ /**
+ * clear #main-content and call clearUserMessages
+ */
+ screenChange=function(){
+ var mainContent=$("#main-content");
+ mainContent.empty();
+ mainContent.removeAttr("data-bind");
+ $("#body_content" ).find(".popover" ).hide();
+ clearUserMessages();
+ if(window.archivaModel.adminExists==false){
+ displayErrorMessage($.i18n.prop("admin.creation.mandatory"));
+ }
+
+ }
+
+ /**
+ * clear content of id if none clear content of #user-messages
+ * @param idToAppend
+ */
+ clearUserMessages=function(idToAppend){
+ var textId = idToAppend ? $("#"+idToAppend) : $("#user-messages");
+ $(textId).empty();
+ }
+
+ /**
+ * clear all input text and password found in the the selector
+ * @param selectorStr
+ */
+ clearForm=function(selectorStr){
+ $(selectorStr).find("input[type='text']").each(function(ele){
+ $(this).val("");
+ });
+ $(selectorStr).find("input[type='password']").each(function(ele){
+ $(this).val("");
+ });
+
+ }
+
+ /**
+ * open a confirm dialog based on bootstrap modal
+ * @param okFn callback function to call on ok confirm
+ * @param okMessage message in the ok button
+ * @param cancelMessage message in the cancel button
+ * @param title title of the modal box
+ * @param bodyText html content of the modal box
+ */
+ openDialogConfirm=function(okFn, okMessage, cancelMessage, title,bodyText){
+ var dialogCancel=$("#dialog-confirm-modal-cancel");
+ if (window.modalConfirmDialog==null) {
+ window.modalConfirmDialog = $("#dialog-confirm-modal").modal();
+ window.modalConfirmDialog.bind('hidden', function () {
+ $("#dialog-confirm-modal-header-title").empty();
+ $("#dialog-confirm-modal-body-text").empty();
+ })
+ dialogCancel.on("click", function(){
+ window.modalConfirmDialog.modal('hide');
+ });
+ }
+ $("#dialog-confirm-modal-header-title").html(title);
+ $("#dialog-confirm-modal-body-text").html(bodyText);
+ var dialogConfirmModalOk=$("#dialog-confirm-modal-ok");
+ if (okMessage){
+ dialogConfirmModalOk.html(okMessage);
+ }
+ if (cancelMessage){
+ dialogCancel.html(cancelMessage);
+ }
+ window.modalConfirmDialog.modal('show');
+
+ // unbind previous events !!
+
+ dialogConfirmModalOk.off( );
+ dialogConfirmModalOk.on("click", okFn);
+
+ }
+
+ /**
+ * return a small spinner html img element
+ */
+ smallSpinnerImg=function(){
+ return "<img id=\"small-spinner\" src=\"images/small-spinner.gif\"/>";
+ };
+
+ removeSmallSpinnerImg=function(){
+ $("#small-spinner").remove();
+ }
+
+ removeMediumSpinnerImg=function(){
+ $("#medium-spinner").remove();
+ }
+
+ removeMediumSpinnerImg=function(selector){
+ if (typeof selector == 'string') {
+ $(selector).find("#medium-spinner").remove();
+ } else {
+ selector.find("#medium-spinner").remove();
+ }
+
+ }
+
+ mediumSpinnerImg=function(){
+ return "<img id=\"medium-spinner\" src=\"images/medium-spinner.gif\"/>";
+ };
+
+ closeDialogConfirm=function(){
+ window.modalConfirmDialog.modal('hide');
+ }
+
+ mapStringArray=function(data){
+ if (data) {
+ if ($.isArray(data)){
+ return $.map(data,function(item){
+ return item;
+ });
+ } else {
+ return new Array(data);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * display redback error from redback json error response
+ * {"redbackRestError":{"errorMessages":{"args":1,"errorKey":"user.password.violation.numeric"}}}
+ * @param obj
+ * @param idToAppend
+ */
+ displayRedbackError=function(obj,idToAppend) {
+ if ($.isArray(obj.errorMessages)) {
+ $.log("displayRedbackError with array");
+ for(var i=0; i<obj.errorMessages.length; i++ ) {
+ if(obj.errorMessages[i].errorKey) {
+ displayErrorMessage($.i18n.prop( obj.errorMessages[i].errorKey, obj.errorMessages[i].args ),idToAppend);
+ }
+ if(obj.errorMessages[i].message) {
+ displayErrorMessage(obj.errorMessages[i].message,idToAppend);
+ }
+ }
+ } else {
+ displayErrorMessage($.i18n.prop( obj.errorMessages.errorKey, obj.errorMessages.args ),idToAppend);
+ }
+ }
+
+ /*
+ * generic function to display error return by rest service
+ * if fieldName is here the function will try to find a field with this name and add a span on it
+ * if not error is displayed in #user-messages div
+ */
+ displayRestError=function(data,idToAppend){
+ $.log("displayRestError");
+ // maybe data is just the response so test if if we have a responseText and transform it to json
+ if(data.responseText){
+ data= $.parseJSON(data.responseText);
+ }
+ if (data.redbackRestError){
+ displayRedbackError(archivaRestError,idToAppend)
+ }
+ // if we have the fieldName display error on it
+ if (data && data.fieldName){
+ var mainContent=$("#main-content");
+
+ if (mainContent.find("#"+data.fieldName)){
+ var message=null;
+ if (data.errorKey) {
+ message=$.i18n.prop('data.errorKey');
+ } else {
+ message=data.errorMessage;
+ }
+ mainContent.find("div.clearfix" ).removeClass( "error" );
+ mainContent.find("span.help-inline" ).remove();
+ mainContent.find("#"+data.fieldName).parents( "div.clearfix" ).addClass( "error" );
+ mainContent.find("#"+data.fieldName).parent().append( "<span class=\"help-inline\">" + message + "</span>" );
+ return;
+ }
+ // we don't have any id with this fieldName so continue
+ }
+
+ if (data.errorKey && data.errorKey.length>0){
+ displayErrorMessage($.i18n.prop( data.errorKey ),idToAppend);
+ } else if (data.errorMessages){
+ $.each(data.errorMessages, function(index, value) {
+ if(data.errorMessages[index].errorKey) {
+ displayErrorMessage( $.i18n.prop(data.errorMessages[index].errorKey,data.errorMessages[index].args?data.errorMessages[index].args:null),idToAppend);
+ }
+ });
+ } else {
+ $.log("print data.errorMessage:"+data.errorMessage);
+ displayErrorMessage(data.errorMessage,idToAppend);
+ }
+
+ }
+
+ /**
+ * used by validation error to customize error display in the ui
+ * @param selector
+ * @param validator
+ * @param errorMap
+ * @param errorList
+ */
+ customShowError=function(selector, validator, errorMap, errorList) {
+ removeValidationErrorMessages(selector);
+ for ( var i = 0; errorList[i]; i++ ) {
+ var error = errorList[i];
+ if (typeof selector == 'string') {
+ var field = $(selector).find("#"+error.element.id);
+ } else {
+ var field = selector.find("#"+error.element.id);
+ }
+ field.parents( "div.control-group" ).addClass( "error" );
+ field.parent().append( "<span class=\"help-inline\">" + error.message + "</span>" );
+ }
+ }
+
+ removeValidationErrorMessages=function(selector){
+ if (typeof selector == 'string') {
+ $(selector).find("div.control-group" ).removeClass( "error" );
+ $(selector).find("span.help-inline").remove();
+ } else {
+ selector.find("div.control-group" ).removeClass( "error" );
+ selector.find("span.help-inline").remove();
+ }
+
+ }
+
+ appendArchivaVersion=function(){
+ return "_archivaVersion="+window.archivaRuntimeInfo.version;
+ }
+
+ buildLoadJsUrl=function(srcScript){
+ return srcScript+"?"+appendArchivaVersion()+"&_"+jQuery.now();
+ }
+
+ timestampNoCache=function(){
+ if (!window.archivaDevMode){
+ return "";
+ }
+ return "&_="+jQuery.now();
+ }
+
+
+ /**
+ * mapping for a java Map entry
+ * @param key
+ * @param value
+ * @param subscribeFn if any will be called as subscrible function field
+ */
+ Entry=function(key,value,subscribeFn){
+ var self=this;
+ this.modified=ko.observable(false);
+ this.modified.subscribe(function(newValue){
+ $.log("Entry modified");
+ });
+
+ this.key=ko.observable(key);
+ this.key.subscribe(function(newValue){
+ self.modified(true);
+ if(subscribeFn){
+ subscribeFn(newValue)
+ }
+ });
+
+ this.value=ko.observable(value);
+ this.value.subscribe(function(newValue){
+ self.modified(true);
+ if(subscribeFn){
+ subscribeFn(newValue)
+ }
+ });
+
+
+ }
+
+ /**
+ * map {"strings":["snapshots","internal"]} to an array
+ * @param data
+ */
+ mapStringList=function(data){
+ if (data && data.strings){
+ return $.isArray(data.strings) ?
+ $.map(data.strings,function(item){return item}): [data.strings];
+ }
+ return [];
+ }
+
+ /**
+ * return an array with removing duplicate strings
+ * @param strArray an array of string
+ * @param sorted to sort or not
+ */
+ unifyArray=function(strArray,sorted){
+ var res = [];
+ $(strArray).each(function(idx,str){
+ if ( $.inArray(str,res)<0){
+ res.push(str);
+ }
+ });
+ return sorted?res.sort():res;
+ }
+
+ goToAnchor=function(anchor){
+ var curHref = window.location.href;
+ curHref=curHref.substringBeforeLast("#");
+ window.location.href=curHref+"#"+anchor;
+ }
+
+ //------------------------------------
+ // utils javascript string extensions
+ //------------------------------------
+
+ String.prototype.isEmpty = function(str) {
+ return ($.trim(this ).length < 1);
+ }
+ String.prototype.isNotEmpty = function(str) {
+ return ($.trim(this ).length > 0);
+ }
+
+ String.prototype.endsWith = function(str) {
+ return (this.match(str+"$")==str)
+ }
+
+ String.prototype.startsWith = function(str) {
+ return (this.match("^"+str)==str)
+ }
+
+ String.prototype.substringBeforeLast = function(str) {
+ return this.substring(0,this.lastIndexOf(str));
+ }
+
+ String.prototype.substringBeforeFirst = function(str) {
+ var idx = this.indexOf(str);
+ if(idx<0){
+ return this;
+ }
+ return this.substring(0,idx);
+ }
+
+ String.prototype.substringAfterLast = function(str) {
+ return this.substring(this.lastIndexOf(str)+1);
+ }
+ /**
+ *
+ * @param str
+ * @return {String} if str not found return empty string
+ */
+ String.prototype.substringAfterFirst = function(str) {
+ var idx = this.indexOf(str);
+ if (idx<0){
+ return "";
+ }
+ return this.substring(idx+str.length);
+ }
+
+ escapeDot=function(str){
+ return str.replace(/\./g,"\\\.");
+ }
+
+ /**
+ * select class:
+ * * .popover-doc: activate popover with html:true and click trigger
+ * * .tooltip-doc: active tooltip
+ */
+ activatePopoverDoc=function(){
+ var mainContent=$("#main-content");
+ mainContent.find(".popover-doc" ).popover({html: true, trigger: 'click'});
+ /*mainContent.find(".popover-doc" ).on("click",function(){
+ $(this).popover("show");
+ });
+
+ mainContent.find(".popover-doc" ).mouseover(function(){
+ $(this).popover("destroy");
+ });*/
+
+ mainContent.find(".tooltip-doc" ).tooltip({html: true, trigger: 'hover'});
+ }
+
+ //-----------------------------------------
+ // extends jquery tmpl to support var def
+ //-----------------------------------------
+
+ $(function() {
+ $.extend($.tmpl.tag, {
+ "var": {
+ open: "var $1;"
+ }
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/bootstrap.2.2.1.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/bootstrap.2.2.1.js
new file mode 100644
index 000000000..c753bd6f8
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/bootstrap.2.2.1.js
@@ -0,0 +1,2025 @@
+/* ===================================================
+ * bootstrap-transition.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+ * ======================================================= */
+
+ $(function () {
+
+ $.support.transition = (function () {
+
+ var transitionEnd = (function () {
+
+ var el = document.createElement('bootstrap')
+ , transEndEventNames = {
+ 'WebkitTransition' : 'webkitTransitionEnd'
+ , 'MozTransition' : 'transitionend'
+ , 'OTransition' : 'oTransitionEnd otransitionend'
+ , 'transition' : 'transitionend'
+ }
+ , name
+
+ for (name in transEndEventNames){
+ if (el.style[name] !== undefined) {
+ return transEndEventNames[name]
+ }
+ }
+
+ }())
+
+ return transitionEnd && {
+ end: transitionEnd
+ }
+
+ })()
+
+ })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+
+ e && e.preventDefault()
+
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+ $parent.trigger(e = $.Event('close'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ $parent
+ .trigger('closed')
+ .remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent.on($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.alert = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Constructor = Alert
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ $.fn.button = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ $btn.button('toggle')
+ })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+ * ========================= */
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.options = options
+ this.options.slide && this.slide(this.options.slide)
+ this.options.pause == 'hover' && this.$element
+ .on('mouseenter', $.proxy(this.pause, this))
+ .on('mouseleave', $.proxy(this.cycle, this))
+ }
+
+ Carousel.prototype = {
+
+ cycle: function (e) {
+ if (!e) this.paused = false
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+ return this
+ }
+
+ , to: function (pos) {
+ var $active = this.$element.find('.item.active')
+ , children = $active.parent().children()
+ , activePos = children.index($active)
+ , that = this
+
+ if (pos > (children.length - 1) || pos < 0) return
+
+ if (this.sliding) {
+ return this.$element.one('slid', function () {
+ that.to(pos)
+ })
+ }
+
+ if (activePos == pos) {
+ return this.pause().cycle()
+ }
+
+ return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
+ }
+
+ , pause: function (e) {
+ if (!e) this.paused = true
+ if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle()
+ }
+ clearInterval(this.interval)
+ this.interval = null
+ return this
+ }
+
+ , next: function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ , prev: function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ , slide: function (type, next) {
+ var $active = this.$element.find('.item.active')
+ , $next = next || $active[type]()
+ , isCycling = this.interval
+ , direction = type == 'next' ? 'left' : 'right'
+ , fallback = type == 'next' ? 'first' : 'last'
+ , that = this
+ , e
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+ e = $.Event('slide', {
+ relatedTarget: $next[0]
+ })
+
+ if ($next.hasClass('active')) return
+
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ this.$element.one($.support.transition.end, function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
+ })
+ } else {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger('slid')
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+ }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.carousel = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('carousel')
+ , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+ , action = typeof option == 'string' ? option : options.slide
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.cycle()
+ })
+ }
+
+ $.fn.carousel.defaults = {
+ interval: 5000
+ , pause: 'hover'
+ }
+
+ $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL DATA-API
+ * ================= */
+
+ $(document).on('click.carousel.data-api', '[data-slide]', function (e) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , options = $.extend({}, $target.data(), $this.data())
+ $target.carousel(options)
+ e.preventDefault()
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+ * ================================ */
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.options.parent) {
+ this.$parent = $(this.options.parent)
+ }
+
+ this.options.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ constructor: Collapse
+
+ , dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension
+ , scroll
+ , actives
+ , hasData
+
+ if (this.transitioning) return
+
+ dimension = this.dimension()
+ scroll = $.camelCase(['scroll', dimension].join('-'))
+ actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ if (hasData && hasData.transitioning) return
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', $.Event('show'), 'shown')
+ $.support.transition && this.$element[dimension](this.$element[0][scroll])
+ }
+
+ , hide: function () {
+ var dimension
+ if (this.transitioning) return
+ dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', $.Event('hide'), 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function (size) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || 'auto')
+ [0].offsetWidth
+
+ this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+ return this
+ }
+
+ , transition: function (method, startEvent, completeEvent) {
+ var that = this
+ , complete = function () {
+ if (startEvent.type == 'show') that.reset()
+ that.transitioning = 0
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element.trigger(startEvent)
+
+ if (startEvent.isDefaultPrevented()) return
+
+ this.transitioning = 1
+
+ this.$element[method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* COLLAPSIBLE PLUGIN DEFINITION
+ * ============================== */
+
+ $.fn.collapse = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSIBLE DATA-API
+ * ==================== */
+
+ $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+ var $this = $(this), href
+ , target = $this.attr('data-target')
+ || e.preventDefault()
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+ $(target).collapse(option)
+ })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
+
+ var toggle = '[data-toggle=dropdown]'
+ , Dropdown = function (element) {
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
+ $('html').on('click.dropdown.data-api', function () {
+ $el.parent().removeClass('open')
+ })
+ }
+
+ Dropdown.prototype = {
+
+ constructor: Dropdown
+
+ , toggle: function (e) {
+ var $this = $(this)
+ , $parent
+ , isActive
+
+ if ($this.is('.disabled, :disabled')) return
+
+ $parent = getParent($this)
+
+ isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ $parent.toggleClass('open')
+ $this.focus()
+ }
+
+ return false
+ }
+
+ , keydown: function (e) {
+ var $this
+ , $items
+ , $active
+ , $parent
+ , isActive
+ , index
+
+ if (!/(38|40|27)/.test(e.keyCode)) return
+
+ $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ $parent = getParent($this)
+
+ isActive = $parent.hasClass('open')
+
+ if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
+
+ $items = $('[role=menu] li:not(.divider) a', $parent)
+
+ if (!$items.length) return
+
+ index = $items.index($items.filter(':focus'))
+
+ if (e.keyCode == 38 && index > 0) index-- // up
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items
+ .eq(index)
+ .focus()
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).each(function () {
+ getParent($(this)).removeClass('open')
+ })
+ }
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.length || ($parent = $this.parent())
+
+ return $parent
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.dropdown = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(document)
+ .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
+ .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
+ .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);/* =========================================================
+ * bootstrap-modal.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$element = $(element)
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+ }
+
+ Modal.prototype = {
+
+ constructor: Modal
+
+ , toggle: function () {
+ return this[!this.isShown ? 'show' : 'hide']()
+ }
+
+ , show: function () {
+ var that = this
+ , e = $.Event('show')
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.escape()
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(document.body) //don't move modals dom position
+ }
+
+ that.$element
+ .show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element
+ .addClass('in')
+ .attr('aria-hidden', false)
+
+ that.enforceFocus()
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+ that.$element.focus().trigger('shown')
+
+ })
+ }
+
+ , hide: function (e) {
+ e && e.preventDefault()
+
+ var that = this
+
+ e = $.Event('hide')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+
+ $(document).off('focusin.modal')
+
+ this.$element
+ .removeClass('in')
+ .attr('aria-hidden', true)
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.hideWithTransition() :
+ this.hideModal()
+ }
+
+ , enforceFocus: function () {
+ var that = this
+ $(document).on('focusin.modal', function (e) {
+ if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+ that.$element.focus()
+ }
+ })
+ }
+
+ , escape: function () {
+ var that = this
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
+ })
+ } else if (!this.isShown) {
+ this.$element.off('keyup.dismiss.modal')
+ }
+ }
+
+ , hideWithTransition: function () {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.off($.support.transition.end)
+ that.hideModal()
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ that.hideModal()
+ })
+ }
+
+ , hideModal: function (that) {
+ this.$element
+ .hide()
+ .trigger('hidden')
+
+ this.backdrop()
+ }
+
+ , removeBackdrop: function () {
+ this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ , backdrop: function (callback) {
+ var that = this
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+ .appendTo(document.body)
+
+ this.$backdrop.click(
+ this.options.backdrop == 'static' ?
+ $.proxy(this.$element[0].focus, this.$element[0])
+ : $.proxy(this.hide, this)
+ )
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ doAnimate ?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade')?
+ this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
+ this.removeBackdrop()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+ }
+
+
+ /* MODAL PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.modal = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ else if (options.show) data.show()
+ })
+ }
+
+ $.fn.modal.defaults = {
+ backdrop: true
+ , keyboard: true
+ , show: true
+ }
+
+ $.fn.modal.Constructor = Modal
+
+
+ /* MODAL DATA-API
+ * ============== */
+
+ $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ , href = $this.attr('href')
+ , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+ , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+ e.preventDefault()
+
+ $target
+ .modal(option)
+ .one('hide', function () {
+ $this.focus()
+ })
+ })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function (element, options) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function (type, element, options) {
+ var eventIn
+ , eventOut
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ if (this.options.trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (this.options.trigger != 'manual') {
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function (options) {
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ clearTimeout(this.timeout)
+ self.hoverState = 'in'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ , leave: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (this.timeout) clearTimeout(this.timeout)
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.hoverState = 'out'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ , show: function () {
+ var $tip
+ , inside
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+
+ if (this.hasContent() && this.enabled) {
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ inside = /in/.test(placement)
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .insertAfter(this.$element)
+
+ pos = this.getPosition(inside)
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (inside ? placement.split(' ')[1] : placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ $tip
+ .offset(tp)
+ .addClass(placement)
+ .addClass('in')
+ }
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).detach()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.detach()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.detach()
+
+ return this
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function (inside) {
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
+ width: this.$element[0].offsetWidth
+ , height: this.$element[0].offsetHeight
+ })
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+ self[self.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
+ , destroy: function () {
+ this.hide().$element.off('.' + this.type).removeData(this.type)
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , placement: 'top'
+ , selector: false
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+ , trigger: 'hover'
+ , title: ''
+ , delay: 0
+ , html: false
+ }
+
+}(window.jQuery);/* ===========================================================
+ * bootstrap-popover.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content > *')[this.options.html ? 'html' : 'text'](content)
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = $e.attr('data-content')
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+
+ return content
+ }
+
+ , tip: function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ }
+ return this.$tip
+ }
+
+ , destroy: function () {
+ this.hide().$element.off('.' + this.type).removeData(this.type)
+ }
+
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , trigger: 'click'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-scrollspy.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+ * ========================== */
+
+ function ScrollSpy(element, options) {
+ var process = $.proxy(this.process, this)
+ , $element = $(element).is('body') ? $(window) : $(element)
+ , href
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+ this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+ this.selector = (this.options.target
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ || '') + ' .nav li > a'
+ this.$body = $('body')
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.prototype = {
+
+ constructor: ScrollSpy
+
+ , refresh: function () {
+ var self = this
+ , $targets
+
+ this.offsets = $([])
+ this.targets = $([])
+
+ $targets = this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ , href = $el.data('target') || $el.attr('href')
+ , $href = /^#\w/.test(href) && $(href)
+ return ( $href
+ && $href.length
+ && [[ $href.position().top, href ]] ) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ self.offsets.push(this[0])
+ self.targets.push(this[1])
+ })
+ }
+
+ , process: function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+ , maxScroll = scrollHeight - this.$scrollElement.height()
+ , offsets = this.offsets
+ , targets = this.targets
+ , activeTarget = this.activeTarget
+ , i
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets.last()[0])
+ && this.activate ( i )
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && this.activate( targets[i] )
+ }
+ }
+
+ , activate: function (target) {
+ var active
+ , selector
+
+ this.activeTarget = target
+
+ $(this.selector)
+ .parent('.active')
+ .removeClass('active')
+
+ selector = this.selector
+ + '[data-target="' + target + '"],'
+ + this.selector + '[href="' + target + '"]'
+
+ active = $(selector)
+ .parent('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active.closest('li.dropdown').addClass('active')
+ }
+
+ active.trigger('activate')
+ }
+
+ }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.scrollspy = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('scrollspy')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+ $.fn.scrollspy.defaults = {
+ offset: 10
+ }
+
+
+ /* SCROLLSPY DATA-API
+ * ================== */
+
+ $(window).on('load', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ $spy.scrollspy($spy.data())
+ })
+ })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+ * ==================== */
+
+ var Tab = function (element) {
+ this.element = $(element)
+ }
+
+ Tab.prototype = {
+
+ constructor: Tab
+
+ , show: function () {
+ var $this = this.element
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
+ , selector = $this.attr('data-target')
+ , previous
+ , $target
+ , e
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ if ( $this.parent('li').hasClass('active') ) return
+
+ previous = $ul.find('.active:last a')[0]
+
+ e = $.Event('show', {
+ relatedTarget: previous
+ })
+
+ $this.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $target = $(selector)
+
+ this.activate($this.parent('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $this.trigger({
+ type: 'shown'
+ , relatedTarget: previous
+ })
+ })
+ }
+
+ , activate: function ( element, container, callback) {
+ var $active = container.find('> .active')
+ , transition = callback
+ && $.support.transition
+ && $active.hasClass('fade')
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+
+ element.addClass('active')
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if ( element.parent('.dropdown-menu') ) {
+ element.closest('li.dropdown').addClass('active')
+ }
+
+ callback && callback()
+ }
+
+ transition ?
+ $active.one($.support.transition.end, next) :
+ next()
+
+ $active.removeClass('in')
+ }
+ }
+
+
+ /* TAB PLUGIN DEFINITION
+ * ===================== */
+
+ $.fn.tab = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tab')
+ if (!data) $this.data('tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tab.Constructor = Tab
+
+
+ /* TAB DATA-API
+ * ============ */
+
+ $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ e.preventDefault()
+ $(this).tab('show')
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+ "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Typeahead = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
+ this.matcher = this.options.matcher || this.matcher
+ this.sorter = this.options.sorter || this.sorter
+ this.highlighter = this.options.highlighter || this.highlighter
+ this.updater = this.options.updater || this.updater
+ this.$menu = $(this.options.menu).appendTo('body')
+ this.source = this.options.source
+ this.shown = false
+ this.listen()
+ }
+
+ Typeahead.prototype = {
+
+ constructor: Typeahead
+
+ , select: function () {
+ var val = this.$menu.find('.active').attr('data-value')
+ this.$element
+ .val(this.updater(val))
+ .change()
+ return this.hide()
+ }
+
+ , updater: function (item) {
+ return item
+ }
+
+ , show: function () {
+ var pos = $.extend({}, this.$element.offset(), {
+ height: this.$element[0].offsetHeight
+ })
+
+ this.$menu.css({
+ top: pos.top + pos.height
+ , left: pos.left
+ })
+
+ this.$menu.show()
+ this.shown = true
+ return this
+ }
+
+ , hide: function () {
+ this.$menu.hide()
+ this.shown = false
+ return this
+ }
+
+ , lookup: function (event) {
+ var items
+
+ this.query = this.$element.val()
+
+ if (!this.query || this.query.length < this.options.minLength) {
+ return this.shown ? this.hide() : this
+ }
+
+ items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+ return items ? this.process(items) : this
+ }
+
+ , process: function (items) {
+ var that = this
+
+ items = $.grep(items, function (item) {
+ return that.matcher(item)
+ })
+
+ items = this.sorter(items)
+
+ if (!items.length) {
+ return this.shown ? this.hide() : this
+ }
+
+ return this.render(items.slice(0, this.options.items)).show()
+ }
+
+ , matcher: function (item) {
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+ }
+
+ , sorter: function (items) {
+ var beginswith = []
+ , caseSensitive = []
+ , caseInsensitive = []
+ , item
+
+ while (item = items.shift()) {
+ if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+ else if (~item.indexOf(this.query)) caseSensitive.push(item)
+ else caseInsensitive.push(item)
+ }
+
+ return beginswith.concat(caseSensitive, caseInsensitive)
+ }
+
+ , highlighter: function (item) {
+ var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+ return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+ return '<strong>' + match + '</strong>'
+ })
+ }
+
+ , render: function (items) {
+ var that = this
+
+ items = $(items).map(function (i, item) {
+ i = $(that.options.item).attr('data-value', item)
+ i.find('a').html(that.highlighter(item))
+ return i[0]
+ })
+
+ items.first().addClass('active')
+ this.$menu.html(items)
+ return this
+ }
+
+ , next: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , next = active.next()
+
+ if (!next.length) {
+ next = $(this.$menu.find('li')[0])
+ }
+
+ next.addClass('active')
+ }
+
+ , prev: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , prev = active.prev()
+
+ if (!prev.length) {
+ prev = this.$menu.find('li').last()
+ }
+
+ prev.addClass('active')
+ }
+
+ , listen: function () {
+ this.$element
+ .on('blur', $.proxy(this.blur, this))
+ .on('keypress', $.proxy(this.keypress, this))
+ .on('keyup', $.proxy(this.keyup, this))
+
+ if (this.eventSupported('keydown')) {
+ this.$element.on('keydown', $.proxy(this.keydown, this))
+ }
+
+ this.$menu
+ .on('click', $.proxy(this.click, this))
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+ }
+
+ , eventSupported: function(eventName) {
+ var isSupported = eventName in this.$element
+ if (!isSupported) {
+ this.$element.setAttribute(eventName, 'return;')
+ isSupported = typeof this.$element[eventName] === 'function'
+ }
+ return isSupported
+ }
+
+ , move: function (e) {
+ if (!this.shown) return
+
+ switch(e.keyCode) {
+ case 9: // tab
+ case 13: // enter
+ case 27: // escape
+ e.preventDefault()
+ break
+
+ case 38: // up arrow
+ e.preventDefault()
+ this.prev()
+ break
+
+ case 40: // down arrow
+ e.preventDefault()
+ this.next()
+ break
+ }
+
+ e.stopPropagation()
+ }
+
+ , keydown: function (e) {
+ this.suppressKeyPressRepeat = !~$.inArray(e.keyCode, [40,38,9,13,27])
+ this.move(e)
+ }
+
+ , keypress: function (e) {
+ if (this.suppressKeyPressRepeat) return
+ this.move(e)
+ }
+
+ , keyup: function (e) {
+ switch(e.keyCode) {
+ case 40: // down arrow
+ case 38: // up arrow
+ case 16: // shift
+ case 17: // ctrl
+ case 18: // alt
+ break
+
+ case 9: // tab
+ case 13: // enter
+ if (!this.shown) return
+ this.select()
+ break
+
+ case 27: // escape
+ if (!this.shown) return
+ this.hide()
+ break
+
+ default:
+ this.lookup()
+ }
+
+ e.stopPropagation()
+ e.preventDefault()
+ }
+
+ , blur: function (e) {
+ var that = this
+ setTimeout(function () { that.hide() }, 150)
+ }
+
+ , click: function (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ this.select()
+ }
+
+ , mouseenter: function (e) {
+ this.$menu.find('.active').removeClass('active')
+ $(e.currentTarget).addClass('active')
+ }
+
+ }
+
+
+ /* TYPEAHEAD PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.typeahead = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('typeahead')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.typeahead.defaults = {
+ source: []
+ , items: 8
+ , menu: '<ul class="typeahead dropdown-menu"></ul>'
+ , item: '<li><a href="#"></a></li>'
+ , minLength: 1
+ }
+
+ $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD DATA-API
+ * ================== */
+
+ $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+ var $this = $(this)
+ if ($this.data('typeahead')) return
+ e.preventDefault()
+ $this.typeahead($this.data())
+ })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.2.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+ * ====================== */
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, $.fn.affix.defaults, options)
+ this.$window = $(window)
+ .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+ this.$element = $(element)
+ this.checkPosition()
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var scrollHeight = $(document).height()
+ , scrollTop = this.$window.scrollTop()
+ , position = this.$element.offset()
+ , offset = this.options.offset
+ , offsetBottom = offset.bottom
+ , offsetTop = offset.top
+ , reset = 'affix affix-top affix-bottom'
+ , affix
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top()
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+ affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+ false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+ 'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+ 'top' : false
+
+ if (this.affixed === affix) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+ this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+ }
+
+
+ /* AFFIX PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.affix = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('affix')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.affix.Constructor = Affix
+
+ $.fn.affix.defaults = {
+ offset: 0
+ }
+
+
+ /* AFFIX DATA-API
+ * ============== */
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ , data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+ data.offsetTop && (data.offset.top = data.offsetTop)
+
+ $spy.affix(data)
+ })
+ })
+
+
+}(window.jQuery); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/domReady.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/domReady.js
new file mode 100644
index 000000000..6a7977296
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/domReady.js
@@ -0,0 +1,125 @@
+/**
+ * @license RequireJS domReady 2.0.0 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/requirejs/domReady for details
+ */
+/*jslint */
+/*global require: false, define: false, requirejs: false,
+ window: false, clearInterval: false, document: false,
+ self: false, setInterval: false */
+
+
+define(function () {
+ 'use strict';
+
+ var isBrowser = typeof window !== "undefined" && window.document,
+ isPageLoaded = !isBrowser,
+ doc = isBrowser ? document : null,
+ readyCalls = [],
+ isTop, testDiv, scrollIntervalId;
+
+ function runCallbacks(callbacks) {
+ var i;
+ for (i = 0; i < callbacks.length; i++) {
+ callbacks[i](doc);
+ }
+ }
+
+ function callReady() {
+ var callbacks = readyCalls;
+
+ if (isPageLoaded) {
+ //Call the DOM ready callbacks
+ if (callbacks.length) {
+ readyCalls = [];
+ runCallbacks(callbacks);
+ }
+ }
+ }
+
+ /**
+ * Sets the page as loaded.
+ */
+ function pageLoaded() {
+ if (!isPageLoaded) {
+ isPageLoaded = true;
+ if (scrollIntervalId) {
+ clearInterval(scrollIntervalId);
+ }
+
+ callReady();
+ }
+ }
+
+ if (isBrowser) {
+ if (document.addEventListener) {
+ //Standards. Hooray! Assumption here that if standards based,
+ //it knows about DOMContentLoaded.
+ document.addEventListener("DOMContentLoaded", pageLoaded, false);
+ window.addEventListener("load", pageLoaded, false);
+ } else if (window.attachEvent) {
+ window.attachEvent("onload", pageLoaded);
+
+ testDiv = document.createElement('div');
+ try {
+ isTop = window.frameElement === null;
+ } catch(e) {}
+
+ //DOMContentLoaded approximation that uses a doScroll, as found by
+ //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/,
+ //but modified by other contributors, including jdalton
+ if (testDiv.doScroll && isTop && window.external) {
+ scrollIntervalId = setInterval(function () {
+ try {
+ testDiv.doScroll();
+ pageLoaded();
+ } catch (e) {}
+ }, 30);
+ }
+ }
+
+ //Check if document already complete, and if so, just trigger page load
+ //listeners. Latest webkit browsers also use "interactive", and
+ //will fire the onDOMContentLoaded before "interactive" but not after
+ //entering "interactive" or "complete". More details:
+ //http://dev.w3.org/html5/spec/the-end.html#the-end
+ //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded
+ if (document.readyState === "complete" ||
+ document.readyState === "interactive") {
+ pageLoaded();
+ }
+ }
+
+ /** START OF PUBLIC API **/
+
+ /**
+ * Registers a callback for DOM ready. If DOM is already ready, the
+ * callback is called immediately.
+ * @param {Function} callback
+ */
+ function domReady(callback) {
+ if (isPageLoaded) {
+ callback(doc);
+ } else {
+ readyCalls.push(callback);
+ }
+ return domReady;
+ }
+
+ domReady.version = '2.0.0';
+
+ /**
+ * Loader Plugin API method
+ */
+ domReady.load = function (name, req, onLoad, config) {
+ if (config.isBuild) {
+ onLoad(null);
+ } else {
+ domReady(onLoad);
+ }
+ };
+
+ /** END OF PUBLIC API **/
+
+ return domReady;
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-1.8.3.min.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-1.8.3.min.js
new file mode 100644
index 000000000..83589daa7
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-1.8.3.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v1.8.3 jquery.com | jquery.org/license */
+(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-ui-1.9.2.custom.min.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-ui-1.9.2.custom.min.js
new file mode 100755
index 000000000..9b3b84deb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery-ui-1.9.2.custom.min.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.9.2 - 2012-11-23
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
+* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
+
+(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.2",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}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},contains:e.contains,hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e<t+n},isOver:function(t,n,r,i,s,o){return e.ui.isOverAxis(t,r,s)&&e.ui.isOverAxis(n,i,o)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&(e.effects.effect[u]||e.uiBackCompat!==!1&&e.effects[u])?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}}),e.uiBackCompat!==!1&&(e.Widget.prototype._getCreateOptions=function(){return e.metadata&&e.metadata.get(this.element[0])[this.widgetName]})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(e){n=!1}),e.widget("ui.mouse",{version:"1.9.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return!e.ui.ie||document.documentMode>=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,d,v,m,g=e(t.of),y=e.position.getWithinInfo(t.within),b=e.position.getScrollInfo(y),w=g[0],E=(t.collision||"flip").split(" "),S={};return w.nodeType===9?(l=g.width(),d=g.height(),v={top:0,left:0}):e.isWindow(w)?(l=g.width(),d=g.height(),v={top:g.scrollTop(),left:g.scrollLeft()}):w.preventDefault?(t.at="left top",l=d=0,v={top:w.pageY,left:w.pageX}):(l=g.outerWidth(),d=g.outerHeight(),v=g.offset()),m=e.extend({},v),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),S[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),E.length===1&&(E[1]=E[0]),t.at[0]==="right"?m.left+=l:t.at[0]==="center"&&(m.left+=l/2),t.at[1]==="bottom"?m.top+=d:t.at[1]==="center"&&(m.top+=d/2),n=h(S.at,l,d),m.left+=n[0],m.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),w=p(this,"marginLeft"),x=p(this,"marginTop"),T=f+w+p(this,"marginRight")+b.width,N=c+x+p(this,"marginBottom")+b.height,C=e.extend({},m),k=h(S.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:w,marginTop:x},e.each(["left","top"],function(r,i){e.ui.position[E[r]]&&e.ui.position[E[r]][i](C,{targetWidth:l,targetHeight:d,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:y,elem:a})}),e.fn.bgiframe&&a.bgiframe(),t.using&&(u=function(e){var n=v.left-C.left,s=n+l-f,o=v.top-C.top,u=o+d-c,h={target:{element:g,left:v.left,top:v.top,width:l,height:d},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),d<c&&i(o+u)<d&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&(r.active===!1||r.active==null)&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.uiBackCompat!==!1&&(function(e,t){e.extend(t.options,{navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}});var n=t._create;t._create=function(){if(this.options.navigation){var t=this,r=this.element.find(this.options.header),i=r.next(),s=r.add(i).find("a").filter(this.options.navigationFilter)[0];s&&r.add(i).each(function(n){if(e.contains(this,s))return t.options.active=Math.floor(n/2),!1})}n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{heightStyle:null,autoHeight:!0,clearStyle:!1,fillSpace:!1});var n=t._create,r=t._setOption;e.extend(t,{_create:function(){this.options.heightStyle=this.options.heightStyle||this._mergeHeightStyle(),n.call(this)},_setOption:function(e){if(e==="autoHeight"||e==="clearStyle"||e==="fillSpace")this.options.heightStyle=this._mergeHeightStyle();r.apply(this,arguments)},_mergeHeightStyle:function(){var e=this.options;if(e.fillSpace)return"fill";if(e.clearStyle)return"content";if(e.autoHeight)return"auto"}})}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options.icons,{activeHeader:null,headerSelected:"ui-icon-triangle-1-s"});var n=t._createIcons;t._createIcons=function(){this.options.icons&&(this.options.icons.activeHeader=this.options.icons.activeHeader||this.options.icons.headerSelected),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){t.activate=t._activate;var n=t._findActive;t._findActive=function(e){return e===-1&&(e=!1),e&&typeof e!="number"&&(e=this.headers.index(this.headers.filter(e)),e===-1&&(e=!1)),n.call(this,e)}}(jQuery,jQuery.ui.accordion.prototype),jQuery.ui.accordion.prototype.resize=jQuery.ui.accordion.prototype.refresh,function(e,t){e.extend(t.options,{change:null,changestart:null});var n=t._trigger;t._trigger=function(e,t,r){var i=n.apply(this,arguments);return i?(e==="beforeActivate"?i=n.call(this,"changestart",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel}):e==="activate"&&(i=n.call(this,"change",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel})),i):!1}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{animate:null,animated:"slide"});var n=t._create;t._create=function(){var e=this.options;e.animate===null&&(e.animated?e.animated==="slide"?e.animate=300:e.animated==="bounceslide"?e.animate={duration:200,down:{easing:"easeOutBounce",duration:1e3}}:e.animate=e.animated:e.animate=!1),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype))})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.9.2",defaultElement:"<input>",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete").appendTo(this.document.find(this.options.appendTo||"body")[0]).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item")||n.item.data("item.autocomplete");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item")||t.item.data("item.autocomplete"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),e.fn.bgiframe&&this.menu.element.bgiframe(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this.document.find(t||"body")[0]),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="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",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).toggleClass("ui-state-active"),t.buttonElement.attr("aria-pressed",t.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.9.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=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 e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function($,undefined){function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.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>'))}function bindHover(e){var t="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(t,"mouseout",function(){$(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).removeClass("ui-datepicker-next-hover")}).delegate(t,"mouseover",function(){$.datepicker._isDisabledDatepicker(instActive.inline?e.parent()[0]:instActive.input[0])||($(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),$(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).addClass("ui-datepicker-next-hover"))})}function extendRemove(e,t){$.extend(e,t);for(var n in t)if(t[n]==null||t[n]==undefined)e[n]=t[n];return e}$.extend($.ui,{datepicker:{version:"1.9.2"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(e,t){var n=e[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:t,dpDiv:t?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(e,t){var n=$(e);t.append=$([]),t.trigger=$([]);if(n.hasClass(this.markerClassName))return;this._attachments(n,t),n.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),this._autoSize(t),$.data(e,PROP_NAME,t),t.settings.disabled&&this._disableDatepicker(e)},_attachments:function(e,t){var n=this._get(t,"appendText"),r=this._get(t,"isRTL");t.append&&t.append.remove(),n&&(t.append=$('<span class="'+this._appendClass+'">'+n+"</span>"),e[r?"before":"after"](t.append)),e.unbind("focus",this._showDatepicker),t.trigger&&t.trigger.remove();var i=this._get(t,"showOn");(i=="focus"||i=="both")&&e.focus(this._showDatepicker);if(i=="button"||i=="both"){var s=this._get(t,"buttonText"),o=this._get(t,"buttonImage");t.trigger=$(this._get(t,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:o,alt:s,title:s}):$('<button type="button"></button>').addClass(this._triggerClass).html(o==""?s:$("<img/>").attr({src:o,alt:s,title:s}))),e[r?"before":"after"](t.trigger),t.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==e[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=e[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(e[0])):$.datepicker._showDatepicker(e[0]),!1})}},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t=new Date(2009,11,20),n=this._get(e,"dateFormat");if(n.match(/[DM]/)){var r=function(e){var t=0,n=0;for(var r=0;r<e.length;r++)e[r].length>t&&(t=e[r].length,n=r);return n};t.setMonth(r(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),t.setDate(r(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-t.getDay())}e.input.attr("size",this._formatDate(e,t).length)}},_inlineDatepicker:function(e,t){var n=$(e);if(n.hasClass(this.markerClassName))return;n.addClass(this.markerClassName).append(t.dpDiv).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),$.data(e,PROP_NAME,t),this._setDate(t,this._getDefaultDate(t),!0),this._updateDatepicker(t),this._updateAlternate(t),t.settings.disabled&&this._disableDatepicker(e),t.dpDiv.css("display","block")},_dialogDatepicker:function(e,t,n,r,i){var s=this._dialogInst;if(!s){this.uuid+=1;var o="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+o+'" style="position: absolute; top: -100px; width: 0px;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),s=this._dialogInst=this._newInst(this._dialogInput,!1),s.settings={},$.data(this._dialogInput[0],PROP_NAME,s)}extendRemove(s.settings,r||{}),t=t&&t.constructor==Date?this._formatDate(s,t):t,this._dialogInput.val(t),this._pos=i?i.length?i:[i.pageX,i.pageY]:null;if(!this._pos){var u=document.documentElement.clientWidth,a=document.documentElement.clientHeight,f=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[u/2-100+f,a/2-150+l]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),s.settings.onSelect=n,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,s),this},_destroyDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();$.removeData(e,PROP_NAME),r=="input"?(n.append.remove(),n.trigger.remove(),t.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r=="div"||r=="span")&&t.removeClass(this.markerClassName).empty()},_enableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t})},_disableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t}),this._disabledInputs[this._disabledInputs.length]=e},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]==e)return!0;return!1},_getInst:function(e){try{return $.data(e,PROP_NAME)}catch(t){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,t,n){var r=this._getInst(e);if(arguments.length==2&&typeof t=="string")return t=="defaults"?$.extend({},$.datepicker._defaults):r?t=="all"?$.extend({},r.settings):this._get(r,t):null;var i=t||{};typeof t=="string"&&(i={},i[t]=n);if(r){this._curInst==r&&this._hideDatepicker();var s=this._getDateDatepicker(e,!0),o=this._getMinMaxDate(r,"min"),u=this._getMinMaxDate(r,"max");extendRemove(r.settings,i),o!==null&&i.dateFormat!==undefined&&i.minDate===undefined&&(r.settings.minDate=this._formatDate(r,o)),u!==null&&i.dateFormat!==undefined&&i.maxDate===undefined&&(r.settings.maxDate=this._formatDate(r,u)),this._attachments($(e),r),this._autoSize(r),this._setDate(r,s),this._updateAlternate(r),this._updateDatepicker(r)}},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(e){var t=$.datepicker._getInst(e.target),n=!0,r=t.dpDiv.is(".ui-datepicker-rtl");t._keyEvent=!0;if($.datepicker._datepickerShowing)switch(e.keyCode){case 9:$.datepicker._hideDatepicker(),n=!1;break;case 13:var i=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",t.dpDiv);i[0]&&$.datepicker._selectDay(e.target,t.selectedMonth,t.selectedYear,i[0]);var s=$.datepicker._get(t,"onSelect");if(s){var o=$.datepicker._formatDate(t);s.apply(t.input?t.input[0]:null,[o,t])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&$.datepicker._clearDate(e.target),n=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&$.datepicker._gotoToday(e.target),n=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?1:-1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,-7,"D"),n=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?-1:1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,7,"D"),n=e.ctrlKey||e.metaKey;break;default:n=!1}else e.keyCode==36&&e.ctrlKey?$.datepicker._showDatepicker(this):n=!1;n&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var t=$.datepicker._getInst(e.target);if($.datepicker._get(t,"constrainInput")){var n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=String.fromCharCode(e.charCode==undefined?e.keyCode:e.charCode);return e.ctrlKey||e.metaKey||r<" "||!n||n.indexOf(r)>-1}},_doKeyUp:function(e){var t=$.datepicker._getInst(e.target);if(t.input.val()!=t.lastVal)try{var n=$.datepicker.parseDate($.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,$.datepicker._getFormatConfig(t));n&&($.datepicker._setDateFromField(t),$.datepicker._updateAlternate(t),$.datepicker._updateDatepicker(t))}catch(r){$.datepicker.log(r)}return!0},_showDatepicker:function(e){e=e.target||e,e.nodeName.toLowerCase()!="input"&&(e=$("input",e.parentNode)[0]);if($.datepicker._isDisabledDatepicker(e)||$.datepicker._lastInput==e)return;var t=$.datepicker._getInst(e);$.datepicker._curInst&&$.datepicker._curInst!=t&&($.datepicker._curInst.dpDiv.stop(!0,!0),t&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var n=$.datepicker._get(t,"beforeShow"),r=n?n.apply(e,[e,t]):{};if(r===!1)return;extendRemove(t.settings,r),t.lastVal=null,$.datepicker._lastInput=e,$.datepicker._setDateFromField(t),$.datepicker._inDialog&&(e.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(e),$.datepicker._pos[1]+=e.offsetHeight);var i=!1;$(e).parents().each(function(){return i|=$(this).css("position")=="fixed",!i});var s={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,t.dpDiv.empty(),t.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(t),s=$.datepicker._checkOffset(t,s,i),t.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":i?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"});if(!t.inline){var o=$.datepicker._get(t,"showAnim"),u=$.datepicker._get(t,"duration"),a=function(){var e=t.dpDiv.find("iframe.ui-datepicker-cover");if(!!e.length){var n=$.datepicker._getBorders(t.dpDiv);e.css({left:-n[0],top:-n[1],width:t.dpDiv.outerWidth(),height:t.dpDiv.outerHeight()})}};t.dpDiv.zIndex($(e).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&($.effects.effect[o]||$.effects[o])?t.dpDiv.show(o,$.datepicker._get(t,"showOptions"),u,a):t.dpDiv[o||"show"](o?u:null,a),(!o||!u)&&a(),t.input.is(":visible")&&!t.input.is(":disabled")&&t.input.focus(),$.datepicker._curInst=t}},_updateDatepicker:function(e){this.maxRows=4;var t=$.datepicker._getBorders(e.dpDiv);instActive=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var n=e.dpDiv.find("iframe.ui-datepicker-cover");!n.length||n.css({left:-t[0],top:-t[1],width:e.dpDiv.outerWidth(),height:e.dpDiv.outerHeight()}),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var r=this._getNumberOfMonths(e),i=r[1],s=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),i>1&&e.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",s*i+"em"),e.dpDiv[(r[0]!=1||r[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e==$.datepicker._curInst&&$.datepicker._datepickerShowing&&e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&e.input[0]!=document.activeElement&&e.input.focus();if(e.yearshtml){var o=e.yearshtml;setTimeout(function(){o===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),o=e.yearshtml=null},0)}},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(e,t,n){var r=e.dpDiv.outerWidth(),i=e.dpDiv.outerHeight(),s=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,u=document.documentElement.clientWidth+(n?0:$(document).scrollLeft()),a=document.documentElement.clientHeight+(n?0:$(document).scrollTop());return t.left-=this._get(e,"isRTL")?r-s:0,t.left-=n&&t.left==e.input.offset().left?$(document).scrollLeft():0,t.top-=n&&t.top==e.input.offset().top+o?$(document).scrollTop():0,t.left-=Math.min(t.left,t.left+r>u&&u>r?Math.abs(t.left+r-u):0),t.top-=Math.min(t.top,t.top+i>a&&a>i?Math.abs(i+o):0),t},_findPos:function(e){var t=this._getInst(e),n=this._get(t,"isRTL");while(e&&(e.type=="hidden"||e.nodeType!=1||$.expr.filters.hidden(e)))e=e[n?"previousSibling":"nextSibling"];var r=$(e).offset();return[r.left,r.top]},_hideDatepicker:function(e){var t=this._curInst;if(!t||e&&t!=$.data(e,PROP_NAME))return;if(this._datepickerShowing){var n=this._get(t,"showAnim"),r=this._get(t,"duration"),i=function(){$.datepicker._tidyDialog(t)};$.effects&&($.effects.effect[n]||$.effects[n])?t.dpDiv.hide(n,$.datepicker._get(t,"showOptions"),r,i):t.dpDiv[n=="slideDown"?"slideUp":n=="fadeIn"?"fadeOut":"hide"](n?r:null,i),n||i(),this._datepickerShowing=!1;var s=this._get(t,"onClose");s&&s.apply(t.input?t.input[0]:null,[t.input?t.input.val():"",t]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(!$.datepicker._curInst)return;var t=$(e.target),n=$.datepicker._getInst(t[0]);(t[0].id!=$.datepicker._mainDivId&&t.parents("#"+$.datepicker._mainDivId).length==0&&!t.hasClass($.datepicker.markerClassName)&&!t.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||t.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=n)&&$.datepicker._hideDatepicker()},_adjustDate:function(e,t,n){var r=$(e),i=this._getInst(r[0]);if(this._isDisabledDatepicker(r[0]))return;this._adjustInstDate(i,t+(n=="M"?this._get(i,"showCurrentAtPos"):0),n),this._updateDatepicker(i)},_gotoToday:function(e){var t=$(e),n=this._getInst(t[0]);if(this._get(n,"gotoCurrent")&&n.currentDay)n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear;else{var r=new Date;n.selectedDay=r.getDate(),n.drawMonth=n.selectedMonth=r.getMonth(),n.drawYear=n.selectedYear=r.getFullYear()}this._notifyChange(n),this._adjustDate(t)},_selectMonthYear:function(e,t,n){var r=$(e),i=this._getInst(r[0]);i["selected"+(n=="M"?"Month":"Year")]=i["draw"+(n=="M"?"Month":"Year")]=parseInt(t.options[t.selectedIndex].value,10),this._notifyChange(i),this._adjustDate(r)},_selectDay:function(e,t,n,r){var i=$(e);if($(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(i[0]))return;var s=this._getInst(i[0]);s.selectedDay=s.currentDay=$("a",r).html(),s.selectedMonth=s.currentMonth=t,s.selectedYear=s.currentYear=n,this._selectDate(e,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(e){var t=$(e),n=this._getInst(t[0]);this._selectDate(t,"")},_selectDate:function(e,t){var n=$(e),r=this._getInst(n[0]);t=t!=null?t:this._formatDate(r),r.input&&r.input.val(t),this._updateAlternate(r);var i=this._get(r,"onSelect");i?i.apply(r.input?r.input[0]:null,[t,r]):r.input&&r.input.trigger("change"),r.inline?this._updateDatepicker(r):(this._hideDatepicker(),this._lastInput=r.input[0],typeof r.input[0]!="object"&&r.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var t=this._get(e,"altField");if(t){var n=this._get(e,"altFormat")||this._get(e,"dateFormat"),r=this._getDate(e),i=this.formatDate(n,r,this._getFormatConfig(e));$(t).each(function(){$(this).val(i)})}},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t=new Date(e.getTime());t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1},parseDate:function(e,t,n){if(e==null||t==null)throw"Invalid arguments";t=typeof t=="object"?t.toString():t+"";if(t=="")return null;var r=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff;r=typeof r!="string"?r:(new Date).getFullYear()%100+parseInt(r,10);var i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=-1,f=-1,l=-1,c=-1,h=!1,p=function(t){var n=y+1<e.length&&e.charAt(y+1)==t;return n&&y++,n},d=function(e){var n=p(e),r=e=="@"?14:e=="!"?20:e=="y"&&n?4:e=="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=t.substring(g).match(i);if(!s)throw"Missing number at position "+g;return g+=s[0].length,parseInt(s[0],10)},v=function(e,n,r){var i=$.map(p(e)?r:n,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)}),s=-1;$.each(i,function(e,n){var r=n[1];if(t.substr(g,r.length).toLowerCase()==r.toLowerCase())return s=n[0],g+=r.length,!1});if(s!=-1)return s+1;throw"Unknown name at position "+g},m=function(){if(t.charAt(g)!=e.charAt(y))throw"Unexpected literal at position "+g;g++},g=0;for(var y=0;y<e.length;y++)if(h)e.charAt(y)=="'"&&!p("'")?h=!1:m();else switch(e.charAt(y)){case"d":l=d("d");break;case"D":v("D",i,s);break;case"o":c=d("o");break;case"m":f=d("m");break;case"M":f=v("M",o,u);break;case"y":a=d("y");break;case"@":var b=new Date(d("@"));a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"!":var b=new Date((d("!")-this._ticksTo1970)/1e4);a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"'":p("'")?m():h=!0;break;default:m()}if(g<t.length){var w=t.substr(g);if(!/^\s+/.test(w))throw"Extra/unparsed characters found in date: "+w}a==-1?a=(new Date).getFullYear():a<100&&(a+=(new Date).getFullYear()-(new Date).getFullYear()%100+(a<=r?0:-100));if(c>-1){f=1,l=c;do{var E=this._getDaysInMonth(a,f-1);if(l<=E)break;f++,l-=E}while(!0)}var b=this._daylightSavingAdjust(new Date(a,f-1,l));if(b.getFullYear()!=a||b.getMonth()+1!=f||b.getDate()!=l)throw"Invalid date";return b},ATOM:"yy-mm-dd",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",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,i=(n?n.dayNames:null)||this._defaults.dayNames,s=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,o=(n?n.monthNames:null)||this._defaults.monthNames,u=function(t){var n=h+1<e.length&&e.charAt(h+1)==t;return n&&h++,n},a=function(e,t,n){var r=""+t;if(u(e))while(r.length<n)r="0"+r;return r},f=function(e,t,n,r){return u(e)?r[t]:n[t]},l="",c=!1;if(t)for(var h=0;h<e.length;h++)if(c)e.charAt(h)=="'"&&!u("'")?c=!1:l+=e.charAt(h);else switch(e.charAt(h)){case"d":l+=a("d",t.getDate(),2);break;case"D":l+=f("D",t.getDay(),r,i);break;case"o":l+=a("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":l+=a("m",t.getMonth()+1,2);break;case"M":l+=f("M",t.getMonth(),s,o);break;case"y":l+=u("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=t.getTime()*1e4+this._ticksTo1970;break;case"'":u("'")?l+="'":c=!0;break;default:l+=e.charAt(h)}return l},_possibleChars:function(e){var t="",n=!1,r=function(t){var n=i+1<e.length&&e.charAt(i+1)==t;return n&&i++,n};for(var i=0;i<e.length;i++)if(n)e.charAt(i)=="'"&&!r("'")?n=!1:t+=e.charAt(i);else switch(e.charAt(i)){case"d":case"m":case"y":case"@":t+="0123456789";break;case"D":case"M":return null;case"'":r("'")?t+="'":n=!0;break;default:t+=e.charAt(i)}return t},_get:function(e,t){return e.settings[t]!==undefined?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()==e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i,s;i=s=this._getDefaultDate(e);var o=this._getFormatConfig(e);try{i=this.parseDate(n,r,o)||s}catch(u){this.log(u),r=t?"":r}e.selectedDay=i.getDate(),e.drawMonth=e.selectedMonth=i.getMonth(),e.drawYear=e.selectedYear=i.getFullYear(),e.currentDay=r?i.getDate():0,e.currentMonth=r?i.getMonth():0,e.currentYear=r?i.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(e,t,n){var r=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},i=function(t){try{return $.datepicker.parseDate($.datepicker._get(e,"dateFormat"),t,$.datepicker._getFormatConfig(e))}catch(n){}var r=(t.toLowerCase().match(/^c/)?$.datepicker._getDate(e):null)||new Date,i=r.getFullYear(),s=r.getMonth(),o=r.getDate(),u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,a=u.exec(t);while(a){switch(a[2]||"d"){case"d":case"D":o+=parseInt(a[1],10);break;case"w":case"W":o+=parseInt(a[1],10)*7;break;case"m":case"M":s+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s));break;case"y":case"Y":i+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s))}a=u.exec(t)}return new Date(i,s,o)},s=t==null||t===""?n:typeof t=="string"?i(t):typeof t=="number"?isNaN(t)?n:r(t):new Date(t.getTime());return s=s&&s.toString()=="Invalid Date"?n:s,s&&(s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)),this._daylightSavingAdjust(s)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!=e.selectedMonth||s!=e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()==""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(e){var t=this._get(e,"stepMonths"),n="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,-t,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,+t,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(n)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(n,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t=new Date;t=this._daylightSavingAdjust(new Date(t.getFullYear(),t.getMonth(),t.getDate()));var n=this._get(e,"isRTL"),r=this._get(e,"showButtonPanel"),i=this._get(e,"hideIfNoPrevNext"),s=this._get(e,"navigationAsDateFormat"),o=this._getNumberOfMonths(e),u=this._get(e,"showCurrentAtPos"),a=this._get(e,"stepMonths"),f=o[0]!=1||o[1]!=1,l=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),c=this._getMinMaxDate(e,"min"),h=this._getMinMaxDate(e,"max"),p=e.drawMonth-u,d=e.drawYear;p<0&&(p+=12,d--);if(h){var v=this._daylightSavingAdjust(new Date(h.getFullYear(),h.getMonth()-o[0]*o[1]+1,h.getDate()));v=c&&v<c?c:v;while(this._daylightSavingAdjust(new Date(d,p,1))>v)p--,p<0&&(p=11,d--)}e.drawMonth=p,e.drawYear=d;var m=this._get(e,"prevText");m=s?this.formatDate(m,this._daylightSavingAdjust(new Date(d,p-a,1)),this._getFormatConfig(e)):m;var g=this._canAdjustMonth(e,-1,d,p)?'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>":i?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>",y=this._get(e,"nextText");y=s?this.formatDate(y,this._daylightSavingAdjust(new Date(d,p+a,1)),this._getFormatConfig(e)):y;var b=this._canAdjustMonth(e,1,d,p)?'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>":i?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>",w=this._get(e,"currentText"),E=this._get(e,"gotoCurrent")&&e.currentDay?l:t;w=s?this.formatDate(w,E,this._getFormatConfig(e)):w;var S=e.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(e,"closeText")+"</button>",x=r?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(n?S:"")+(this._isInRange(e,E)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click">'+w+"</button>":"")+(n?"":S)+"</div>":"",T=parseInt(this._get(e,"firstDay"),10);T=isNaN(T)?0:T;var N=this._get(e,"showWeek"),C=this._get(e,"dayNames"),k=this._get(e,"dayNamesShort"),L=this._get(e,"dayNamesMin"),A=this._get(e,"monthNames"),O=this._get(e,"monthNamesShort"),M=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),D=this._get(e,"selectOtherMonths"),P=this._get(e,"calculateWeek")||this.iso8601Week,H=this._getDefaultDate(e),B="";for(var j=0;j<o[0];j++){var F="";this.maxRows=4;for(var I=0;I<o[1];I++){var q=this._daylightSavingAdjust(new Date(d,p,e.selectedDay)),R=" ui-corner-all",U="";if(f){U+='<div class="ui-datepicker-group';if(o[1]>1)switch(I){case 0:U+=" ui-datepicker-group-first",R=" ui-corner-"+(n?"right":"left");break;case o[1]-1:U+=" ui-datepicker-group-last",R=" ui-corner-"+(n?"left":"right");break;default:U+=" ui-datepicker-group-middle",R=""}U+='">'}U+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+R+'">'+(/all|left/.test(R)&&j==0?n?b:g:"")+(/all|right/.test(R)&&j==0?n?g:b:"")+this._generateMonthYearHeader(e,p,d,c,h,j>0||I>0,A,O)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var z=N?'<th class="ui-datepicker-week-col">'+this._get(e,"weekHeader")+"</th>":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="<th"+((W+T+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+C[X]+'">'+L[X]+"</span></th>"}U+=z+"</tr></thead><tbody>";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y<Q;Y++){U+="<tr>";var Z=N?'<td class="ui-datepicker-week-col">'+this._get(e,"calculateWeek")(G)+"</td>":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&G<c||h&&G>h;Z+='<td class="'+((W+T+6)%7>=5?" ui-datepicker-week-end":"")+(tt?" ui-datepicker-other-month":"")+(G.getTime()==q.getTime()&&p==e.selectedMonth&&e._keyEvent||H.getTime()==G.getTime()&&H.getTime()==q.getTime()?" "+this._dayOverClass:"")+(nt?" "+this._unselectableClass+" ui-state-disabled":"")+(tt&&!_?"":" "+et[1]+(G.getTime()==l.getTime()?" "+this._currentClass:"")+(G.getTime()==t.getTime()?" ui-datepicker-today":""))+'"'+((!tt||_)&&et[2]?' title="'+et[2]+'"':"")+(nt?"":' data-handler="selectDay" data-event="click" data-month="'+G.getMonth()+'" data-year="'+G.getFullYear()+'"')+">"+(tt&&!_?"&#xa0;":nt?'<span class="ui-state-default">'+G.getDate()+"</span>":'<a class="ui-state-default'+(G.getTime()==t.getTime()?" ui-state-highlight":"")+(G.getTime()==l.getTime()?" ui-state-active":"")+(tt?" ui-priority-secondary":"")+'" href="#">'+G.getDate()+"</a>")+"</td>",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+"</tr>"}p++,p>11&&(p=0,d++),U+="</tbody></table>"+(f?"</div>"+(o[0]>0&&I==o[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='<div class="ui-datepicker-title">',h="";if(s||!a)h+='<span class="ui-datepicker-month">'+o[t]+"</span>";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';for(var v=0;v<12;v++)(!p||v>=r.getMonth())&&(!d||v<=i.getMonth())&&(h+='<option value="'+v+'"'+(v==t?' selected="selected"':"")+">"+u[v]+"</option>");h+="</select>"}l||(c+=h+(s||!a||!f?"&#xa0;":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+='<span class="ui-datepicker-year">'+n+"</span>";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';for(;b<=w;b++)e.yearshtml+='<option value="'+b+'"'+(b==n?' selected="selected"':"")+">"+b+"</option>";e.yearshtml+="</select>",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?"&#xa0;":"")+h),c+="</div>",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return i=r&&i>r?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||"&#160;",s,o,u,a,f;s=(this.uiDialog=e("<div>")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("<div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("<a href='#'></a>").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("<span>")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("<span>").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("<div>")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("<div>")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("<button></button>",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||"&#160;"))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()<e.ui.dialog.overlay.maxZ)return!1})},1),e(window).bind("resize.dialog-overlay",e.ui.dialog.overlay.resize));var n=this.oldInstances.pop()||e("<div>").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t<n?e(window).height()+"px":t+"px"):e(document).height()+"px"},width:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),n=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),t<n?e(window).width()+"px":t+"px"):e(document).width()+"px"},resize:function(){var t=e([]);e.each(e.ui.dialog.overlay.instances,function(){t=t.add(this)}),t.css({width:0,height:0}).css({width:e.ui.dialog.overlay.width(),height:e.ui.dialog.overlay.height()})}}),e.extend(e.ui.dialog.overlay.prototype,{destroy:function(){e.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),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(t){var n=this.options;return this.helper||n.disabled||e(t.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.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";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}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 t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.left<u[0]&&(s=u[0]+this.offset.click.left),t.pageY-this.offset.click.top<u[1]&&(o=u[1]+this.offset.click.top),t.pageX-this.offset.click.left>u[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.top<u[1]||f-this.offset.click.top>u[3]?f-this.offset.click.top<u[1]?f+n.grid[1]:f-n.grid[1]:f:f;var l=n.grid[0]?this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX;s=u?l-this.offset.click.left<u[0]||l-this.offset.click.left>u[2]?l-this.offset.click.left<u[0]?l+n.grid[0]:l-n.grid[0]:l:l}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(e){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("draggable"),i=this,s=function(t){var n=this.offset.click.top,r=this.offset.click.left,i=this.positionAbs.top,s=this.positionAbs.left,o=t.height,u=t.width,a=t.top,f=t.left;return e.ui.isOver(i+n,s+r,a,f,o,u)};e.each(r.sortables,function(s){var o=!1,u=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!=u&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(u.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,n){var r=e("body"),i=e(this).data("draggable").options;r.css("cursor")&&(i._cursor=r.css("cursor")),r.css("cursor",i.cursor)},stop:function(t,n){var r=e(this).data("draggable").options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(t,n){var r=e(this).data("draggable");r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"&&(r.overflowOffset=r.scrollParent.offset())},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=!1;if(r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"){if(!i.axis||i.axis!="x")r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY<i.scrollSensitivity?r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop+i.scrollSpeed:t.pageY-r.overflowOffset.top<i.scrollSensitivity&&(r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop-i.scrollSpeed);if(!i.axis||i.axis!="y")r.overflowOffset.left+r.scrollParent[0].offsetWidth-t.pageX<i.scrollSensitivity?r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft+i.scrollSpeed:t.pageX-r.overflowOffset.left<i.scrollSensitivity&&(r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft-i.scrollSpeed)}else{if(!i.axis||i.axis!="x")t.pageY-e(document).scrollTop()<i.scrollSensitivity?s=e(document).scrollTop(e(document).scrollTop()-i.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<i.scrollSensitivity&&(s=e(document).scrollTop(e(document).scrollTop()+i.scrollSpeed));if(!i.axis||i.axis!="y")t.pageX-e(document).scrollLeft()<i.scrollSensitivity?s=e(document).scrollLeft(e(document).scrollLeft()-i.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<i.scrollSensitivity&&(s=e(document).scrollLeft(e(document).scrollLeft()+i.scrollSpeed))}s!==!1&&e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(r,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,n){var r=e(this).data("draggable"),i=r.options;r.snapElements=[],e(i.snap.constructor!=String?i.snap.items||":data(draggable)":i.snap).each(function(){var t=e(this),n=t.offset();this!=r.element[0]&&r.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:n.top,left:n.left})})},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=i.snapTolerance,o=n.offset.left,u=o+r.helperProportions.width,a=n.offset.top,f=a+r.helperProportions.height;for(var l=r.snapElements.length-1;l>=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s<o&&o<h+s&&p-s<a&&a<d+s||c-s<o&&o<h+s&&p-s<f&&f<d+s||c-s<u&&u<h+s&&p-s<a&&a<d+s||c-s<u&&u<h+s&&p-s<f&&f<d+s)){r.snapElements[l].snapping&&r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=!1;continue}if(i.snapMode!="inner"){var v=Math.abs(p-f)<=s,m=Math.abs(d-a)<=s,g=Math.abs(c-u)<=s,y=Math.abs(h-o)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p-r.helperProportions.height,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c-r.helperProportions.width}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h}).left-r.margins.left)}var b=v||m||g||y;if(i.snapMode!="outer"){var v=Math.abs(p-a)<=s,m=Math.abs(d-f)<=s,g=Math.abs(c-o)<=s,y=Math.abs(h-u)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d-r.helperProportions.height,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h-r.helperProportions.width}).left-r.margins.left)}!r.snapElements[l].snapping&&(v||m||g||y||b)&&r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=v||m||g||y||b}}}),e.ui.plugin.add("draggable","stack",{start:function(t,n){var r=e(this).data("draggable").options,i=e.makeArray(e(r.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!i.length)return;var s=parseInt(i[0].style.zIndex)||0;e(i).each(function(e){this.style.zIndex=s+e}),this[0].style.zIndex=s+i.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){e.widget("ui.droppable",{version:"1.9.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var t=this.options,n=t.accept;this.isover=0,this.isout=1,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];for(var n=0;n<t.length;n++)t[n]==this&&t.splice(n,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t=="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current;if(!r||(r.currentItem||r.element)[0]==this.element[0])return!1;var i=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope==r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(t,n,r){if(!n.offset)return!1;var i=(t.positionAbs||t.position.absolute).left,s=i+t.helperProportions.width,o=(t.positionAbs||t.position.absolute).top,u=o+t.helperProportions.height,a=n.offset.left,f=a+n.proportions.width,l=n.offset.top,c=l+n.proportions.height;switch(r){case"fit":return a<=i&&s<=f&&l<=o&&u<=c;case"intersect":return a<i+t.helperProportions.width/2&&s-t.helperProportions.width/2<f&&l<o+t.helperProportions.height/2&&u-t.helperProportions.height/2<c;case"pointer":var h=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,p=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,d=e.ui.isOver(p,h,l,a,n.proportions.height,n.proportions.width);return d;case"touch":return(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c)&&(i>=a&&i<=f||s>=a&&s<=f||i<a&&s>f);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;o<r.length;o++){if(r[o].options.disabled||t&&!r[o].accept.call(r[o].element[0],t.currentItem||t.element))continue;for(var u=0;u<s.length;u++)if(s[u]==r[o].element[0]){r[o].proportions.height=0;continue e}r[o].visible=r[o].element.css("display")!="none";if(!r[o].visible)continue;i=="mousedown"&&r[o]._activate.call(r[o],n),r[o].offset=r[o].element.offset(),r[o].proportions={width:r[o].element[0].offsetWidth,height:r[o].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r=e.ui.intersect(t,this,this.options.tolerance),i=!r&&this.isover==1?"isout":r&&this.isover==0?"isover":null;if(!i)return;var s;if(this.options.greedy){var o=this.options.scope,u=this.element.parents(":data(droppable)").filter(function(){return e.data(this,"droppable").options.scope===o});u.length&&(s=e.data(u[0],"droppable"),s.greedyChild=i=="isover"?1:0)}s&&i=="isover"&&(s.isover=0,s.isout=1,s._out.call(s,n)),this[i]=1,this[i=="isout"?"isover":"isout"]=0,this[i=="isover"?"_over":"_out"].call(this,n),s&&i=="isout"&&(s.isout=0,s.isover=1,s._over.call(s,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function d(e){var n=o(),r=n._rgba=[];return e=e.toLowerCase(),h(s,function(t,i){var s,o=i.re.exec(e),a=o&&i.parse(o),f=i.space||"rgba";if(a)return s=n[f](a),n[u[f].cache]=s[u[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&t.extend(r,c.transparent),n):c[e]}function v(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var r="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),i=/^([\-+])=\s*(\d+\.?\d*)/,s=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],o=t.Color=function(e,n,r,i){return new t.Color.fn.parse(e,n,r,i)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},a={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},f=o.support={},l=t("<p>")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n<t.length;n++)t[n]!==null&&e.data(r+t[n],e[0].style[t[n]])},restore:function(e,n){var i,s;for(s=0;s<n.length;s++)n[s]!==null&&(i=e.data(r+n[s]),i===t&&(i=""),e.css(n[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m<l;m++)g={},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p).animate(y,h,p),f=o?f*2:f/2;o&&(g={opacity:0},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p)),r.queue(function(){o&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),w>1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h<r;h++){v=a.top+h*l,g=h-(r-1)/2;for(p=0;p<i;p++)d=a.left+p*f,m=p-(i-1)/2,s.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m<a;m++)r.animate(d,l,t.easing).animate(v,l,t.easing);r.animate(d,l,t.easing).animate(p,l/2,t.easing).queue(function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),y>1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){e.widget("ui.progressbar",{version:"1.9.2",options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,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}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{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"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i<r.length;i++){var s=e.trim(r[i]),o="ui-resizable-"+s,u=e('<div class="ui-resizable-handle '+o+'"></div>');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),i<u.maxWidth&&(u.maxWidth=i),o<u.maxHeight&&(u.maxHeight=o);this._vBoundaries=u},_updateCache:function(e){var t=this.options;this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e,t){var n=this.options,i=this.position,s=this.size,o=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),o=="sw"&&(e.left=i.left+(s.width-e.width),e.top=null),o=="nw"&&(e.top=i.top+(s.height-e.height),e.left=i.left+(s.width-e.width)),e},_respectSize:function(e,t){var n=this.helper,i=this._vBoundaries,s=this._aspectRatio||t.shiftKey,o=this.axis,u=r(e.width)&&i.maxWidth&&i.maxWidth<e.width,a=r(e.height)&&i.maxHeight&&i.maxHeight<e.height,f=r(e.width)&&i.minWidth&&i.minWidth>e.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r<this._proportionallyResizeElements.length;r++){var i=this._proportionallyResizeElements[r];if(!this.borderDif){var s=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],o=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];this.borderDif=e.map(s,function(e,t){var n=parseInt(e,10)||0,r=parseInt(o[t],10)||0;return n+r})}i.css({height:n.height()-this.borderDif[0]-this.borderDif[2]||0,width:n.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,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}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.right<i||a.top>u||a.bottom<s):r.tolerance=="fit"&&(f=a.left>i&&a.right<o&&a.top>s&&a.bottom<u),f?(a.selected&&(a.$element.removeClass("ui-selected"),a.selected=!1),a.unselecting&&(a.$element.removeClass("ui-unselecting"),a.unselecting=!1),a.selecting||(a.$element.addClass("ui-selecting"),a.selecting=!0,n._trigger("selecting",t,{selecting:a.element}))):(a.selecting&&((t.metaKey||t.ctrlKey)&&a.startselected?(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.$element.addClass("ui-selected"),a.selected=!0):(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.startselected&&(a.$element.addClass("ui-unselecting"),a.unselecting=!0),n._trigger("unselecting",t,{unselecting:a.element}))),a.selected&&!t.metaKey&&!t.ctrlKey&&!a.startselected&&(a.$element.removeClass("ui-selected"),a.selected=!1,a.$element.addClass("ui-unselecting"),a.unselecting=!0,n._trigger("unselecting",t,{unselecting:a.element})))}),!1},_mouseStop:function(t){var n=this;this.dragged=!1;var r=this.options;return e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var t,r,i=this.options,s=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",u=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(i.disabled?" ui-slider-disabled ui-disabled":"")),this.range=e([]),i.range&&(i.range===!0&&(i.values||(i.values=[this._valueMin(),this._valueMin()]),i.values.length&&i.values.length!==2&&(i.values=[i.values[0],i.values[0]])),this.range=e("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;t<r;t++)u.push(o);this.handles=s.add(e(u.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(e){e.preventDefault()}).mouseenter(function(){i.disabled||e(this).addClass("ui-state-hover")}).mouseleave(function(){e(this).removeClass("ui-state-hover")}).focus(function(){i.disabled?e(this).blur():(e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),e(this).addClass("ui-state-focus"))}).blur(function(){e(this).removeClass("ui-state-focus")}),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)}),this._on(this.handles,{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}),this._refreshValue(),this._animateOff=!1},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));i>n&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"disabled":n?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.prop("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.prop("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?r=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(r=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?r=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(r=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)}this.positionAbs=this._convertPositionTo("absolute");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";for(var i=this.items.length-1;i>=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(t){var n=this.options.axis==="x"||e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),r=this.options.axis==="y"||e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),i=n&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o=="right"||s=="down"?2:1:s&&(s=="down"?2:1):!1},_intersectsWithSides:function(t){var n=e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),r=e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s=="right"&&r||s=="left"&&!r:i&&(i=="down"&&n||i=="up"&&!n)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!=0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]==e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n=this.items,r=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],i=this._connectWith();if(i&&this.ready)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u<c;u++){var h=e(l[u]);h.data(this.widgetName+"-item",f),n.push({item:h,instance:f,width:0,height:0,left:0,top:0})}}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var n=this.items.length-1;n>=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)<s&&(s=Math.abs(c-f),o=this.items[l],this.direction=h?"up":"down")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.top<this.containment[1]||u-this.offset.click.top>this.containment[3]?u-this.offset.click.top<this.containment[1]?u+n.grid[1]:u-n.grid[1]:u:u;var a=this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0];s=this.containment?a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2]?a-this.offset.click.left<this.containment[0]?a+n.grid[0]:a-n.grid[0]:a:a}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i==this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS)if(this._storedCSS[i]=="auto"||this._storedCSS[i]=="static")this._storedCSS[i]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!n&&r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(var i=this.containers.length-1;i>=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.9.2",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e<r.min?r.min:e},_stop:function(e){if(!this.spinning)return;clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e)},_setOption:function(e,t){if(e==="culture"||e==="numberFormat"){var n=this._parse(this.element.val());this.options[e]=t,this.element.val(this._format(n));return}(e==="max"||e==="min"||e==="step")&&typeof t=="string"&&(t=this._parse(t)),this._super(e,t),e==="disabled"&&(t?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:t(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return typeof e=="string"&&e!==""&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),e===""||isNaN(e)?null:e},_format:function(e){return e===""?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(e,t){var n;e!==""&&(n=this._parse(e),n!==null&&(t||(n=this._adjustValue(n)),e=this._format(n))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:t(function(e){this._stepUp(e)}),_stepUp:function(e){this._spin((e||1)*this.options.step)},stepDown:t(function(e){this._stepDown(e)}),_stepDown:function(e){this._spin((e||1)*-this.options.step)},pageUp:t(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:t(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){if(!arguments.length)return this._parse(this.element.val());t(this._value).call(this,e)},widget:function(){return this.uiSpinner}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.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"}),this.active.length?(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"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=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 e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){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").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(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 t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"<em>Loading&#8230;</em>"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1<this.anchors.length?1:-1)),n.disabled=e.map(e.grep(n.disabled,function(e){return e!==t}),function(e){return e>=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"<div></div>"},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.cookie.1.0.0.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.cookie.1.0.0.js
new file mode 100644
index 000000000..61d3bcef2
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.cookie.1.0.0.js
@@ -0,0 +1,91 @@
+/*jslint browser: true */ /*global jQuery: true */
+
+/**
+ * jQuery Cookie plugin
+ *
+ * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+// TODO JsDoc
+
+/**
+ * Create a cookie with the given key and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ * used when the cookie was set.
+ *
+ * @param String key The key of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
+ * when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ * require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given key.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String key The key of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function (key, value, options) {
+
+ // key and at least value given, set cookie...
+ if (arguments.length > 1 && String(value) !== "[object Object]") {
+ options = jQuery.extend({}, options);
+
+ if (value === null || value === undefined) {
+ options.expires = -1;
+ }
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setDate(t.getDate() + days);
+ }
+
+ value = String(value);
+
+ return (document.cookie = [
+ encodeURIComponent(key), '=',
+ options.raw ? value : encodeURIComponent(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // key and possibly options given, get cookie...
+ options = value || {};
+ var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
+ return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
+};
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-5.10.0.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-5.10.0.js
new file mode 100644
index 000000000..8fb856265
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-5.10.0.js
@@ -0,0 +1,905 @@
+/*
+ * jQuery File Upload Plugin 5.10.0
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint nomen: true, unparam: true, regexp: true */
+/*global define, window, document, Blob, FormData, location */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ 'jquery',
+ 'jquery.ui.widget'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(window.jQuery);
+ }
+}(function ($) {
+ 'use strict';
+
+ // The FileReader API is not actually used, but works as feature detection,
+ // as e.g. Safari supports XHR file uploads via the FormData API,
+ // but not non-multipart XHR file uploads:
+ $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader);
+ $.support.xhrFormDataFileUpload = !!window.FormData;
+
+ // The fileupload widget listens for change events on file input fields defined
+ // via fileInput setting and paste or drop events of the given dropZone.
+ // In addition to the default jQuery Widget methods, the fileupload widget
+ // exposes the "add" and "send" methods, to add or directly send files using
+ // the fileupload API.
+ // By default, files added via file input selection, paste, drag & drop or
+ // "add" method are uploaded immediately, but it is possible to override
+ // the "add" callback option to queue file uploads.
+ $.widget('blueimp.fileupload', {
+
+ options: {
+ // The namespace used for event handler binding on the dropZone and
+ // fileInput collections.
+ // If not set, the name of the widget ("fileupload") is used.
+ namespace: undefined,
+ // The drop target collection, by the default the complete document.
+ // Set to null or an empty collection to disable drag & drop support:
+ dropZone: $(document),
+ // The file input field collection, that is listened for change events.
+ // If undefined, it is set to the file input fields inside
+ // of the widget element on plugin initialization.
+ // Set to null or an empty collection to disable the change listener.
+ fileInput: undefined,
+ // By default, the file input field is replaced with a clone after
+ // each input field change event. This is required for iframe transport
+ // queues and allows change events to be fired for the same file
+ // selection, but can be disabled by setting the following option to false:
+ replaceFileInput: true,
+ // The parameter name for the file form data (the request argument name).
+ // If undefined or empty, the name property of the file input field is
+ // used, or "files[]" if the file input name property is also empty,
+ // can be a string or an array of strings:
+ paramName: undefined,
+ // By default, each file of a selection is uploaded using an individual
+ // request for XHR type uploads. Set to false to upload file
+ // selections in one request each:
+ singleFileUploads: true,
+ // To limit the number of files uploaded with one XHR request,
+ // set the following option to an integer greater than 0:
+ limitMultiFileUploads: undefined,
+ // Set the following option to true to issue all file upload requests
+ // in a sequential order:
+ sequentialUploads: false,
+ // To limit the number of concurrent uploads,
+ // set the following option to an integer greater than 0:
+ limitConcurrentUploads: undefined,
+ // Set the following option to true to force iframe transport uploads:
+ forceIframeTransport: false,
+ // Set the following option to the location of a redirect url on the
+ // origin server, for cross-domain iframe transport uploads:
+ redirect: undefined,
+ // The parameter name for the redirect url, sent as part of the form
+ // data and set to 'redirect' if this option is empty:
+ redirectParamName: undefined,
+ // Set the following option to the location of a postMessage window,
+ // to enable postMessage transport uploads:
+ postMessage: undefined,
+ // By default, XHR file uploads are sent as multipart/form-data.
+ // The iframe transport is always using multipart/form-data.
+ // Set to false to enable non-multipart XHR uploads:
+ multipart: true,
+ // To upload large files in smaller chunks, set the following option
+ // to a preferred maximum chunk size. If set to 0, null or undefined,
+ // or the browser does not support the required Blob API, files will
+ // be uploaded as a whole.
+ maxChunkSize: undefined,
+ // When a non-multipart upload or a chunked multipart upload has been
+ // aborted, this option can be used to resume the upload by setting
+ // it to the size of the already uploaded bytes. This option is most
+ // useful when modifying the options object inside of the "add" or
+ // "send" callbacks, as the options are cloned for each file upload.
+ uploadedBytes: undefined,
+ // By default, failed (abort or error) file uploads are removed from the
+ // global progress calculation. Set the following option to false to
+ // prevent recalculating the global progress data:
+ recalculateProgress: true,
+
+ // Additional form data to be sent along with the file uploads can be set
+ // using this option, which accepts an array of objects with name and
+ // value properties, a function returning such an array, a FormData
+ // object (for XHR file uploads), or a simple object.
+ // The form of the first fileInput is given as parameter to the function:
+ formData: function (form) {
+ return form.serializeArray();
+ },
+
+ // The add callback is invoked as soon as files are added to the fileupload
+ // widget (via file input selection, drag & drop, paste or add API call).
+ // If the singleFileUploads option is enabled, this callback will be
+ // called once for each file in the selection for XHR file uplaods, else
+ // once for each file selection.
+ // The upload starts when the submit method is invoked on the data parameter.
+ // The data object contains a files property holding the added files
+ // and allows to override plugin options as well as define ajax settings.
+ // Listeners for this callback can also be bound the following way:
+ // .bind('fileuploadadd', func);
+ // data.submit() returns a Promise object and allows to attach additional
+ // handlers using jQuery's Deferred callbacks:
+ // data.submit().done(func).fail(func).always(func);
+ add: function (e, data) {
+ data.submit();
+ },
+
+ // Other callbacks:
+ // Callback for the submit event of each file upload:
+ // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
+ // Callback for the start of each file upload request:
+ // send: function (e, data) {}, // .bind('fileuploadsend', func);
+ // Callback for successful uploads:
+ // done: function (e, data) {}, // .bind('fileuploaddone', func);
+ // Callback for failed (abort or error) uploads:
+ // fail: function (e, data) {}, // .bind('fileuploadfail', func);
+ // Callback for completed (success, abort or error) requests:
+ // always: function (e, data) {}, // .bind('fileuploadalways', func);
+ // Callback for upload progress events:
+ // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
+ // Callback for global upload progress events:
+ // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
+ // Callback for uploads start, equivalent to the global ajaxStart event:
+ // start: function (e) {}, // .bind('fileuploadstart', func);
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
+ // stop: function (e) {}, // .bind('fileuploadstop', func);
+ // Callback for change events of the fileInput collection:
+ // change: function (e, data) {}, // .bind('fileuploadchange', func);
+ // Callback for paste events to the dropZone collection:
+ // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
+ // Callback for drop events of the dropZone collection:
+ // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
+ // Callback for dragover events of the dropZone collection:
+ // dragover: function (e) {}, // .bind('fileuploaddragover', func);
+
+ // The plugin options are used as settings object for the ajax calls.
+ // The following are jQuery ajax settings required for the file uploads:
+ processData: false,
+ contentType: false,
+ cache: false
+ },
+
+ // A list of options that require a refresh after assigning a new value:
+ _refreshOptionsList: [
+ 'namespace',
+ 'dropZone',
+ 'fileInput',
+ 'multipart',
+ 'forceIframeTransport'
+ ],
+
+ _isXHRUpload: function (options) {
+ return !options.forceIframeTransport &&
+ ((!options.multipart && $.support.xhrFileUpload) ||
+ $.support.xhrFormDataFileUpload);
+ },
+
+ _getFormData: function (options) {
+ var formData;
+ if (typeof options.formData === 'function') {
+ return options.formData(options.form);
+ } else if ($.isArray(options.formData)) {
+ return options.formData;
+ } else if (options.formData) {
+ formData = [];
+ $.each(options.formData, function (name, value) {
+ formData.push({name: name, value: value});
+ });
+ return formData;
+ }
+ return [];
+ },
+
+ _getTotal: function (files) {
+ var total = 0;
+ $.each(files, function (index, file) {
+ total += file.size || 1;
+ });
+ return total;
+ },
+
+ _onProgress: function (e, data) {
+ if (e.lengthComputable) {
+ var total = data.total || this._getTotal(data.files),
+ loaded = parseInt(
+ e.loaded / e.total * (data.chunkSize || total),
+ 10
+ ) + (data.uploadedBytes || 0);
+ this._loaded += loaded - (data.loaded || data.uploadedBytes || 0);
+ data.lengthComputable = true;
+ data.loaded = loaded;
+ data.total = total;
+ // Trigger a custom progress event with a total data property set
+ // to the file size(s) of the current upload and a loaded data
+ // property calculated accordingly:
+ this._trigger('progress', e, data);
+ // Trigger a global progress event for all current file uploads,
+ // including ajax calls queued for sequential file uploads:
+ this._trigger('progressall', e, {
+ lengthComputable: true,
+ loaded: this._loaded,
+ total: this._total
+ });
+ }
+ },
+
+ _initProgressListener: function (options) {
+ var that = this,
+ xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
+ // Accesss to the native XHR object is required to add event listeners
+ // for the upload progress event:
+ if (xhr.upload) {
+ $(xhr.upload).bind('progress', function (e) {
+ var oe = e.originalEvent;
+ // Make sure the progress event properties get copied over:
+ e.lengthComputable = oe.lengthComputable;
+ e.loaded = oe.loaded;
+ e.total = oe.total;
+ that._onProgress(e, options);
+ });
+ options.xhr = function () {
+ return xhr;
+ };
+ }
+ },
+
+ _initXHRData: function (options) {
+ var formData,
+ file = options.files[0],
+ // Ignore non-multipart setting if not supported:
+ multipart = options.multipart || !$.support.xhrFileUpload,
+ paramName = options.paramName[0];
+ if (!multipart || options.blob) {
+ // For non-multipart uploads and chunked uploads,
+ // file meta data is not part of the request body,
+ // so we transmit this data as part of the HTTP headers.
+ // For cross domain requests, these headers must be allowed
+ // via Access-Control-Allow-Headers or removed using
+ // the beforeSend callback:
+ options.headers = $.extend(options.headers, {
+ 'X-File-Name': file.name,
+ 'X-File-Type': file.type,
+ 'X-File-Size': file.size
+ });
+ if (!options.blob) {
+ // Non-chunked non-multipart upload:
+ options.contentType = file.type;
+ options.data = file;
+ } else if (!multipart) {
+ // Chunked non-multipart upload:
+ options.contentType = 'application/octet-stream';
+ options.data = options.blob;
+ }
+ }
+ if (multipart && $.support.xhrFormDataFileUpload) {
+ if (options.postMessage) {
+ // window.postMessage does not allow sending FormData
+ // objects, so we just add the File/Blob objects to
+ // the formData array and let the postMessage window
+ // create the FormData object out of this array:
+ formData = this._getFormData(options);
+ if (options.blob) {
+ formData.push({
+ name: paramName,
+ value: options.blob
+ });
+ } else {
+ $.each(options.files, function (index, file) {
+ formData.push({
+ name: options.paramName[index] || paramName,
+ value: file
+ });
+ });
+ }
+ } else {
+ if (options.formData instanceof FormData) {
+ formData = options.formData;
+ } else {
+ formData = new FormData();
+ $.each(this._getFormData(options), function (index, field) {
+ formData.append(field.name, field.value);
+ });
+ }
+ if (options.blob) {
+ formData.append(paramName, options.blob, file.name);
+ } else {
+ $.each(options.files, function (index, file) {
+ // File objects are also Blob instances.
+ // This check allows the tests to run with
+ // dummy objects:
+ if (file instanceof Blob) {
+ formData.append(
+ options.paramName[index] || paramName,
+ file,
+ file.name
+ );
+ }
+ });
+ }
+ }
+ options.data = formData;
+ }
+ // Blob reference is not needed anymore, free memory:
+ options.blob = null;
+ },
+
+ _initIframeSettings: function (options) {
+ // Setting the dataType to iframe enables the iframe transport:
+ options.dataType = 'iframe ' + (options.dataType || '');
+ // The iframe transport accepts a serialized array as form data:
+ options.formData = this._getFormData(options);
+ // Add redirect url to form data on cross-domain uploads:
+ if (options.redirect && $('<a></a>').prop('href', options.url)
+ .prop('host') !== location.host) {
+ options.formData.push({
+ name: options.redirectParamName || 'redirect',
+ value: options.redirect
+ });
+ }
+ },
+
+ _initDataSettings: function (options) {
+ if (this._isXHRUpload(options)) {
+ if (!this._chunkedUpload(options, true)) {
+ if (!options.data) {
+ this._initXHRData(options);
+ }
+ this._initProgressListener(options);
+ }
+ if (options.postMessage) {
+ // Setting the dataType to postmessage enables the
+ // postMessage transport:
+ options.dataType = 'postmessage ' + (options.dataType || '');
+ }
+ } else {
+ this._initIframeSettings(options, 'iframe');
+ }
+ },
+
+ _getParamName: function (options) {
+ var fileInput = $(options.fileInput),
+ paramName = options.paramName;
+ if (!paramName) {
+ paramName = [];
+ fileInput.each(function () {
+ var input = $(this),
+ name = input.prop('name') || 'files[]',
+ i = (input.prop('files') || [1]).length;
+ while (i) {
+ paramName.push(name);
+ i -= 1;
+ }
+ });
+ if (!paramName.length) {
+ paramName = [fileInput.prop('name') || 'files[]'];
+ }
+ } else if (!$.isArray(paramName)) {
+ paramName = [paramName];
+ }
+ return paramName;
+ },
+
+ _initFormSettings: function (options) {
+ // Retrieve missing options from the input field and the
+ // associated form, if available:
+ if (!options.form || !options.form.length) {
+ options.form = $(options.fileInput.prop('form'));
+ }
+ options.paramName = this._getParamName(options);
+ if (!options.url) {
+ options.url = options.form.prop('action') || location.href;
+ }
+ // The HTTP request method must be "POST" or "PUT":
+ options.type = (options.type || options.form.prop('method') || '')
+ .toUpperCase();
+ if (options.type !== 'POST' && options.type !== 'PUT') {
+ options.type = 'POST';
+ }
+ },
+
+ _getAJAXSettings: function (data) {
+ var options = $.extend({}, this.options, data);
+ this._initFormSettings(options);
+ this._initDataSettings(options);
+ return options;
+ },
+
+ // Maps jqXHR callbacks to the equivalent
+ // methods of the given Promise object:
+ _enhancePromise: function (promise) {
+ promise.success = promise.done;
+ promise.error = promise.fail;
+ promise.complete = promise.always;
+ return promise;
+ },
+
+ // Creates and returns a Promise object enhanced with
+ // the jqXHR methods abort, success, error and complete:
+ _getXHRPromise: function (resolveOrReject, context, args) {
+ var dfd = $.Deferred(),
+ promise = dfd.promise();
+ context = context || this.options.context || promise;
+ if (resolveOrReject === true) {
+ dfd.resolveWith(context, args);
+ } else if (resolveOrReject === false) {
+ dfd.rejectWith(context, args);
+ }
+ promise.abort = dfd.promise;
+ return this._enhancePromise(promise);
+ },
+
+ // Uploads a file in multiple, sequential requests
+ // by splitting the file up in multiple blob chunks.
+ // If the second parameter is true, only tests if the file
+ // should be uploaded in chunks, but does not invoke any
+ // upload requests:
+ _chunkedUpload: function (options, testOnly) {
+ var that = this,
+ file = options.files[0],
+ fs = file.size,
+ ub = options.uploadedBytes = options.uploadedBytes || 0,
+ mcs = options.maxChunkSize || fs,
+ // Use the Blob methods with the slice implementation
+ // according to the W3C Blob API specification:
+ slice = file.webkitSlice || file.mozSlice || file.slice,
+ upload,
+ n,
+ jqXHR,
+ pipe;
+ if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
+ options.data) {
+ return false;
+ }
+ if (testOnly) {
+ return true;
+ }
+ if (ub >= fs) {
+ file.error = 'uploadedBytes';
+ return this._getXHRPromise(
+ false,
+ options.context,
+ [null, 'error', file.error]
+ );
+ }
+ // n is the number of blobs to upload,
+ // calculated via filesize, uploaded bytes and max chunk size:
+ n = Math.ceil((fs - ub) / mcs);
+ // The chunk upload method accepting the chunk number as parameter:
+ upload = function (i) {
+ if (!i) {
+ return that._getXHRPromise(true, options.context);
+ }
+ // Upload the blobs in sequential order:
+ return upload(i -= 1).pipe(function () {
+ // Clone the options object for each chunk upload:
+ var o = $.extend({}, options);
+ o.blob = slice.call(
+ file,
+ ub + i * mcs,
+ ub + (i + 1) * mcs
+ );
+ // Store the current chunk size, as the blob itself
+ // will be dereferenced after data processing:
+ o.chunkSize = o.blob.size;
+ // Process the upload data (the blob and potential form data):
+ that._initXHRData(o);
+ // Add progress listeners for this chunk upload:
+ that._initProgressListener(o);
+ jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context))
+ .done(function () {
+ // Create a progress event if upload is done and
+ // no progress event has been invoked for this chunk:
+ if (!o.loaded) {
+ that._onProgress($.Event('progress', {
+ lengthComputable: true,
+ loaded: o.chunkSize,
+ total: o.chunkSize
+ }), o);
+ }
+ options.uploadedBytes = o.uploadedBytes +=
+ o.chunkSize;
+ });
+ return jqXHR;
+ });
+ };
+ // Return the piped Promise object, enhanced with an abort method,
+ // which is delegated to the jqXHR object of the current upload,
+ // and jqXHR callbacks mapped to the equivalent Promise methods:
+ pipe = upload(n);
+ pipe.abort = function () {
+ return jqXHR.abort();
+ };
+ return this._enhancePromise(pipe);
+ },
+
+ _beforeSend: function (e, data) {
+ if (this._active === 0) {
+ // the start callback is triggered when an upload starts
+ // and no other uploads are currently running,
+ // equivalent to the global ajaxStart event:
+ this._trigger('start');
+ }
+ this._active += 1;
+ // Initialize the global progress values:
+ this._loaded += data.uploadedBytes || 0;
+ this._total += this._getTotal(data.files);
+ },
+
+ _onDone: function (result, textStatus, jqXHR, options) {
+ if (!this._isXHRUpload(options)) {
+ // Create a progress event for each iframe load:
+ this._onProgress($.Event('progress', {
+ lengthComputable: true,
+ loaded: 1,
+ total: 1
+ }), options);
+ }
+ options.result = result;
+ options.textStatus = textStatus;
+ options.jqXHR = jqXHR;
+ this._trigger('done', null, options);
+ },
+
+ _onFail: function (jqXHR, textStatus, errorThrown, options) {
+ options.jqXHR = jqXHR;
+ options.textStatus = textStatus;
+ options.errorThrown = errorThrown;
+ this._trigger('fail', null, options);
+ if (options.recalculateProgress) {
+ // Remove the failed (error or abort) file upload from
+ // the global progress calculation:
+ this._loaded -= options.loaded || options.uploadedBytes || 0;
+ this._total -= options.total || this._getTotal(options.files);
+ }
+ },
+
+ _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
+ this._active -= 1;
+ options.textStatus = textStatus;
+ if (jqXHRorError && jqXHRorError.always) {
+ options.jqXHR = jqXHRorError;
+ options.result = jqXHRorResult;
+ } else {
+ options.jqXHR = jqXHRorResult;
+ options.errorThrown = jqXHRorError;
+ }
+ this._trigger('always', null, options);
+ if (this._active === 0) {
+ // The stop callback is triggered when all uploads have
+ // been completed, equivalent to the global ajaxStop event:
+ this._trigger('stop');
+ // Reset the global progress values:
+ this._loaded = this._total = 0;
+ }
+ },
+
+ _onSend: function (e, data) {
+ var that = this,
+ jqXHR,
+ slot,
+ pipe,
+ options = that._getAJAXSettings(data),
+ send = function (resolve, args) {
+ that._sending += 1;
+ jqXHR = jqXHR || (
+ (resolve !== false &&
+ that._trigger('send', e, options) !== false &&
+ (that._chunkedUpload(options) || $.ajax(options))) ||
+ that._getXHRPromise(false, options.context, args)
+ ).done(function (result, textStatus, jqXHR) {
+ that._onDone(result, textStatus, jqXHR, options);
+ }).fail(function (jqXHR, textStatus, errorThrown) {
+ that._onFail(jqXHR, textStatus, errorThrown, options);
+ }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
+ that._sending -= 1;
+ that._onAlways(
+ jqXHRorResult,
+ textStatus,
+ jqXHRorError,
+ options
+ );
+ if (options.limitConcurrentUploads &&
+ options.limitConcurrentUploads > that._sending) {
+ // Start the next queued upload,
+ // that has not been aborted:
+ var nextSlot = that._slots.shift();
+ while (nextSlot) {
+ if (!nextSlot.isRejected()) {
+ nextSlot.resolve();
+ break;
+ }
+ nextSlot = that._slots.shift();
+ }
+ }
+ });
+ return jqXHR;
+ };
+ this._beforeSend(e, options);
+ if (this.options.sequentialUploads ||
+ (this.options.limitConcurrentUploads &&
+ this.options.limitConcurrentUploads <= this._sending)) {
+ if (this.options.limitConcurrentUploads > 1) {
+ slot = $.Deferred();
+ this._slots.push(slot);
+ pipe = slot.pipe(send);
+ } else {
+ pipe = (this._sequence = this._sequence.pipe(send, send));
+ }
+ // Return the piped Promise object, enhanced with an abort method,
+ // which is delegated to the jqXHR object of the current upload,
+ // and jqXHR callbacks mapped to the equivalent Promise methods:
+ pipe.abort = function () {
+ var args = [undefined, 'abort', 'abort'];
+ if (!jqXHR) {
+ if (slot) {
+ slot.rejectWith(args);
+ }
+ return send(false, args);
+ }
+ return jqXHR.abort();
+ };
+ return this._enhancePromise(pipe);
+ }
+ return send();
+ },
+
+ _onAdd: function (e, data) {
+ var that = this,
+ result = true,
+ options = $.extend({}, this.options, data),
+ limit = options.limitMultiFileUploads,
+ paramName = this._getParamName(options),
+ paramNameSet,
+ paramNameSlice,
+ fileSet,
+ i;
+ if (!(options.singleFileUploads || limit) ||
+ !this._isXHRUpload(options)) {
+ fileSet = [data.files];
+ paramNameSet = [paramName];
+ } else if (!options.singleFileUploads && limit) {
+ fileSet = [];
+ paramNameSet = [];
+ for (i = 0; i < data.files.length; i += limit) {
+ fileSet.push(data.files.slice(i, i + limit));
+ paramNameSlice = paramName.slice(i, i + limit);
+ if (!paramNameSlice.length) {
+ paramNameSlice = paramName;
+ }
+ paramNameSet.push(paramNameSlice);
+ }
+ } else {
+ paramNameSet = paramName;
+ }
+ data.originalFiles = data.files;
+ $.each(fileSet || data.files, function (index, element) {
+ var newData = $.extend({}, data);
+ newData.files = fileSet ? element : [element];
+ newData.paramName = paramNameSet[index];
+ newData.submit = function () {
+ newData.jqXHR = this.jqXHR =
+ (that._trigger('submit', e, this) !== false) &&
+ that._onSend(e, this);
+ return this.jqXHR;
+ };
+ return (result = that._trigger('add', e, newData));
+ });
+ return result;
+ },
+
+ // File Normalization for Gecko 1.9.1 (Firefox 3.5) support:
+ _normalizeFile: function (index, file) {
+ if (file.name === undefined && file.size === undefined) {
+ file.name = file.fileName;
+ file.size = file.fileSize;
+ }
+ },
+
+ _replaceFileInput: function (input) {
+ var inputClone = input.clone(true);
+ $('<form></form>').append(inputClone)[0].reset();
+ // Detaching allows to insert the fileInput on another form
+ // without loosing the file input value:
+ input.after(inputClone).detach();
+ // Avoid memory leaks with the detached file input:
+ $.cleanData(input.unbind('remove'));
+ // Replace the original file input element in the fileInput
+ // collection with the clone, which has been copied including
+ // event handlers:
+ this.options.fileInput = this.options.fileInput.map(function (i, el) {
+ if (el === input[0]) {
+ return inputClone[0];
+ }
+ return el;
+ });
+ // If the widget has been initialized on the file input itself,
+ // override this.element with the file input clone:
+ if (input[0] === this.element[0]) {
+ this.element = inputClone;
+ }
+ },
+
+ _onChange: function (e) {
+ var that = e.data.fileupload,
+ data = {
+ files: $.each($.makeArray(e.target.files), that._normalizeFile),
+ fileInput: $(e.target),
+ form: $(e.target.form)
+ };
+ if (!data.files.length) {
+ // If the files property is not available, the browser does not
+ // support the File API and we add a pseudo File object with
+ // the input value as name with path information removed:
+ data.files = [{name: e.target.value.replace(/^.*\\/, '')}];
+ }
+ if (that.options.replaceFileInput) {
+ that._replaceFileInput(data.fileInput);
+ }
+ if (that._trigger('change', e, data) === false ||
+ that._onAdd(e, data) === false) {
+ return false;
+ }
+ },
+
+ _onPaste: function (e) {
+ var that = e.data.fileupload,
+ cbd = e.originalEvent.clipboardData,
+ items = (cbd && cbd.items) || [],
+ data = {files: []};
+ $.each(items, function (index, item) {
+ var file = item.getAsFile && item.getAsFile();
+ if (file) {
+ data.files.push(file);
+ }
+ });
+ if (that._trigger('paste', e, data) === false ||
+ that._onAdd(e, data) === false) {
+ return false;
+ }
+ },
+
+ _onDrop: function (e) {
+ var that = e.data.fileupload,
+ dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
+ data = {
+ files: $.each(
+ $.makeArray(dataTransfer && dataTransfer.files),
+ that._normalizeFile
+ )
+ };
+ if (that._trigger('drop', e, data) === false ||
+ that._onAdd(e, data) === false) {
+ return false;
+ }
+ e.preventDefault();
+ },
+
+ _onDragOver: function (e) {
+ var that = e.data.fileupload,
+ dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
+ if (that._trigger('dragover', e) === false) {
+ return false;
+ }
+ if (dataTransfer) {
+ dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy';
+ }
+ e.preventDefault();
+ },
+
+ _initEventHandlers: function () {
+ var ns = this.options.namespace;
+ if (this._isXHRUpload(this.options)) {
+ this.options.dropZone
+ .bind('dragover.' + ns, {fileupload: this}, this._onDragOver)
+ .bind('drop.' + ns, {fileupload: this}, this._onDrop)
+ .bind('paste.' + ns, {fileupload: this}, this._onPaste);
+ }
+ this.options.fileInput
+ .bind('change.' + ns, {fileupload: this}, this._onChange);
+ },
+
+ _destroyEventHandlers: function () {
+ var ns = this.options.namespace;
+ this.options.dropZone
+ .unbind('dragover.' + ns, this._onDragOver)
+ .unbind('drop.' + ns, this._onDrop)
+ .unbind('paste.' + ns, this._onPaste);
+ this.options.fileInput
+ .unbind('change.' + ns, this._onChange);
+ },
+
+ _setOption: function (key, value) {
+ var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
+ if (refresh) {
+ this._destroyEventHandlers();
+ }
+ $.Widget.prototype._setOption.call(this, key, value);
+ if (refresh) {
+ this._initSpecialOptions();
+ this._initEventHandlers();
+ }
+ },
+
+ _initSpecialOptions: function () {
+ var options = this.options;
+ if (options.fileInput === undefined) {
+ options.fileInput = this.element.is('input:file') ?
+ this.element : this.element.find('input:file');
+ } else if (!(options.fileInput instanceof $)) {
+ options.fileInput = $(options.fileInput);
+ }
+ if (!(options.dropZone instanceof $)) {
+ options.dropZone = $(options.dropZone);
+ }
+ },
+
+ _create: function () {
+ var options = this.options,
+ dataOpts = $.extend({}, this.element.data());
+ dataOpts[this.widgetName] = undefined;
+ $.extend(options, dataOpts);
+ options.namespace = options.namespace || this.widgetName;
+ this._initSpecialOptions();
+ this._slots = [];
+ this._sequence = this._getXHRPromise(true);
+ this._sending = this._active = this._loaded = this._total = 0;
+ this._initEventHandlers();
+ },
+
+ destroy: function () {
+ this._destroyEventHandlers();
+ $.Widget.prototype.destroy.call(this);
+ },
+
+ enable: function () {
+ $.Widget.prototype.enable.call(this);
+ this._initEventHandlers();
+ },
+
+ disable: function () {
+ this._destroyEventHandlers();
+ $.Widget.prototype.disable.call(this);
+ },
+
+ // This method is exposed to the widget API and allows adding files
+ // using the fileupload API. The data parameter accepts an object which
+ // must have a files property and can contain additional options:
+ // .fileupload('add', {files: filesList});
+ add: function (data) {
+ if (!data || this.options.disabled) {
+ return;
+ }
+ data.files = $.each($.makeArray(data.files), this._normalizeFile);
+ this._onAdd(null, data);
+ },
+
+ // This method is exposed to the widget API and allows sending files
+ // using the fileupload API. The data parameter accepts an object which
+ // must have a files property and can contain additional options:
+ // .fileupload('send', {files: filesList});
+ // The method returns a Promise object for the file upload call.
+ send: function (data) {
+ if (data && !this.options.disabled) {
+ data.files = $.each($.makeArray(data.files), this._normalizeFile);
+ if (data.files.length) {
+ return this._onSend(null, data);
+ }
+ }
+ return this._getXHRPromise(false, data && data.context);
+ }
+
+ });
+
+}));
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ip-1.0.6.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ip-1.0.6.js
new file mode 100644
index 000000000..7b998032f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ip-1.0.6.js
@@ -0,0 +1,160 @@
+/*
+ * jQuery File Upload Image Processing Plugin 1.0.6
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2012, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint nomen: true, unparam: true, regexp: true */
+/*global define, window, document */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ 'jquery',
+ //'load-image',
+ //'canvas-to-blob',
+ 'jquery.fileupload'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.jQuery,
+ window.loadImage,
+ window.canvasToBlob
+ );
+ }
+}(function ($, loadImage, canvasToBlob) {
+ 'use strict';
+
+ // The File Upload IP version extends the basic fileupload widget
+ // with image processing functionality:
+ $.widget('blueimpIP.fileupload', $.blueimp.fileupload, {
+
+ options: {
+ // The regular expression to define which image files are to be
+ // resized, given that the browser supports the operation:
+ resizeSourceFileTypes: /^image\/(gif|jpeg|png)$/,
+ // The maximum file size of images that are to be resized:
+ resizeSourceMaxFileSize: 20000000, // 20MB
+ // The maximum width of the resized images:
+ resizeMaxWidth: undefined,
+ // The maximum height of the resized images:
+ resizeMaxHeight: undefined,
+ // The minimum width of the resized images:
+ resizeMinWidth: undefined,
+ // The minimum height of the resized images:
+ resizeMinHeight: undefined,
+
+ // The add callback is invoked as soon as files are added to the fileupload
+ // widget (via file input selection, drag & drop or add API call).
+ // See the basic file upload widget for more information:
+ add: function (e, data) {
+ $(this).fileupload('resize', data).done(function () {
+ data.submit();
+ });
+ }
+ },
+
+ // Resizes the image file at the given index and stores the created blob
+ // at the original position of the files list, returns a Promise object:
+ _resizeImage: function (files, index, options) {
+ var that = this,
+ file = files[index],
+ deferred = $.Deferred(),
+ canvas,
+ blob;
+ options = options || this.options;
+ loadImage(
+ file,
+ function (img) {
+ var width = img.width,
+ height = img.height;
+ canvas = loadImage.scale(img, {
+ maxWidth: options.resizeMaxWidth,
+ maxHeight: options.resizeMaxHeight,
+ minWidth: options.resizeMinWidth,
+ minHeight: options.resizeMinHeight,
+ canvas: true
+ });
+ if (width !== canvas.width || height !== canvas.height) {
+ canvasToBlob(canvas, function (blob) {
+ if (!blob.name) {
+ if (file.type === blob.type) {
+ blob.name = file.name;
+ } else if (file.name) {
+ blob.name = file.name.replace(
+ /\..+$/,
+ '.' + blob.type.substr(6)
+ );
+ }
+ }
+ files[index] = blob;
+ deferred.resolveWith(that);
+ }, file);
+ } else {
+ deferred.resolveWith(that);
+ }
+ }
+ );
+ return deferred.promise();
+ },
+
+ // Resizes the images given as files property of the data parameter,
+ // returns a Promise object that allows to bind a done handler, which
+ // will be invoked after processing all images is done:
+ resize: function (data) {
+ var that = this,
+ options = $.extend({}, this.options, data),
+ resizeAll = $.type(options.resizeSourceMaxFileSize) !== 'number',
+ isXHRUpload = this._isXHRUpload(options);
+ $.each(data.files, function (index, file) {
+ if (isXHRUpload && that._resizeSupport &&
+ (options.resizeMaxWidth || options.resizeMaxHeight ||
+ options.resizeMinWidth || options.resizeMinHeight) &&
+ (resizeAll || file.size < options.resizeSourceMaxFileSize) &&
+ options.resizeSourceFileTypes.test(file.type)) {
+ that._processing += 1;
+ if (that._processing === 1) {
+ that.element.addClass('fileupload-processing');
+ }
+ that._processingQueue = that._processingQueue.pipe(function () {
+ var deferred = $.Deferred();
+ that._resizeImage(
+ data.files,
+ index,
+ options
+ ).done(function () {
+ that._processing -= 1;
+ if (that._processing === 0) {
+ that.element
+ .removeClass('fileupload-processing');
+ }
+ deferred.resolveWith(that);
+ });
+ return deferred.promise();
+ });
+ }
+ });
+ return this._processingQueue;
+ },
+
+ _create: function () {
+ $.blueimp.fileupload.prototype._create.call(this);
+ this._processing = 0;
+ this._processingQueue = $.Deferred().resolveWith(this).promise();
+ this._resizeSupport = canvasToBlob && canvasToBlob(
+ document.createElement('canvas'),
+ $.noop
+ );
+ }
+
+ });
+
+}));
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ui-6.6.3.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ui-6.6.3.js
new file mode 100644
index 000000000..c2c48a8aa
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.fileupload-ui-6.6.3.js
@@ -0,0 +1,630 @@
+/*
+ * jQuery File Upload User Interface Plugin 6.6.3
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint nomen: true, unparam: true, regexp: true */
+/*global define, window, document, URL, webkitURL, FileReader */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ 'jquery',
+ 'tmpl',
+ //'load-image',
+ 'jquery.fileupload.ip'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.jQuery,
+ window.tmpl,
+ window.loadImage
+ );
+ }
+}(function ($, tmpl, loadImage) {
+ 'use strict';
+
+ // The UI version extends the IP (image processing) version or the basic
+ // file upload widget and adds complete user interface interaction:
+ var parentWidget = ($.blueimpIP || $.blueimp).fileupload;
+ $.widget('blueimpUI.fileupload', parentWidget, {
+
+ options: {
+ // By default, files added to the widget are uploaded as soon
+ // as the user clicks on the start buttons. To enable automatic
+ // uploads, set the following option to true:
+ autoUpload: false,
+ // The following option limits the number of files that are
+ // allowed to be uploaded using this widget:
+ maxNumberOfFiles: undefined,
+ // The maximum allowed file size:
+ maxFileSize: undefined,
+ // The minimum allowed file size:
+ minFileSize: undefined,
+ // The regular expression for allowed file types, matches
+ // against either file type or file name:
+ acceptFileTypes: /.+$/i,
+ // The regular expression to define for which files a preview
+ // image is shown, matched against the file type:
+ previewSourceFileTypes: /^image\/(gif|jpeg|png)$/,
+ // The maximum file size of images that are to be displayed as preview:
+ previewSourceMaxFileSize: 5000000, // 5MB
+ // The maximum width of the preview images:
+ previewMaxWidth: 80,
+ // The maximum height of the preview images:
+ previewMaxHeight: 80,
+ // By default, preview images are displayed as canvas elements
+ // if supported by the browser. Set the following option to false
+ // to always display preview images as img elements:
+ previewAsCanvas: true,
+ // The ID of the upload template:
+ uploadTemplateId: 'template-upload',
+ // The ID of the download template:
+ downloadTemplateId: 'template-download',
+ // The expected data type of the upload response, sets the dataType
+ // option of the $.ajax upload requests:
+ dataType: 'json',
+
+ // The add callback is invoked as soon as files are added to the fileupload
+ // widget (via file input selection, drag & drop or add API call).
+ // See the basic file upload widget for more information:
+ add: function (e, data) {
+ var that = $(this).data('fileupload'),
+ options = that.options,
+ files = data.files;
+ $(this).fileupload('resize', data).done(data, function () {
+ that._adjustMaxNumberOfFiles(-files.length);
+ data.isAdjusted = true;
+ data.files.valid = data.isValidated = that._validate(files);
+ data.context = that._renderUpload(files)
+ .appendTo(options.filesContainer)
+ .data('data', data);
+ that._renderPreviews(files, data.context);
+ that._forceReflow(data.context);
+ that._transition(data.context).done(
+ function () {
+ if ((that._trigger('added', e, data) !== false) &&
+ (options.autoUpload || data.autoUpload) &&
+ data.autoUpload !== false && data.isValidated) {
+ data.submit();
+ }
+ }
+ );
+ });
+ },
+ // Callback for the start of each file upload request:
+ send: function (e, data) {
+ var that = $(this).data('fileupload');
+ if (!data.isValidated) {
+ if (!data.isAdjusted) {
+ that._adjustMaxNumberOfFiles(-data.files.length);
+ }
+ if (!that._validate(data.files)) {
+ return false;
+ }
+ }
+ if (data.context && data.dataType &&
+ data.dataType.substr(0, 6) === 'iframe') {
+ // Iframe Transport does not support progress events.
+ // In lack of an indeterminate progress bar, we set
+ // the progress to 100%, showing the full animated bar:
+ data.context
+ .find('.progress').addClass(
+ !$.support.transition && 'progress-animated'
+ )
+ .find('.bar').css(
+ 'width',
+ parseInt(100, 10) + '%'
+ );
+ }
+ return that._trigger('sent', e, data);
+ },
+ // Callback for successful uploads:
+ done: function (e, data) {
+ var that = $(this).data('fileupload'),
+ template,
+ preview;
+ if (data.context) {
+
+ data.context.each(function (index, e) {
+ var file = ($.isArray(data.result) &&
+ data.result[index]) || data.result || {error: 'emptyResult'};
+ if (file.error) {
+ that._adjustMaxNumberOfFiles(1);
+ }
+ that._transition($(this)).done(
+ function () {
+ var node = $(this);
+ template = that._renderDownload([file])
+ .css('height', node.height())
+ .replaceAll(node);
+ that._forceReflow(template);
+ that._transition(template).done(
+ function () {
+ data.context = $(this);
+ that._trigger('completed', e, data);
+ }
+ );
+ }
+ );
+ });
+ } else {
+ template = that._renderDownload(data.result)
+ .appendTo(that.options.filesContainer);
+ that._forceReflow(template);
+ that._transition(template).done(
+ function () {
+ data.context = $(this);
+ that._trigger('completed', e, data);
+ }
+ );
+ }
+ },
+ // Callback for failed (abort or error) uploads:
+ fail: function (e, data) {
+ var that = $(this).data('fileupload'),
+ template;
+ that._adjustMaxNumberOfFiles(data.files.length);
+ if (data.context) {
+ data.context.each(function (index) {
+ if (data.errorThrown !== 'abort') {
+ var file = data.files[index];
+ file.error = file.error || data.errorThrown ||
+ true;
+ that._transition($(this)).done(
+ function () {
+ var node = $(this);
+ template = that._renderDownload([file])
+ .replaceAll(node);
+ that._forceReflow(template);
+ that._transition(template).done(
+ function () {
+ data.context = $(this);
+ that._trigger('failed', e, data);
+ }
+ );
+ }
+ );
+ } else {
+ that._transition($(this)).done(
+ function () {
+ $(this).remove();
+ that._trigger('failed', e, data);
+ }
+ );
+ }
+ });
+ } else if (data.errorThrown !== 'abort') {
+ that._adjustMaxNumberOfFiles(-data.files.length);
+ data.context = that._renderUpload(data.files)
+ .appendTo(that.options.filesContainer)
+ .data('data', data);
+ that._forceReflow(data.context);
+ that._transition(data.context).done(
+ function () {
+ data.context = $(this);
+ that._trigger('failed', e, data);
+ }
+ );
+ } else {
+ that._trigger('failed', e, data);
+ }
+ },
+ // Callback for upload progress events:
+ progress: function (e, data) {
+ if (data.context) {
+ data.context.find('.progress .bar').css(
+ 'width',
+ parseInt(data.loaded / data.total * 100, 10) + '%'
+ );
+ }
+ },
+ // Callback for global upload progress events:
+ progressall: function (e, data) {
+ $(this).find('.fileupload-buttonbar .progress .bar').css(
+ 'width',
+ parseInt(data.loaded / data.total * 100, 10) + '%'
+ );
+ },
+ // Callback for uploads start, equivalent to the global ajaxStart event:
+ start: function (e) {
+ var that = $(this).data('fileupload');
+ that._transition($(this).find('.fileupload-buttonbar .progress')).done(
+ function () {
+ that._trigger('started', e);
+ }
+ );
+ },
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
+ stop: function (e) {
+ var that = $(this).data('fileupload');
+ that._transition($(this).find('.fileupload-buttonbar .progress')).done(
+ function () {
+ $(this).find('.bar').css('width', '0%');
+ that._trigger('stopped', e);
+ }
+ );
+ },
+ // Callback for file deletion:
+ destroy: function (e, data) {
+ var that = $(this).data('fileupload');
+ if (data.url) {
+ $.ajax(data);
+ }
+ that._adjustMaxNumberOfFiles(1);
+ that._transition(data.context).done(
+ function () {
+ $(this).remove();
+ that._trigger('destroyed', e, data);
+ }
+ );
+ }
+ },
+
+ // Link handler, that allows to download files
+ // by drag & drop of the links to the desktop:
+ _enableDragToDesktop: function () {
+ var link = $(this),
+ url = link.prop('href'),
+ name = link.prop('download'),
+ type = 'application/octet-stream';
+ link.bind('dragstart', function (e) {
+ try {
+ e.originalEvent.dataTransfer.setData(
+ 'DownloadURL',
+ [type, name, url].join(':')
+ );
+ } catch (err) {}
+ });
+ },
+
+ _adjustMaxNumberOfFiles: function (operand) {
+ if (typeof this.options.maxNumberOfFiles === 'number') {
+ this.options.maxNumberOfFiles += operand;
+ if (this.options.maxNumberOfFiles < 1) {
+ this._disableFileInputButton();
+ } else {
+ this._enableFileInputButton();
+ }
+ }
+ },
+
+ _formatFileSize: function (bytes) {
+ if (typeof bytes !== 'number') {
+ return '';
+ }
+ if (bytes >= 1000000000) {
+ return (bytes / 1000000000).toFixed(2) + ' GB';
+ }
+ if (bytes >= 1000000) {
+ return (bytes / 1000000).toFixed(2) + ' MB';
+ }
+ return (bytes / 1000).toFixed(2) + ' KB';
+ },
+
+ _hasError: function (file) {
+ if (file.error) {
+ return file.error;
+ }
+ // The number of added files is subtracted from
+ // maxNumberOfFiles before validation, so we check if
+ // maxNumberOfFiles is below 0 (instead of below 1):
+ if (this.options.maxNumberOfFiles < 0) {
+ return 'maxNumberOfFiles';
+ }
+ // Files are accepted if either the file type or the file name
+ // matches against the acceptFileTypes regular expression, as
+ // only browsers with support for the File API report the type:
+ if (!(this.options.acceptFileTypes.test(file.type) ||
+ this.options.acceptFileTypes.test(file.name))) {
+ return 'acceptFileTypes';
+ }
+ if (this.options.maxFileSize &&
+ file.size > this.options.maxFileSize) {
+ return 'maxFileSize';
+ }
+ if (typeof file.size === 'number' &&
+ file.size < this.options.minFileSize) {
+ return 'minFileSize';
+ }
+ return null;
+ },
+
+ _validate: function (files) {
+ var that = this,
+ valid = !!files.length;
+ $.each(files, function (index, file) {
+ file.error = that._hasError(file);
+ if (file.error) {
+ valid = false;
+ }
+ });
+ return valid;
+ },
+
+ _renderTemplate: function (func, files) {
+ if (!func) {
+ return $();
+ }
+ var result = func({
+ files: files,
+ formatFileSize: this._formatFileSize,
+ options: this.options
+ });
+ if (result instanceof $) {
+ return result;
+ }
+ return $(this.options.templatesContainer).html(result).children();
+ },
+
+ _renderPreview: function (file, node) {
+ var that = this,
+ options = this.options,
+ deferred = $.Deferred();
+ return ((loadImage && loadImage(
+ file,
+ function (img) {
+ node.append(img);
+ that._forceReflow(node);
+ that._transition(node).done(function () {
+ deferred.resolveWith(node);
+ });
+ },
+ {
+ maxWidth: options.previewMaxWidth,
+ maxHeight: options.previewMaxHeight,
+ canvas: options.previewAsCanvas
+ }
+ )) || deferred.resolveWith(node)) && deferred;
+ },
+
+ _renderPreviews: function (files, nodes) {
+ var that = this,
+ options = this.options;
+ nodes.find('.preview span').each(function (index, element) {
+ var file = files[index];
+ if (options.previewSourceFileTypes.test(file.type) &&
+ ($.type(options.previewSourceMaxFileSize) !== 'number' ||
+ file.size < options.previewSourceMaxFileSize)) {
+ that._processingQueue = that._processingQueue.pipe(function () {
+ var deferred = $.Deferred();
+ that._renderPreview(file, $(element)).done(
+ function () {
+ deferred.resolveWith(that);
+ }
+ );
+ return deferred.promise();
+ });
+ }
+ });
+ return this._processingQueue;
+ },
+
+ _renderUpload: function (files) {
+ return this._renderTemplate(
+ this.options.uploadTemplate,
+ files
+ );
+ },
+
+ _renderDownload: function (files) {
+ return this._renderTemplate(
+ this.options.downloadTemplate,
+ files
+ ).find('a[download]').each(this._enableDragToDesktop).end();
+ },
+
+ _startHandler: function (e) {
+ e.preventDefault();
+ var button = $(this),
+ template = button.closest('.template-upload'),
+ data = template.data('data');
+ if (data && data.submit && !data.jqXHR && data.submit()) {
+ button.prop('disabled', true);
+ }
+ },
+
+ _cancelHandler: function (e) {
+ e.preventDefault();
+ var template = $(this).closest('.template-upload'),
+ data = template.data('data') || {};
+ if (!data.jqXHR) {
+ data.errorThrown = 'abort';
+ e.data.fileupload._trigger('fail', e, data);
+ } else {
+ data.jqXHR.abort();
+ }
+ },
+
+ _deleteHandler: function (e) {
+ e.preventDefault();
+ var button = $(this);
+ e.data.fileupload._trigger('destroy', e, {
+ context: button.closest('.template-download'),
+ url: button.attr('data-url'),
+ type: button.attr('data-type') || 'DELETE',
+ dataType: e.data.fileupload.options.dataType
+ });
+ },
+
+ _forceReflow: function (node) {
+ this._reflow = $.support.transition &&
+ node.length && node[0].offsetWidth;
+ },
+
+ _transition: function (node) {
+ var that = this,
+ deferred = $.Deferred();
+ if ($.support.transition && node.hasClass('fade')) {
+ node.bind(
+ $.support.transition.end,
+ function (e) {
+ // Make sure we don't respond to other transitions events
+ // in the container element, e.g. from button elements:
+ if (e.target === node[0]) {
+ node.unbind($.support.transition.end);
+ deferred.resolveWith(node);
+ }
+ }
+ ).toggleClass('in');
+ } else {
+ node.toggleClass('in');
+ deferred.resolveWith(node);
+ }
+ return deferred;
+ },
+
+ _initButtonBarEventHandlers: function () {
+ var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
+ filesList = this.options.filesContainer,
+ ns = this.options.namespace;
+ fileUploadButtonBar.find('.start')
+ .bind('click.' + ns, function (e) {
+ e.preventDefault();
+ filesList.find('.start button').click();
+ });
+ fileUploadButtonBar.find('.cancel')
+ .bind('click.' + ns, function (e) {
+ e.preventDefault();
+ filesList.find('.cancel button').click();
+ });
+ fileUploadButtonBar.find('.delete')
+ .bind('click.' + ns, function (e) {
+ e.preventDefault();
+ filesList.find('.delete input:checked')
+ .siblings('button').click();
+ fileUploadButtonBar.find('.toggle')
+ .prop('checked', false);
+ });
+ fileUploadButtonBar.find('.toggle')
+ .bind('change.' + ns, function (e) {
+ filesList.find('.delete input').prop(
+ 'checked',
+ $(this).is(':checked')
+ );
+ });
+ },
+
+ _destroyButtonBarEventHandlers: function () {
+ this.element.find('.fileupload-buttonbar button')
+ .unbind('click.' + this.options.namespace);
+ this.element.find('.fileupload-buttonbar .toggle')
+ .unbind('change.' + this.options.namespace);
+ },
+
+ _initEventHandlers: function () {
+ parentWidget.prototype._initEventHandlers.call(this);
+ var eventData = {fileupload: this};
+ this.options.filesContainer
+ .delegate(
+ '.start button',
+ 'click.' + this.options.namespace,
+ eventData,
+ this._startHandler
+ )
+ .delegate(
+ '.cancel button',
+ 'click.' + this.options.namespace,
+ eventData,
+ this._cancelHandler
+ )
+ .delegate(
+ '.delete button',
+ 'click.' + this.options.namespace,
+ eventData,
+ this._deleteHandler
+ );
+ this._initButtonBarEventHandlers();
+ },
+
+ _destroyEventHandlers: function () {
+ var options = this.options;
+ this._destroyButtonBarEventHandlers();
+ options.filesContainer
+ .undelegate('.start button', 'click.' + options.namespace)
+ .undelegate('.cancel button', 'click.' + options.namespace)
+ .undelegate('.delete button', 'click.' + options.namespace);
+ parentWidget.prototype._destroyEventHandlers.call(this);
+ },
+
+ _enableFileInputButton: function () {
+ this.element.find('.fileinput-button input')
+ .prop('disabled', false)
+ .parent().removeClass('disabled');
+ },
+
+ _disableFileInputButton: function () {
+ this.element.find('.fileinput-button input')
+ .prop('disabled', true)
+ .parent().addClass('disabled');
+ },
+
+ _initTemplates: function () {
+ var options = this.options;
+ options.templatesContainer = document.createElement(
+ options.filesContainer.prop('nodeName')
+ );
+ if (tmpl) {
+ if (options.uploadTemplateId) {
+ options.uploadTemplate = tmpl(options.uploadTemplateId);
+ }
+ if (options.downloadTemplateId) {
+ options.downloadTemplate = tmpl(options.downloadTemplateId);
+ }
+ }
+ },
+
+ _initFilesContainer: function () {
+ var options = this.options;
+ if (options.filesContainer === undefined) {
+ options.filesContainer = this.element.find('.files');
+ } else if (!(options.filesContainer instanceof $)) {
+ options.filesContainer = $(options.filesContainer);
+ }
+ },
+
+ _initSpecialOptions: function () {
+ parentWidget.prototype._initSpecialOptions.call(this);
+ this._initFilesContainer();
+ this._initTemplates();
+ },
+
+ _create: function () {
+ parentWidget.prototype._create.call(this);
+ this._refreshOptionsList.push(
+ 'filesContainer',
+ 'uploadTemplateId',
+ 'downloadTemplateId'
+ );
+ if (!$.blueimpIP) {
+ this._processingQueue = $.Deferred().resolveWith(this).promise();
+ this.resize = function () {
+ return this._processingQueue;
+ };
+ }
+ },
+
+ enable: function () {
+ parentWidget.prototype.enable.call(this);
+ this.element.find('input, button').prop('disabled', false);
+ this._enableFileInputButton();
+ },
+
+ disable: function () {
+ this.element.find('input, button').prop('disabled', true);
+ this._disableFileInputButton();
+ parentWidget.prototype.disable.call(this);
+ }
+
+ });
+
+}));
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.i18n.properties-1.0.9.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.i18n.properties-1.0.9.js
new file mode 100644
index 000000000..573c4de93
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.i18n.properties-1.0.9.js
@@ -0,0 +1,499 @@
+/******************************************************************************
+ * jquery.i18n.properties
+ *
+ * Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ * MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ *
+ * @version 1.0.x
+ * @author Nuno Fernandes
+ * @url www.codingwithcoffee.com
+ * @inspiration Localisation assistance for jQuery (http://keith-wood.name/localisation.html)
+ * by Keith Wood (kbwood{at}iinet.com.au) June 2007
+ *
+ *****************************************************************************/
+
+// START olamy hack more AMD compliant
+(function($, window) {
+ (function(factory){
+ // Support module loading scenarios
+ if (typeof define === 'function' && define.amd){
+ // AMD Anonymous Module
+ define(['jquery'], factory);
+ } else {
+ // No module loader (plain <script> tag) - put directly in global namespace
+ $.sammy = window.Sammy = factory($);
+ }
+ })
+
+// END olamy hack
+(function($) {
+$.i18n = {};
+
+/** Map holding bundle keys (if mode: 'map') */
+$.i18n.map = {};
+
+/**
+ * Load and parse message bundle files (.properties),
+ * making bundles keys available as javascript variables.
+ *
+ * i18n files are named <name>.js, or <name>_<language>.js or <name>_<language>_<country>.js
+ * Where:
+ * The <language> argument is a valid ISO Language Code. These codes are the lower-case,
+ * two-letter codes as defined by ISO-639. You can find a full list of these codes at a
+ * number of sites, such as: http://www.loc.gov/standards/iso639-2/englangn.html
+ * The <country> argument is a valid ISO Country Code. These codes are the upper-case,
+ * two-letter codes as defined by ISO-3166. You can find a full list of these codes at a
+ * number of sites, such as: http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
+ *
+ * Sample usage for a bundles/Messages.properties bundle:
+ * $.i18n.properties({
+ * name: 'Messages',
+ * language: 'en_US',
+ * path: 'bundles'
+ * });
+ * @param name (string/string[], optional) names of file to load (eg, 'Messages' or ['Msg1','Msg2']). Defaults to "Messages"
+ * @param language (string, optional) language/country code (eg, 'en', 'en_US', 'pt_PT'). if not specified, language reported by the browser will be used instead.
+ * @param path (string, optional) path of directory that contains file to load
+ * @param mode (string, optional) whether bundles keys are available as JavaScript variables/functions or as a map (eg, 'vars' or 'map')
+ * @param cache (boolean, optional) whether bundles should be cached by the browser, or forcibly reloaded on each page load. Defaults to false (i.e. forcibly reloaded)
+ * @param encoding (string, optional) the encoding to request for bundles. Property file resource bundles are specified to be in ISO-8859-1 format. Defaults to UTF-8 for backward compatibility.
+ * @param callback (function, optional) callback function to be called after script is terminated
+ */
+$.i18n.properties = function(settings) {
+ // set up settings
+ var defaults = {
+ name: 'Messages',
+ language: '',
+ path: '',
+ mode: 'vars',
+ cache: false,
+ encoding: 'UTF-8',
+ callback: null
+ };
+ settings = $.extend(defaults, settings);
+ if(settings.language === null || settings.language == '') {
+ settings.language = $.i18n.browserLang();
+ }
+ if(settings.language === null) {settings.language='';}
+
+ // load and parse bundle files
+ var files = getFiles(settings.name);
+ for(i=0; i<files.length; i++) {
+ // 1. load base (eg, Messages.properties)
+ loadAndParseFile(settings.path + files[i] + '.properties', settings);
+ // 2. with language code (eg, Messages_pt.properties)
+ if(settings.language.length >= 2) {
+ loadAndParseFile(settings.path + files[i] + '_' + settings.language.substring(0, 2) +'.properties', settings);
+ }
+ // 3. with language code and country code (eg, Messages_pt_PT.properties)
+ if(settings.language.length >= 5) {
+ loadAndParseFile(settings.path + files[i] + '_' + settings.language.substring(0, 5) +'.properties', settings);
+ }
+ }
+
+ // call callback
+ if(settings.callback){ settings.callback(); }
+};
+
+
+/**
+ * When configured with mode: 'map', allows access to bundle values by specifying its key.
+ * Eg, jQuery.i18n.prop('com.company.bundles.menu_add')
+ */
+$.i18n.prop = function(key /* Add parameters as function arguments as necessary */) {
+ var value = $.i18n.map[key];
+ if (value == null) {
+ if (window.archivaRuntimeInfo.logMissingI18n){
+ $.get('restServices/archivaUiServices/runtimeInfoService/logMissingI18n?key='+encodeURIComponent(key));
+ }
+ return '[' + key + ']';
+ }
+
+// if(arguments.length < 2) // No arguments.
+// //if(key == 'spv.lbl.modified') {alert(value);}
+// return value;
+
+// if (!$.isArray(placeHolderValues)) {
+// // If placeHolderValues is not an array, make it into one.
+// placeHolderValues = [placeHolderValues];
+// for (var i=2; i<arguments.length; i++)
+// placeHolderValues.push(arguments[i]);
+// }
+
+ // Place holder replacement
+ /**
+ * Tested with:
+ * test.t1=asdf ''{0}''
+ * test.t2=asdf '{0}' '{1}'{1}'zxcv
+ * test.t3=This is \"a quote" 'a''{0}''s'd{fgh{ij'
+ * test.t4="'''{'0}''" {0}{a}
+ * test.t5="'''{0}'''" {1}
+ * test.t6=a {1} b {0} c
+ * test.t7=a 'quoted \\ s\ttringy' \t\t x
+ *
+ * Produces:
+ * test.t1, p1 ==> asdf 'p1'
+ * test.t2, p1 ==> asdf {0} {1}{1}zxcv
+ * test.t3, p1 ==> This is "a quote" a'{0}'sd{fgh{ij
+ * test.t4, p1 ==> "'{0}'" p1{a}
+ * test.t5, p1 ==> "'{0}'" {1}
+ * test.t6, p1 ==> a {1} b p1 c
+ * test.t6, p1, p2 ==> a p2 b p1 c
+ * test.t6, p1, p2, p3 ==> a p2 b p1 c
+ * test.t7 ==> a quoted \ s tringy x
+ */
+
+ var i;
+ if (typeof(value) == 'string') {
+ // Handle escape characters. Done separately from the tokenizing loop below because escape characters are
+ // active in quoted strings.
+ i = 0;
+ while ((i = value.indexOf('\\', i)) != -1) {
+ if (value[i+1] == 't')
+ value = value.substring(0, i) + '\t' + value.substring((i++) + 2); // tab
+ else if (value[i+1] == 'r')
+ value = value.substring(0, i) + '\r' + value.substring((i++) + 2); // return
+ else if (value[i+1] == 'n')
+ value = value.substring(0, i) + '\n' + value.substring((i++) + 2); // line feed
+ else if (value[i+1] == 'f')
+ value = value.substring(0, i) + '\f' + value.substring((i++) + 2); // form feed
+ else if (value[i+1] == '\\')
+ value = value.substring(0, i) + '\\' + value.substring((i++) + 2); // \
+ else
+ value = value.substring(0, i) + value.substring(i+1); // Quietly drop the character
+ }
+
+ // Lazily convert the string to a list of tokens.
+ var arr = [], j, index;
+ i = 0;
+ while (i < value.length) {
+ if (value[i] == '\'') {
+ // Handle quotes
+ if (i == value.length-1)
+ value = value.substring(0, i); // Silently drop the trailing quote
+ else if (value[i+1] == '\'')
+ value = value.substring(0, i) + value.substring(++i); // Escaped quote
+ else {
+ // Quoted string
+ j = i + 2;
+ while ((j = value.indexOf('\'', j)) != -1) {
+ if (j == value.length-1 || value[j+1] != '\'') {
+ // Found start and end quotes. Remove them
+ value = value.substring(0,i) + value.substring(i+1, j) + value.substring(j+1);
+ i = j - 1;
+ break;
+ }
+ else {
+ // Found a double quote, reduce to a single quote.
+ value = value.substring(0,j) + value.substring(++j);
+ }
+ }
+
+ if (j == -1) {
+ // There is no end quote. Drop the start quote
+ value = value.substring(0,i) + value.substring(i+1);
+ }
+ }
+ }
+ else if (value[i] == '{') {
+ // Beginning of an unquoted place holder.
+ j = value.indexOf('}', i+1);
+ if (j == -1)
+ i++; // No end. Process the rest of the line. Java would throw an exception
+ else {
+ // Add 1 to the index so that it aligns with the function arguments.
+ index = parseInt(value.substring(i+1, j));
+ if (!isNaN(index) && index >= 0) {
+ // Put the line thus far (if it isn't empty) into the array
+ var s = value.substring(0, i);
+ if (s != "")
+ arr.push(s);
+ // Put the parameter reference into the array
+ arr.push(index);
+ // Start the processing over again starting from the rest of the line.
+ i = 0;
+ value = value.substring(j+1);
+ }
+ else
+ i = j + 1; // Invalid parameter. Leave as is.
+ }
+ }
+ else
+ i++;
+ }
+
+ // Put the remainder of the no-empty line into the array.
+ if (value != "")
+ arr.push(value);
+ value = arr;
+
+ // Make the array the value for the entry.
+ $.i18n.map[key] = arr;
+ }
+
+ if (value.length == 0)
+ return "";
+ if (value.lengh == 1 && typeof(value[0]) == "string")
+ return value[0];
+
+ var s = "";
+ for (i=0; i<value.length; i++) {
+ if (typeof(value[i]) == "string")
+ s += value[i];
+ // Must be a number
+ else if (value[i] + 1 < arguments.length)
+ s += arguments[value[i] + 1];
+ else
+ s += "{"+ value[i] +"}";
+ }
+
+ return s;
+};
+
+/** Language reported by browser, normalized code */
+$.i18n.browserLang = function() {
+ return normaliseLanguageCode(navigator.language /* Mozilla */ || navigator.userLanguage /* IE */);
+}
+
+
+/** Load and parse .properties files */
+loadAndParseFile = function (filename, settings) {
+ $.ajax({
+ url: filename,
+ async: true,
+ cache: settings.cache,
+ contentType:'text/plain;charset='+ settings.encoding,
+ dataType: 'text',
+ success: function(data, status) {
+ parseData(data, settings.mode);
+ if(settings.callback){ settings.callback(); }
+ }
+ });
+}
+
+/** Parse .properties files */
+parseData = function(data, mode) {
+ var parsed = '';
+ var parameters = data.split( /\n/ );
+ var regPlaceHolder = /(\{\d+\})/g;
+ var regRepPlaceHolder = /\{(\d+)\}/g;
+ var unicodeRE = /(\\u.{4})/ig;
+ for(var i=0; i<parameters.length; i++ ) {
+ parameters[i] = parameters[i].replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
+ if(parameters[i].length > 0 && parameters[i].match("^#")!="#") { // skip comments
+ var pair = parameters[i].split('=');
+ if(pair.length > 0) {
+ /** Process key & value */
+ var name = unescape(pair[0]).replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
+ var value = pair.length == 1 ? "" : pair[1];
+ // process multi-line values
+ while(value.match(/\\$/)=="\\") {
+ value = value.substring(0, value.length - 1);
+ value += parameters[++i].replace( /\s\s*$/, '' ); // right trim
+ }
+ // Put values with embedded '='s back together
+ for(var s=2;s<pair.length;s++){ value +='=' + pair[s]; }
+ value = value.replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
+
+ /** Mode: bundle keys in a map */
+ if(mode == 'map' || mode == 'both') {
+ // handle unicode chars possibly left out
+ var unicodeMatches = value.match(unicodeRE);
+ if(unicodeMatches) {
+ for(var u=0; u<unicodeMatches.length; u++) {
+ value = value.replace( unicodeMatches[u], unescapeUnicode(unicodeMatches[u]));
+ }
+ }
+ // add to map
+ $.i18n.map[name] = value;
+ // olamy hack replace . with _
+ //var nName = name.replace (/\./g, '_');
+ //$.i18n.map[nName] = value;
+ }
+
+ /** Mode: bundle keys as vars/functions */
+ if(mode == 'vars' || mode == 'both') {
+ value = value.replace( /"/g, '\\"' ); // escape quotation mark (")
+
+ // make sure namespaced key exists (eg, 'some.key')
+ checkKeyNamespace(name);
+
+ // value with variable substitutions
+ if(regPlaceHolder.test(value)) {
+ var parts = value.split(regPlaceHolder);
+ // process function args
+ var first = true;
+ var fnArgs = '';
+ var usedArgs = [];
+ for(var p=0; p<parts.length; p++) {
+ if(regPlaceHolder.test(parts[p]) && (usedArgs.length == 0 || usedArgs.indexOf(parts[p]) == -1)) {
+ if(!first) {fnArgs += ',';}
+ fnArgs += parts[p].replace(regRepPlaceHolder, 'v$1');
+ usedArgs.push(parts[p]);
+ first = false;
+ }
+ }
+ parsed += name + '=function(' + fnArgs + '){';
+ // process function body
+ var fnExpr = '"' + value.replace(regRepPlaceHolder, '"+v$1+"') + '"';
+ parsed += 'return ' + fnExpr + ';' + '};';
+
+ // simple value
+ }else{
+ parsed += name+'="'+value+'";';
+ }
+ } // END: Mode: bundle keys as vars/functions
+ } // END: if(pair.length > 0)
+ } // END: skip comments
+ }
+ eval(parsed);
+}
+
+/** Make sure namespace exists (for keys with dots in name) */
+// TODO key parts that start with numbers quietly fail. i.e. month.short.1=Jan
+function checkKeyNamespace(key) {
+ var regDot = /\./;
+ if(regDot.test(key)) {
+ var fullname = '';
+ var names = key.split( /\./ );
+ for(var i=0; i<names.length; i++) {
+ if(i>0) {fullname += '.';}
+ fullname += names[i];
+ if(eval('typeof '+fullname+' == "undefined"')) {
+ eval(fullname + '={};');
+ }
+ }
+ }
+}
+
+/** Make sure filename is an array */
+function getFiles(names) {
+ return (names && names.constructor == Array) ? names : [names];
+}
+
+/** Ensure language code is in the format aa_AA. */
+function normaliseLanguageCode(lang) {
+ lang = lang.toLowerCase();
+ if(lang.length > 3) {
+ lang = lang.substring(0, 3) + lang.substring(3).toUpperCase();
+ }
+ return lang;
+}
+
+/** Unescape unicode chars ('\u00e3') */
+function unescapeUnicode(str) {
+ // unescape unicode codes
+ var codes = [];
+ var code = parseInt(str.substr(2), 16);
+ if (code >= 0 && code < Math.pow(2, 16)) {
+ codes.push(code);
+ }
+ // convert codes to text
+ var unescaped = '';
+ for (var i = 0; i < codes.length; ++i) {
+ unescaped += String.fromCharCode(codes[i]);
+ }
+ return unescaped;
+}
+
+/* Cross-Browser Split 1.0.1
+(c) Steven Levithan <stevenlevithan.com>; MIT License
+An ECMA-compliant, uniform cross-browser split method */
+var cbSplit;
+// avoid running twice, which would break `cbSplit._nativeSplit`'s reference to the native `split`
+if (!cbSplit) {
+ cbSplit = function(str, separator, limit) {
+ // if `separator` is not a regex, use the native `split`
+ if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
+ if(typeof cbSplit._nativeSplit == "undefined")
+ return str.split(separator, limit);
+ else
+ return cbSplit._nativeSplit.call(str, separator, limit);
+ }
+
+ var output = [],
+ lastLastIndex = 0,
+ flags = (separator.ignoreCase ? "i" : "") +
+ (separator.multiline ? "m" : "") +
+ (separator.sticky ? "y" : ""),
+ separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy
+ separator2, match, lastIndex, lastLength;
+
+ str = str + ""; // type conversion
+ if (!cbSplit._compliantExecNpcg) {
+ separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt
+ }
+
+ /* behavior for `limit`: if it's...
+ - `undefined`: no limit.
+ - `NaN` or zero: return an empty array.
+ - a positive number: use `Math.floor(limit)`.
+ - a negative number: no limit.
+ - other: type-convert, then use the above rules. */
+ if (limit === undefined || +limit < 0) {
+ limit = Infinity;
+ } else {
+ limit = Math.floor(+limit);
+ if (!limit) {
+ return [];
+ }
+ }
+
+ while (match = separator.exec(str)) {
+ lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser
+
+ if (lastIndex > lastLastIndex) {
+ output.push(str.slice(lastLastIndex, match.index));
+
+ // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups
+ if (!cbSplit._compliantExecNpcg && match.length > 1) {
+ match[0].replace(separator2, function () {
+ for (var i = 1; i < arguments.length - 2; i++) {
+ if (arguments[i] === undefined) {
+ match[i] = undefined;
+ }
+ }
+ });
+ }
+
+ if (match.length > 1 && match.index < str.length) {
+ Array.prototype.push.apply(output, match.slice(1));
+ }
+
+ lastLength = match[0].length;
+ lastLastIndex = lastIndex;
+
+ if (output.length >= limit) {
+ break;
+ }
+ }
+
+ if (separator.lastIndex === match.index) {
+ separator.lastIndex++; // avoid an infinite loop
+ }
+ }
+
+ if (lastLastIndex === str.length) {
+ if (lastLength || !separator.test("")) {
+ output.push("");
+ }
+ } else {
+ output.push(str.slice(lastLastIndex));
+ }
+
+ return output.length > limit ? output.slice(0, limit) : output;
+ };
+
+ cbSplit._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group
+ cbSplit._nativeSplit = String.prototype.split;
+
+} // end `if (!cbSplit)`
+String.prototype.split = function (separator, limit) {
+ return cbSplit(this, separator, limit);
+};
+
+});// (jQuery);
+
+// START olamy hack more AMD compliant
+})(jQuery, window);
+// END olamy hack \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.iframe-transport-1.4.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.iframe-transport-1.4.js
new file mode 100644
index 000000000..04a566230
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.iframe-transport-1.4.js
@@ -0,0 +1,171 @@
+/*
+ * jQuery Iframe Transport Plugin 1.4
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2011, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint unparam: true, nomen: true */
+/*global define, window, document */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define(['jquery'], factory);
+ } else {
+ // Browser globals:
+ factory(window.jQuery);
+ }
+}(function ($) {
+ 'use strict';
+
+ // Helper variable to create unique names for the transport iframes:
+ var counter = 0;
+
+ // The iframe transport accepts three additional options:
+ // options.fileInput: a jQuery collection of file input fields
+ // options.paramName: the parameter name for the file form data,
+ // overrides the name property of the file input field(s),
+ // can be a string or an array of strings.
+ // options.formData: an array of objects with name and value properties,
+ // equivalent to the return data of .serializeArray(), e.g.:
+ // [{name: 'a', value: 1}, {name: 'b', value: 2}]
+ $.ajaxTransport('iframe', function (options) {
+ if (options.async && (options.type === 'POST' || options.type === 'GET')) {
+ var form,
+ iframe;
+ return {
+ send: function (_, completeCallback) {
+ form = $('<form style="display:none;"></form>');
+ // javascript:false as initial iframe src
+ // prevents warning popups on HTTPS in IE6.
+ // IE versions below IE8 cannot set the name property of
+ // elements that have already been added to the DOM,
+ // so we set the name along with the iframe HTML markup:
+ iframe = $(
+ '<iframe src="javascript:false;" name="iframe-transport-' +
+ (counter += 1) + '"></iframe>'
+ ).bind('load', function () {
+ var fileInputClones,
+ paramNames = $.isArray(options.paramName) ?
+ options.paramName : [options.paramName];
+ iframe
+ .unbind('load')
+ .bind('load', function () {
+ var response;
+ // Wrap in a try/catch block to catch exceptions thrown
+ // when trying to access cross-domain iframe contents:
+ try {
+ response = iframe.contents();
+ // Google Chrome and Firefox do not throw an
+ // exception when calling iframe.contents() on
+ // cross-domain requests, so we unify the response:
+ if (!response.length || !response[0].firstChild) {
+ throw new Error();
+ }
+ } catch (e) {
+ response = undefined;
+ }
+ // The complete callback returns the
+ // iframe content document as response object:
+ completeCallback(
+ 200,
+ 'success',
+ {'iframe': response}
+ );
+ // Fix for IE endless progress bar activity bug
+ // (happens on form submits to iframe targets):
+ $('<iframe src="javascript:false;"></iframe>')
+ .appendTo(form);
+ form.remove();
+ });
+ form
+ .prop('target', iframe.prop('name'))
+ .prop('action', options.url)
+ .prop('method', options.type);
+ if (options.formData) {
+ $.each(options.formData, function (index, field) {
+ $('<input type="hidden"/>')
+ .prop('name', field.name)
+ .val(field.value)
+ .appendTo(form);
+ });
+ }
+ if (options.fileInput && options.fileInput.length &&
+ options.type === 'POST') {
+ fileInputClones = options.fileInput.clone();
+ // Insert a clone for each file input field:
+ options.fileInput.after(function (index) {
+ return fileInputClones[index];
+ });
+ if (options.paramName) {
+ options.fileInput.each(function (index) {
+ $(this).prop(
+ 'name',
+ paramNames[index] || options.paramName
+ );
+ });
+ }
+ // Appending the file input fields to the hidden form
+ // removes them from their original location:
+ form
+ .append(options.fileInput)
+ .prop('enctype', 'multipart/form-data')
+ // enctype must be set as encoding for IE:
+ .prop('encoding', 'multipart/form-data');
+ }
+ form.submit();
+ // Insert the file input fields at their original location
+ // by replacing the clones with the originals:
+ if (fileInputClones && fileInputClones.length) {
+ options.fileInput.each(function (index, input) {
+ var clone = $(fileInputClones[index]);
+ $(input).prop('name', clone.prop('name'));
+ clone.replaceWith(input);
+ });
+ }
+ });
+ form.append(iframe).appendTo(document.body);
+ },
+ abort: function () {
+ if (iframe) {
+ // javascript:false as iframe src aborts the request
+ // and prevents warning popups on HTTPS in IE6.
+ // concat is used to avoid the "Script URL" JSLint error:
+ iframe
+ .unbind('load')
+ .prop('src', 'javascript'.concat(':false;'));
+ }
+ if (form) {
+ form.remove();
+ }
+ }
+ };
+ }
+ });
+
+ // The iframe transport returns the iframe content document as response.
+ // The following adds converters from iframe to text, json, html, and script:
+ $.ajaxSetup({
+ converters: {
+ 'iframe text': function (iframe) {
+ return $(iframe[0].body).text();
+ },
+ 'iframe json': function (iframe) {
+ return $.parseJSON($(iframe[0].body).text());
+ },
+ 'iframe html': function (iframe) {
+ return $(iframe[0].body).html();
+ },
+ 'iframe script': function (iframe) {
+ return $.globalEval($(iframe[0].body).text());
+ }
+ }
+ });
+
+}));
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.json-2.3.min.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.json-2.3.min.js
new file mode 100644
index 000000000..4e4e38680
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.json-2.3.min.js
@@ -0,0 +1,23 @@
+
+(function($){var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};$.toJSON=typeof JSON==='object'&&JSON.stringify?JSON.stringify:function(o){if(o===null){return'null';}
+var type=typeof o;if(type==='undefined'){return undefined;}
+if(type==='number'||type==='boolean'){return''+o;}
+if(type==='string'){return $.quoteString(o);}
+if(type==='object'){if(typeof o.toJSON==='function'){return $.toJSON(o.toJSON());}
+if(o.constructor===Date){var month=o.getUTCMonth()+1,day=o.getUTCDate(),year=o.getUTCFullYear(),hours=o.getUTCHours(),minutes=o.getUTCMinutes(),seconds=o.getUTCSeconds(),milli=o.getUTCMilliseconds();if(month<10){month='0'+month;}
+if(day<10){day='0'+day;}
+if(hours<10){hours='0'+hours;}
+if(minutes<10){minutes='0'+minutes;}
+if(seconds<10){seconds='0'+seconds;}
+if(milli<100){milli='0'+milli;}
+if(milli<10){milli='0'+milli;}
+return'"'+year+'-'+month+'-'+day+'T'+
+hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
+if(o.constructor===Array){var ret=[];for(var i=0;i<o.length;i++){ret.push($.toJSON(o[i])||'null');}
+return'['+ret.join(',')+']';}
+var name,val,pairs=[];for(var k in o){type=typeof k;if(type==='number'){name='"'+k+'"';}else if(type==='string'){name=$.quoteString(k);}else{continue;}
+type=typeof o[k];if(type==='function'||type==='undefined'){continue;}
+val=$.toJSON(o[k]);pairs.push(name+':'+val);}
+return'{'+pairs.join(',')+'}';}};$.evalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(src){return eval('('+src+')');};$.secureEvalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(src){var filtered=src.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered)){return eval('('+src+')');}else{throw new SyntaxError('Error parsing JSON, source is not valid.');}};$.quoteString=function(string){if(string.match(escapeable)){return'"'+string.replace(escapeable,function(a){var c=meta[a];if(typeof c==='string'){return c;}
+c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
+return'"'+string+'"';};})(jQuery); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.tmpl.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.tmpl.js
new file mode 100644
index 000000000..c10fc8f75
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.tmpl.js
@@ -0,0 +1,492 @@
+/*!
+ * jQuery Templates Plugin 1.0.0pre
+ * http://github.com/jquery/jquery-tmpl
+ * Requires jQuery 1.4.2
+ *
+ * Copyright Software Freedom Conservancy, Inc.
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ */
+
+define("jquery.tmpl",["jquery"],
+function() {
+
+//(function( jQuery, undefined ){
+ var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
+ newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
+
+ function newTmplItem( options, parentItem, fn, data ) {
+ // Returns a template item data structure for a new rendered instance of a template (a 'template item').
+ // The content field is a hierarchical array of strings and nested items (to be
+ // removed and replaced by nodes field of dom elements, once inserted in DOM).
+ var newItem = {
+ data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
+ _wrap: parentItem ? parentItem._wrap : null,
+ tmpl: null,
+ parent: parentItem || null,
+ nodes: [],
+ calls: tiCalls,
+ nest: tiNest,
+ wrap: tiWrap,
+ html: tiHtml,
+ update: tiUpdate
+ };
+ if ( options ) {
+ jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
+ }
+ if ( fn ) {
+ // Build the hierarchical content to be used during insertion into DOM
+ newItem.tmpl = fn;
+ newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
+ newItem.key = ++itemKey;
+ // Keep track of new template item, until it is stored as jQuery Data on DOM element
+ (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
+ }
+ return newItem;
+ }
+
+ // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
+ jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+ }, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
+ parent = this.length === 1 && this[0].parentNode;
+
+ appendToTmplItems = newTmplItems || {};
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ ret = this;
+ } else {
+ for ( i = 0, l = insert.length; i < l; i++ ) {
+ cloneIndex = i;
+ elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+ cloneIndex = 0;
+ ret = this.pushStack( ret, name, insert.selector );
+ }
+ tmplItems = appendToTmplItems;
+ appendToTmplItems = null;
+ jQuery.tmpl.complete( tmplItems );
+ return ret;
+ };
+ });
+
+ jQuery.fn.extend({
+ // Use first wrapped element as template markup.
+ // Return wrapped set of template items, obtained by rendering template against data.
+ tmpl: function( data, options, parentItem ) {
+ return jQuery.tmpl( this[0], data, options, parentItem );
+ },
+
+ // Find which rendered template item the first wrapped DOM element belongs to
+ tmplItem: function() {
+ return jQuery.tmplItem( this[0] );
+ },
+
+ // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
+ template: function( name ) {
+ return jQuery.template( name, this[0] );
+ },
+
+ domManip: function( args, table, callback, options ) {
+ if ( args[0] && jQuery.isArray( args[0] )) {
+ var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
+ while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
+ if ( tmplItem && cloneIndex ) {
+ dmArgs[2] = function( fragClone ) {
+ // Handler called by oldManip when rendered template has been inserted into DOM.
+ jQuery.tmpl.afterManip( this, fragClone, callback );
+ };
+ }
+ oldManip.apply( this, dmArgs );
+ } else {
+ oldManip.apply( this, arguments );
+ }
+ cloneIndex = 0;
+ if ( !appendToTmplItems ) {
+ jQuery.tmpl.complete( newTmplItems );
+ }
+ return this;
+ }
+ });
+
+ jQuery.extend({
+ // Return wrapped set of template items, obtained by rendering template against data.
+ tmpl: function( tmpl, data, options, parentItem ) {
+ var ret, topLevel = !parentItem;
+ if ( topLevel ) {
+ // This is a top-level tmpl call (not from a nested template using {{tmpl}})
+ parentItem = topTmplItem;
+ tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
+ wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
+ } else if ( !tmpl ) {
+ // The template item is already associated with DOM - this is a refresh.
+ // Re-evaluate rendered template for the parentItem
+ tmpl = parentItem.tmpl;
+ newTmplItems[parentItem.key] = parentItem;
+ parentItem.nodes = [];
+ if ( parentItem.wrapped ) {
+ updateWrapped( parentItem, parentItem.wrapped );
+ }
+ // Rebuild, without creating a new template item
+ return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
+ }
+ if ( !tmpl ) {
+ return []; // Could throw...
+ }
+ if ( typeof data === "function" ) {
+ data = data.call( parentItem || {} );
+ }
+ if ( options && options.wrapped ) {
+ updateWrapped( options, options.wrapped );
+ }
+ ret = jQuery.isArray( data ) ?
+ jQuery.map( data, function( dataItem ) {
+ return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
+ }) :
+ [ newTmplItem( options, parentItem, tmpl, data ) ];
+ return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
+ },
+
+ // Return rendered template item for an element.
+ tmplItem: function( elem ) {
+ var tmplItem;
+ if ( elem instanceof jQuery ) {
+ elem = elem[0];
+ }
+ while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
+ return tmplItem || topTmplItem;
+ },
+
+ // Set:
+ // Use $.template( name, tmpl ) to cache a named template,
+ // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
+ // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
+
+ // Get:
+ // Use $.template( name ) to access a cached template.
+ // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
+ // will return the compiled template, without adding a name reference.
+ // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
+ // to $.template( null, templateString )
+ template: function( name, tmpl ) {
+ if (tmpl) {
+ // Compile template and associate with name
+ if ( typeof tmpl === "string" ) {
+ // This is an HTML string being passed directly in.
+ tmpl = buildTmplFn( tmpl );
+ } else if ( tmpl instanceof jQuery ) {
+ tmpl = tmpl[0] || {};
+ }
+ if ( tmpl.nodeType ) {
+ // If this is a template block, use cached copy, or generate tmpl function and cache.
+ tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
+ // Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
+ // This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
+ // To correct this, include space in tag: foo="${ x }" -> foo="value of x"
+ }
+ return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
+ }
+ // Return named compiled template
+ return name ? (typeof name !== "string" ? jQuery.template( null, name ):
+ (jQuery.template[name] ||
+ // If not in map, and not containing at least on HTML tag, treat as a selector.
+ // (If integrated with core, use quickExpr.exec)
+ jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
+ },
+
+ encode: function( text ) {
+ // Do HTML encoding replacing < > & and ' and " by corresponding entities.
+ return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
+ }
+ });
+
+ jQuery.extend( jQuery.tmpl, {
+ tag: {
+ "tmpl": {
+ _default: { $2: "null" },
+ open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
+ // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
+ // This means that {{tmpl foo}} treats foo as a template (which IS a function).
+ // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
+ },
+ "wrap": {
+ _default: { $2: "null" },
+ open: "$item.calls(__,$1,$2);__=[];",
+ close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
+ },
+ "each": {
+ _default: { $2: "$index, $value" },
+ open: "if($notnull_1){$.each($1a,function($2){with(this){",
+ close: "}});}"
+ },
+ "if": {
+ open: "if(($notnull_1) && $1a){",
+ close: "}"
+ },
+ "else": {
+ _default: { $1: "true" },
+ open: "}else if(($notnull_1) && $1a){"
+ },
+ "html": {
+ // Unecoded expression evaluation.
+ open: "if($notnull_1){__.push($1a);}"
+ },
+ "=": {
+ // Encoded expression evaluation. Abbreviated form is ${}.
+ _default: { $1: "$data" },
+ open: "if($notnull_1){__.push($.encode($1a));}"
+ },
+ "!": {
+ // Comment tag. Skipped by parser
+ open: ""
+ }
+ },
+
+ // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
+ complete: function( items ) {
+ newTmplItems = {};
+ },
+
+ // Call this from code which overrides domManip, or equivalent
+ // Manage cloning/storing template items etc.
+ afterManip: function afterManip( elem, fragClone, callback ) {
+ // Provides cloned fragment ready for fixup prior to and after insertion into DOM
+ var content = fragClone.nodeType === 11 ?
+ jQuery.makeArray(fragClone.childNodes) :
+ fragClone.nodeType === 1 ? [fragClone] : [];
+
+ // Return fragment to original caller (e.g. append) for DOM insertion
+ callback.call( elem, fragClone );
+
+ // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
+ storeTmplItems( content );
+ cloneIndex++;
+ }
+ });
+
+ //========================== Private helper functions, used by code above ==========================
+
+ function build( tmplItem, nested, content ) {
+ // Convert hierarchical content into flat string array
+ // and finally return array of fragments ready for DOM insertion
+ var frag, ret = content ? jQuery.map( content, function( item ) {
+ return (typeof item === "string") ?
+ // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
+ (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
+ // This is a child template item. Build nested template.
+ build( item, tmplItem, item._ctnt );
+ }) :
+ // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
+ tmplItem;
+ if ( nested ) {
+ return ret;
+ }
+
+ // top-level template
+ ret = ret.join("");
+
+ // Support templates which have initial or final text nodes, or consist only of text
+ // Also support HTML entities within the HTML markup.
+ ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
+ frag = jQuery( middle ).get();
+
+ storeTmplItems( frag );
+ if ( before ) {
+ frag = unencode( before ).concat(frag);
+ }
+ if ( after ) {
+ frag = frag.concat(unencode( after ));
+ }
+ });
+ return frag ? frag : unencode( ret );
+ }
+
+ function unencode( text ) {
+ // Use createElement, since createTextNode will not render HTML entities correctly
+ var el = document.createElement( "div" );
+ el.innerHTML = text;
+ return jQuery.makeArray(el.childNodes);
+ }
+
+ // Generate a reusable function that will serve to render a template against data
+ function buildTmplFn( markup ) {
+ return new Function("jQuery","$item",
+ // Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
+ "var $=jQuery,call,__=[],$data=$item.data;" +
+
+ // Introduce the data as local variables using with(){}
+ "with($data){__.push('" +
+
+ // Convert the template into pure JavaScript
+ jQuery.trim(markup)
+ .replace( /([\\'])/g, "\\$1" )
+ .replace( /[\r\t\n]/g, " " )
+ .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
+ .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
+ function( all, slash, type, fnargs, target, parens, args ) {
+ var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
+ if ( !tag ) {
+ throw "Unknown template tag: " + type;
+ }
+ def = tag._default || [];
+ if ( parens && !/\w$/.test(target)) {
+ target += parens;
+ parens = "";
+ }
+ if ( target ) {
+ target = unescape( target );
+ args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
+ // Support for target being things like a.toLowerCase();
+ // In that case don't call with template item as 'this' pointer. Just evaluate...
+ expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
+ exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
+ } else {
+ exprAutoFnDetect = expr = def.$1 || "null";
+ }
+ fnargs = unescape( fnargs );
+ return "');" +
+ tag[ slash ? "close" : "open" ]
+ .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
+ .split( "$1a" ).join( exprAutoFnDetect )
+ .split( "$1" ).join( expr )
+ .split( "$2" ).join( fnargs || def.$2 || "" ) +
+ "__.push('";
+ }) +
+ "');}return __;"
+ );
+ }
+ function updateWrapped( options, wrapped ) {
+ // Build the wrapped content.
+ options._wrap = build( options, true,
+ // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
+ jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
+ ).join("");
+ }
+
+ function unescape( args ) {
+ return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
+ }
+ function outerHtml( elem ) {
+ var div = document.createElement("div");
+ div.appendChild( elem.cloneNode(true) );
+ return div.innerHTML;
+ }
+
+ // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
+ function storeTmplItems( content ) {
+ var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
+ for ( i = 0, l = content.length; i < l; i++ ) {
+ if ( (elem = content[i]).nodeType !== 1 ) {
+ continue;
+ }
+ elems = elem.getElementsByTagName("*");
+ for ( m = elems.length - 1; m >= 0; m-- ) {
+ processItemKey( elems[m] );
+ }
+ processItemKey( elem );
+ }
+ function processItemKey( el ) {
+ var pntKey, pntNode = el, pntItem, tmplItem, key;
+ // Ensure that each rendered template inserted into the DOM has its own template item,
+ if ( (key = el.getAttribute( tmplItmAtt ))) {
+ while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
+ if ( pntKey !== key ) {
+ // The next ancestor with a _tmplitem expando is on a different key than this one.
+ // So this is a top-level element within this template item
+ // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
+ pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
+ if ( !(tmplItem = newTmplItems[key]) ) {
+ // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
+ tmplItem = wrappedItems[key];
+ tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
+ tmplItem.key = ++itemKey;
+ newTmplItems[itemKey] = tmplItem;
+ }
+ if ( cloneIndex ) {
+ cloneTmplItem( key );
+ }
+ }
+ el.removeAttribute( tmplItmAtt );
+ } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
+ // This was a rendered element, cloned during append or appendTo etc.
+ // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
+ cloneTmplItem( tmplItem.key );
+ newTmplItems[tmplItem.key] = tmplItem;
+ pntNode = jQuery.data( el.parentNode, "tmplItem" );
+ pntNode = pntNode ? pntNode.key : 0;
+ }
+ if ( tmplItem ) {
+ pntItem = tmplItem;
+ // Find the template item of the parent element.
+ // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
+ while ( pntItem && pntItem.key != pntNode ) {
+ // Add this element as a top-level node for this rendered template item, as well as for any
+ // ancestor items between this item and the item of its parent element
+ pntItem.nodes.push( el );
+ pntItem = pntItem.parent;
+ }
+ // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
+ delete tmplItem._ctnt;
+ delete tmplItem._wrap;
+ // Store template item as jQuery data on the element
+ jQuery.data( el, "tmplItem", tmplItem );
+ }
+ function cloneTmplItem( key ) {
+ key = key + keySuffix;
+ tmplItem = newClonedItems[key] =
+ (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
+ }
+ }
+ }
+
+ //---- Helper functions for template item ----
+
+ function tiCalls( content, tmpl, data, options ) {
+ if ( !content ) {
+ return stack.pop();
+ }
+ stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
+ }
+
+ function tiNest( tmpl, data, options ) {
+ // nested template, using {{tmpl}} tag
+ return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
+ }
+
+ function tiWrap( call, wrapped ) {
+ // nested template, using {{wrap}} tag
+ var options = call.options || {};
+ options.wrapped = wrapped;
+ // Apply the template, which may incorporate wrapped content,
+ return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
+ }
+
+ function tiHtml( filter, textOnly ) {
+ var wrapped = this._wrap;
+ return jQuery.map(
+ jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
+ function(e) {
+ return textOnly ?
+ e.innerText || e.textContent :
+ e.outerHTML || outerHtml(e);
+ });
+ }
+
+ function tiUpdate() {
+ var coll = this.nodes;
+ jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
+ jQuery( coll ).remove();
+ }
+//})( jQuery );
+
+
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.ui.widget-1.9.2.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.ui.widget-1.9.2.js
new file mode 100755
index 000000000..067476d97
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.ui.widget-1.9.2.js
@@ -0,0 +1,528 @@
+/*!
+ * jQuery UI Widget 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/jQuery.widget/
+ */
+(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,
+ 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 ) ) {
+ prototype[ 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
+ }, prototype, {
+ constructor: constructor,
+ namespace: namespace,
+ widgetName: name,
+ // TODO remove widgetBaseClass, see #8155
+ widgetBaseClass: fullName,
+ 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 init
+ 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 ) {
+ // 1.9 BC for #7810
+ // TODO remove dual storage
+ $.data( element, this.widgetName, 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 ( value === undefined ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( value === undefined ) {
+ 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 ] || $.uiBackCompat !== false && $.effects[ 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();
+ });
+ }
+ };
+});
+
+// DEPRECATED
+if ( $.uiBackCompat !== false ) {
+ $.Widget.prototype._getCreateOptions = function() {
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
+ };
+}
+
+})( jQuery );
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.validate-1.9.0.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.validate-1.9.0.js
new file mode 100644
index 000000000..b7ed45b4a
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jquery.validate-1.9.0.js
@@ -0,0 +1,1188 @@
+/**
+ * jQuery Validation Plugin 1.9.0
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2011 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+
+(function($) {
+
+$.extend($.fn, {
+ // http://docs.jquery.com/Plugins/Validation/validate
+ validate: function( options ) {
+
+ // if nothing is selected, return nothing; can't chain anyway
+ if (!this.length) {
+ options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
+ return;
+ }
+
+ // check if a validator for this form was already created
+ var validator = $.data(this[0], 'validator');
+ if ( validator ) {
+ return validator;
+ }
+
+ // Add novalidate tag if HTML5.
+ this.attr('novalidate', 'novalidate');
+
+ validator = new $.validator( options, this[0] );
+ $.data(this[0], 'validator', validator);
+
+ if ( validator.settings.onsubmit ) {
+
+ var inputsAndButtons = this.find("input, button");
+
+ // allow suppresing validation by adding a cancel class to the submit button
+ inputsAndButtons.filter(".cancel").click(function () {
+ validator.cancelSubmit = true;
+ });
+
+ // when a submitHandler is used, capture the submitting button
+ if (validator.settings.submitHandler) {
+ inputsAndButtons.filter(":submit").click(function () {
+ validator.submitButton = this;
+ });
+ }
+
+ // validate the form on submit
+ this.submit( function( event ) {
+ if ( validator.settings.debug )
+ // prevent form submit to be able to see console output
+ event.preventDefault();
+
+ function handle() {
+ if ( validator.settings.submitHandler ) {
+ if (validator.submitButton) {
+ // insert a hidden input as a replacement for the missing submit button
+ var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
+ }
+ validator.settings.submitHandler.call( validator, validator.currentForm );
+ if (validator.submitButton) {
+ // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
+ hidden.remove();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // prevent submit for invalid forms or custom submit handlers
+ if ( validator.cancelSubmit ) {
+ validator.cancelSubmit = false;
+ return handle();
+ }
+ if ( validator.form() ) {
+ if ( validator.pendingRequest ) {
+ validator.formSubmitted = true;
+ return false;
+ }
+ return handle();
+ } else {
+ validator.focusInvalid();
+ return false;
+ }
+ });
+ }
+
+ return validator;
+ },
+ // http://docs.jquery.com/Plugins/Validation/valid
+ valid: function() {
+ if ( $(this[0]).is('form')) {
+ return this.validate().form();
+ } else {
+ var valid = true;
+ var validator = $(this[0].form).validate();
+ this.each(function() {
+ valid &= validator.element(this);
+ });
+ return valid;
+ }
+ },
+ // attributes: space seperated list of attributes to retrieve and remove
+ removeAttrs: function(attributes) {
+ var result = {},
+ $element = this;
+ $.each(attributes.split(/\s/), function(index, value) {
+ result[value] = $element.attr(value);
+ $element.removeAttr(value);
+ });
+ return result;
+ },
+ // http://docs.jquery.com/Plugins/Validation/rules
+ rules: function(command, argument) {
+ var element = this[0];
+
+ if (command) {
+ var settings = $.data(element.form, 'validator').settings;
+ var staticRules = settings.rules;
+ var existingRules = $.validator.staticRules(element);
+ switch(command) {
+ case "add":
+ $.extend(existingRules, $.validator.normalizeRule(argument));
+ staticRules[element.name] = existingRules;
+ if (argument.messages)
+ settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
+ break;
+ case "remove":
+ if (!argument) {
+ delete staticRules[element.name];
+ return existingRules;
+ }
+ var filtered = {};
+ $.each(argument.split(/\s/), function(index, method) {
+ filtered[method] = existingRules[method];
+ delete existingRules[method];
+ });
+ return filtered;
+ }
+ }
+
+ var data = $.validator.normalizeRules(
+ $.extend(
+ {},
+ $.validator.metadataRules(element),
+ $.validator.classRules(element),
+ $.validator.attributeRules(element),
+ $.validator.staticRules(element)
+ ), element);
+
+ // make sure required is at front
+ if (data.required) {
+ var param = data.required;
+ delete data.required;
+ data = $.extend({required: param}, data);
+ }
+
+ return data;
+ }
+});
+
+// Custom selectors
+$.extend($.expr[":"], {
+ // http://docs.jquery.com/Plugins/Validation/blank
+ blank: function(a) {return !$.trim("" + a.value);},
+ // http://docs.jquery.com/Plugins/Validation/filled
+ filled: function(a) {return !!$.trim("" + a.value);},
+ // http://docs.jquery.com/Plugins/Validation/unchecked
+ unchecked: function(a) {return !a.checked;}
+});
+
+// constructor for validator
+$.validator = function( options, form ) {
+ this.settings = $.extend( true, {}, $.validator.defaults, options );
+ this.currentForm = form;
+ this.init();
+};
+
+$.validator.format = function(source, params) {
+ if ( arguments.length == 1 )
+ return function() {
+ var args = $.makeArray(arguments);
+ args.unshift(source);
+ return $.validator.format.apply( this, args );
+ };
+ if ( arguments.length > 2 && params.constructor != Array ) {
+ params = $.makeArray(arguments).slice(1);
+ }
+ if ( params.constructor != Array ) {
+ params = [ params ];
+ }
+ $.each(params, function(i, n) {
+ source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
+ });
+ return source;
+};
+
+$.extend($.validator, {
+
+ defaults: {
+ messages: {},
+ groups: {},
+ rules: {},
+ errorClass: "error",
+ validClass: "valid",
+ errorElement: "label",
+ focusInvalid: true,
+ errorContainer: $( [] ),
+ errorLabelContainer: $( [] ),
+ onsubmit: true,
+ ignore: ":hidden",
+ ignoreTitle: false,
+ onfocusin: function(element, event) {
+ this.lastActive = element;
+
+ // hide error label and remove error class on focus if enabled
+ if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
+ this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
+ this.addWrapper(this.errorsFor(element)).hide();
+ }
+ },
+ onfocusout: function(element, event) {
+ if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
+ this.element(element);
+ }
+ },
+ onkeyup: function(element, event) {
+ if ( element.name in this.submitted || element == this.lastElement ) {
+ this.element(element);
+ }
+ },
+ onclick: function(element, event) {
+ // click on selects, radiobuttons and checkboxes
+ if ( element.name in this.submitted )
+ this.element(element);
+ // or option elements, check parent select in that case
+ else if (element.parentNode.name in this.submitted)
+ this.element(element.parentNode);
+ },
+ highlight: function(element, errorClass, validClass) {
+ if (element.type === 'radio') {
+ this.findByName(element.name).addClass(errorClass).removeClass(validClass);
+ } else {
+ $(element).addClass(errorClass).removeClass(validClass);
+ }
+ },
+ unhighlight: function(element, errorClass, validClass) {
+ if (element.type === 'radio') {
+ this.findByName(element.name).removeClass(errorClass).addClass(validClass);
+ } else {
+ $(element).removeClass(errorClass).addClass(validClass);
+ }
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
+ setDefaults: function(settings) {
+ $.extend( $.validator.defaults, settings );
+ },
+
+ messages: {
+ required: "This field is required.",
+ remote: "Please fix this field.",
+ email: "Please enter a valid email address.",
+ url: "Please enter a valid URL.",
+ date: "Please enter a valid date.",
+ dateISO: "Please enter a valid date (ISO).",
+ number: "Please enter a valid number.",
+ digits: "Please enter only digits.",
+ creditcard: "Please enter a valid credit card number.",
+ equalTo: "Please enter the same value again.",
+ accept: "Please enter a value with a valid extension.",
+ maxlength: $.validator.format("Please enter no more than {0} characters."),
+ minlength: $.validator.format("Please enter at least {0} characters."),
+ rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
+ range: $.validator.format("Please enter a value between {0} and {1}."),
+ max: $.validator.format("Please enter a value less than or equal to {0}."),
+ min: $.validator.format("Please enter a value greater than or equal to {0}.")
+ },
+
+ autoCreateRanges: false,
+
+ prototype: {
+
+ init: function() {
+ this.labelContainer = $(this.settings.errorLabelContainer);
+ this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
+ this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
+ this.submitted = {};
+ this.valueCache = {};
+ this.pendingRequest = 0;
+ this.pending = {};
+ this.invalid = {};
+ this.reset();
+
+ var groups = (this.groups = {});
+ $.each(this.settings.groups, function(key, value) {
+ $.each(value.split(/\s/), function(index, name) {
+ groups[name] = key;
+ });
+ });
+ var rules = this.settings.rules;
+ $.each(rules, function(key, value) {
+ rules[key] = $.validator.normalizeRule(value);
+ });
+
+ function delegate(event) {
+ var validator = $.data(this[0].form, "validator"),
+ eventType = "on" + event.type.replace(/^validate/, "");
+ validator.settings[eventType] && validator.settings[eventType].call(validator, this[0], event);
+ }
+ $(this.currentForm)
+ .validateDelegate("[type='text'], [type='password'], [type='file'], select, textarea, " +
+ "[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
+ "[type='email'], [type='datetime'], [type='date'], [type='month'], " +
+ "[type='week'], [type='time'], [type='datetime-local'], " +
+ "[type='range'], [type='color'] ",
+ "focusin focusout keyup", delegate)
+ .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);
+
+ if (this.settings.invalidHandler)
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
+ form: function() {
+ this.checkForm();
+ $.extend(this.submitted, this.errorMap);
+ this.invalid = $.extend({}, this.errorMap);
+ if (!this.valid())
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ this.showErrors();
+ return this.valid();
+ },
+
+ checkForm: function() {
+ this.prepareForm();
+ for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
+ this.check( elements[i] );
+ }
+ return this.valid();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/element
+ element: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+ this.lastElement = element;
+ this.prepareElement( element );
+ this.currentElements = $(element);
+ var result = this.check( element );
+ if ( result ) {
+ delete this.invalid[element.name];
+ } else {
+ this.invalid[element.name] = true;
+ }
+ if ( !this.numberOfInvalids() ) {
+ // Hide error containers on last error
+ this.toHide = this.toHide.add( this.containers );
+ }
+ this.showErrors();
+ return result;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
+ showErrors: function(errors) {
+ if(errors) {
+ // add items to error list and map
+ $.extend( this.errorMap, errors );
+ this.errorList = [];
+ for ( var name in errors ) {
+ this.errorList.push({
+ message: errors[name],
+ element: this.findByName(name)[0]
+ });
+ }
+ // remove items from success list
+ this.successList = $.grep( this.successList, function(element) {
+ return !(element.name in errors);
+ });
+ }
+ this.settings.showErrors
+ ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
+ : this.defaultShowErrors();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
+ resetForm: function() {
+ if ( $.fn.resetForm )
+ $( this.currentForm ).resetForm();
+ this.submitted = {};
+ this.lastElement = null;
+ this.prepareForm();
+ this.hideErrors();
+ this.elements().removeClass( this.settings.errorClass );
+ },
+
+ numberOfInvalids: function() {
+ return this.objectLength(this.invalid);
+ },
+
+ objectLength: function( obj ) {
+ var count = 0;
+ for ( var i in obj )
+ count++;
+ return count;
+ },
+
+ hideErrors: function() {
+ this.addWrapper( this.toHide ).hide();
+ },
+
+ valid: function() {
+ return this.size() == 0;
+ },
+
+ size: function() {
+ return this.errorList.length;
+ },
+
+ focusInvalid: function() {
+ if( this.settings.focusInvalid ) {
+ try {
+ $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
+ .filter(":visible")
+ .focus()
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
+ .trigger("focusin");
+ } catch(e) {
+ // ignore IE throwing errors when focusing hidden elements
+ }
+ }
+ },
+
+ findLastActive: function() {
+ var lastActive = this.lastActive;
+ return lastActive && $.grep(this.errorList, function(n) {
+ return n.element.name == lastActive.name;
+ }).length == 1 && lastActive;
+ },
+
+ elements: function() {
+ var validator = this,
+ rulesCache = {};
+
+ // select all valid inputs inside the form (no submit or reset buttons)
+ return $(this.currentForm)
+ .find("input, select, textarea")
+ .not(":submit, :reset, :image, [disabled]")
+ .not( this.settings.ignore )
+ .filter(function() {
+ !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
+
+ // select only the first element for each name, and only those with rules specified
+ if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
+ return false;
+
+ rulesCache[this.name] = true;
+ return true;
+ });
+ },
+
+ clean: function( selector ) {
+ return $( selector )[0];
+ },
+
+ errors: function() {
+ return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
+ },
+
+ reset: function() {
+ this.successList = [];
+ this.errorList = [];
+ this.errorMap = {};
+ this.toShow = $([]);
+ this.toHide = $([]);
+ this.currentElements = $([]);
+ },
+
+ prepareForm: function() {
+ this.reset();
+ this.toHide = this.errors().add( this.containers );
+ },
+
+ prepareElement: function( element ) {
+ this.reset();
+ this.toHide = this.errorsFor(element);
+ },
+
+ check: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+
+ var rules = $(element).rules();
+ var dependencyMismatch = false;
+ for (var method in rules ) {
+ var rule = { method: method, parameters: rules[method] };
+ try {
+ var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
+
+ // if a method indicates that the field is optional and therefore valid,
+ // don't mark it as valid when there are no other rules
+ if ( result == "dependency-mismatch" ) {
+ dependencyMismatch = true;
+ continue;
+ }
+ dependencyMismatch = false;
+
+ if ( result == "pending" ) {
+ this.toHide = this.toHide.not( this.errorsFor(element) );
+ return;
+ }
+
+ if( !result ) {
+ this.formatAndAdd( element, rule );
+ return false;
+ }
+ } catch(e) {
+ this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
+ + ", check the '" + rule.method + "' method", e);
+ throw e;
+ }
+ }
+ if (dependencyMismatch)
+ return;
+ if ( this.objectLength(rules) )
+ this.successList.push(element);
+ return true;
+ },
+
+ // return the custom message for the given element and validation method
+ // specified in the element's "messages" metadata
+ customMetaMessage: function(element, method) {
+ if (!$.metadata)
+ return;
+
+ var meta = this.settings.meta
+ ? $(element).metadata()[this.settings.meta]
+ : $(element).metadata();
+
+ return meta && meta.messages && meta.messages[method];
+ },
+
+ // return the custom message for the given element name and validation method
+ customMessage: function( name, method ) {
+ var m = this.settings.messages[name];
+ return m && (m.constructor == String
+ ? m
+ : m[method]);
+ },
+
+ // return the first defined argument, allowing empty strings
+ findDefined: function() {
+ for(var i = 0; i < arguments.length; i++) {
+ if (arguments[i] !== undefined)
+ return arguments[i];
+ }
+ return undefined;
+ },
+
+ defaultMessage: function( element, method) {
+ return this.findDefined(
+ this.customMessage( element.name, method ),
+ this.customMetaMessage( element, method ),
+ // title is never undefined, so handle empty string as undefined
+ !this.settings.ignoreTitle && element.title || undefined,
+ $.validator.messages[method],
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
+ );
+ },
+
+ formatAndAdd: function( element, rule ) {
+ var message = this.defaultMessage( element, rule.method ),
+ theregex = /\$?\{(\d+)\}/g;
+ if ( typeof message == "function" ) {
+ message = message.call(this, rule.parameters, element);
+ } else if (theregex.test(message)) {
+ message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
+ }
+ this.errorList.push({
+ message: message,
+ element: element
+ });
+
+ this.errorMap[element.name] = message;
+ this.submitted[element.name] = message;
+ },
+
+ addWrapper: function(toToggle) {
+ if ( this.settings.wrapper )
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
+ return toToggle;
+ },
+
+ defaultShowErrors: function() {
+ for ( var i = 0; this.errorList[i]; i++ ) {
+ var error = this.errorList[i];
+ this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
+ this.showLabel( error.element, error.message );
+ }
+ if( this.errorList.length ) {
+ this.toShow = this.toShow.add( this.containers );
+ }
+ if (this.settings.success) {
+ for ( var i = 0; this.successList[i]; i++ ) {
+ this.showLabel( this.successList[i] );
+ }
+ }
+ if (this.settings.unhighlight) {
+ for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
+ this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
+ }
+ }
+ this.toHide = this.toHide.not( this.toShow );
+ this.hideErrors();
+ this.addWrapper( this.toShow ).show();
+ },
+
+ validElements: function() {
+ return this.currentElements.not(this.invalidElements());
+ },
+
+ invalidElements: function() {
+ return $(this.errorList).map(function() {
+ return this.element;
+ });
+ },
+
+ showLabel: function(element, message) {
+ var label = this.errorsFor( element );
+ if ( label.length ) {
+ // refresh error/success class
+ label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
+
+ // check if we have a generated label, replace the message then
+ label.attr("generated") && label.html(message);
+ } else {
+ // create label
+ label = $("<" + this.settings.errorElement + "/>")
+ .attr({"for": this.idOrName(element), generated: true})
+ .addClass(this.settings.errorClass)
+ .html(message || "");
+ if ( this.settings.wrapper ) {
+ // make sure the element is visible, even in IE
+ // actually showing the wrapped element is handled elsewhere
+ label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
+ }
+ if ( !this.labelContainer.append(label).length )
+ this.settings.errorPlacement
+ ? this.settings.errorPlacement(label, $(element) )
+ : label.insertAfter(element);
+ }
+ if ( !message && this.settings.success ) {
+ label.text("");
+ typeof this.settings.success == "string"
+ ? label.addClass( this.settings.success )
+ : this.settings.success( label );
+ }
+ this.toShow = this.toShow.add(label);
+ },
+
+ errorsFor: function(element) {
+ var name = this.idOrName(element);
+ return this.errors().filter(function() {
+ return $(this).attr('for') == name;
+ });
+ },
+
+ idOrName: function(element) {
+ return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
+ },
+
+ validationTargetFor: function(element) {
+ // if radio/checkbox, validate first element in group instead
+ if (this.checkable(element)) {
+ element = this.findByName( element.name ).not(this.settings.ignore)[0];
+ }
+ return element;
+ },
+
+ checkable: function( element ) {
+ return /radio|checkbox/i.test(element.type);
+ },
+
+ findByName: function( name ) {
+ // select by name and filter by form for performance over form.find("[name=...]")
+ var form = this.currentForm;
+ return $(document.getElementsByName(name)).map(function(index, element) {
+ return element.form == form && element.name == name && element || null;
+ });
+ },
+
+ getLength: function(value, element) {
+ switch( element.nodeName.toLowerCase() ) {
+ case 'select':
+ return $("option:selected", element).length;
+ case 'input':
+ if( this.checkable( element) )
+ return this.findByName(element.name).filter(':checked').length;
+ }
+ return value.length;
+ },
+
+ depend: function(param, element) {
+ return this.dependTypes[typeof param]
+ ? this.dependTypes[typeof param](param, element)
+ : true;
+ },
+
+ dependTypes: {
+ "boolean": function(param, element) {
+ return param;
+ },
+ "string": function(param, element) {
+ return !!$(param, element.form).length;
+ },
+ "function": function(param, element) {
+ return param(element);
+ }
+ },
+
+ optional: function(element) {
+ return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
+ },
+
+ startRequest: function(element) {
+ if (!this.pending[element.name]) {
+ this.pendingRequest++;
+ this.pending[element.name] = true;
+ }
+ },
+
+ stopRequest: function(element, valid) {
+ this.pendingRequest--;
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
+ if (this.pendingRequest < 0)
+ this.pendingRequest = 0;
+ delete this.pending[element.name];
+ if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
+ $(this.currentForm).submit();
+ this.formSubmitted = false;
+ } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ this.formSubmitted = false;
+ }
+ },
+
+ previousValue: function(element) {
+ return $.data(element, "previousValue") || $.data(element, "previousValue", {
+ old: null,
+ valid: true,
+ message: this.defaultMessage( element, "remote" )
+ });
+ }
+
+ },
+
+ classRuleSettings: {
+ required: {required: true},
+ email: {email: true},
+ url: {url: true},
+ date: {date: true},
+ dateISO: {dateISO: true},
+ dateDE: {dateDE: true},
+ number: {number: true},
+ numberDE: {numberDE: true},
+ digits: {digits: true},
+ creditcard: {creditcard: true}
+ },
+
+ addClassRules: function(className, rules) {
+ className.constructor == String ?
+ this.classRuleSettings[className] = rules :
+ $.extend(this.classRuleSettings, className);
+ },
+
+ classRules: function(element) {
+ var rules = {};
+ var classes = $(element).attr('class');
+ classes && $.each(classes.split(' '), function() {
+ if (this in $.validator.classRuleSettings) {
+ $.extend(rules, $.validator.classRuleSettings[this]);
+ }
+ });
+ return rules;
+ },
+
+ attributeRules: function(element) {
+ var rules = {};
+ var $element = $(element);
+
+ for (var method in $.validator.methods) {
+ var value;
+ // If .prop exists (jQuery >= 1.6), use it to get true/false for required
+ if (method === 'required' && typeof $.fn.prop === 'function') {
+ value = $element.prop(method);
+ } else {
+ value = $element.attr(method);
+ }
+ if (value) {
+ rules[method] = value;
+ } else if ($element[0].getAttribute("type") === method) {
+ rules[method] = true;
+ }
+ }
+
+ // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
+ if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
+ delete rules.maxlength;
+ }
+
+ return rules;
+ },
+
+ metadataRules: function(element) {
+ if (!$.metadata) return {};
+
+ var meta = $.data(element.form, 'validator').settings.meta;
+ return meta ?
+ $(element).metadata()[meta] :
+ $(element).metadata();
+ },
+
+ staticRules: function(element) {
+ var rules = {};
+ var validator = $.data(element.form, 'validator');
+ if (validator.settings.rules) {
+ rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
+ }
+ return rules;
+ },
+
+ normalizeRules: function(rules, element) {
+ // handle dependency check
+ $.each(rules, function(prop, val) {
+ // ignore rule when param is explicitly false, eg. required:false
+ if (val === false) {
+ delete rules[prop];
+ return;
+ }
+ if (val.param || val.depends) {
+ var keepRule = true;
+ switch (typeof val.depends) {
+ case "string":
+ keepRule = !!$(val.depends, element.form).length;
+ break;
+ case "function":
+ keepRule = val.depends.call(element, element);
+ break;
+ }
+ if (keepRule) {
+ rules[prop] = val.param !== undefined ? val.param : true;
+ } else {
+ delete rules[prop];
+ }
+ }
+ });
+
+ // evaluate parameters
+ $.each(rules, function(rule, parameter) {
+ rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
+ });
+
+ // clean number parameters
+ $.each(['minlength', 'maxlength', 'min', 'max'], function() {
+ if (rules[this]) {
+ rules[this] = Number(rules[this]);
+ }
+ });
+ $.each(['rangelength', 'range'], function() {
+ if (rules[this]) {
+ rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
+ }
+ });
+
+ if ($.validator.autoCreateRanges) {
+ // auto-create ranges
+ if (rules.min && rules.max) {
+ rules.range = [rules.min, rules.max];
+ delete rules.min;
+ delete rules.max;
+ }
+ if (rules.minlength && rules.maxlength) {
+ rules.rangelength = [rules.minlength, rules.maxlength];
+ delete rules.minlength;
+ delete rules.maxlength;
+ }
+ }
+
+ // To support custom messages in metadata ignore rule methods titled "messages"
+ if (rules.messages) {
+ delete rules.messages;
+ }
+
+ return rules;
+ },
+
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
+ normalizeRule: function(data) {
+ if( typeof data == "string" ) {
+ var transformed = {};
+ $.each(data.split(/\s/), function() {
+ transformed[this] = true;
+ });
+ data = transformed;
+ }
+ return data;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
+ addMethod: function(name, method, message) {
+ $.validator.methods[name] = method;
+ $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
+ if (method.length < 3) {
+ $.validator.addClassRules(name, $.validator.normalizeRule(name));
+ }
+ },
+
+ methods: {
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/required
+ required: function(value, element, param) {
+ // check if dependency is met
+ if ( !this.depend(param, element) )
+ return "dependency-mismatch";
+ switch( element.nodeName.toLowerCase() ) {
+ case 'select':
+ // could be an array for select-multiple or a string, both are fine this way
+ var val = $(element).val();
+ return val && val.length > 0;
+ case 'input':
+ if ( this.checkable(element) )
+ return this.getLength(value, element) > 0;
+ default:
+ return $.trim(value).length > 0;
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/remote
+ remote: function(value, element, param) {
+ if ( this.optional(element) )
+ return "dependency-mismatch";
+
+ var previous = this.previousValue(element);
+ if (!this.settings.messages[element.name] )
+ this.settings.messages[element.name] = {};
+ previous.originalMessage = this.settings.messages[element.name].remote;
+ this.settings.messages[element.name].remote = previous.message;
+
+ param = typeof param == "string" && {url:param} || param;
+
+ if ( this.pending[element.name] ) {
+ return "pending";
+ }
+ if ( previous.old === value ) {
+ return previous.valid;
+ }
+
+ previous.old = value;
+ var validator = this;
+ this.startRequest(element);
+ var data = {};
+ data[element.name] = value;
+ $.ajax($.extend(true, {
+ url: param,
+ mode: "abort",
+ port: "validate" + element.name,
+ dataType: "json",
+ data: data,
+ success: function(response) {
+ validator.settings.messages[element.name].remote = previous.originalMessage;
+ var valid = response === true;
+ if ( valid ) {
+ var submitted = validator.formSubmitted;
+ validator.prepareElement(element);
+ validator.formSubmitted = submitted;
+ validator.successList.push(element);
+ validator.showErrors();
+ } else {
+ var errors = {};
+ var message = response || validator.defaultMessage( element, "remote" );
+ errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
+ validator.showErrors(errors);
+ }
+ previous.valid = valid;
+ validator.stopRequest(element, valid);
+ }
+ }, param));
+ return "pending";
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/minlength
+ minlength: function(value, element, param) {
+ return this.optional(element) || this.getLength($.trim(value), element) >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
+ maxlength: function(value, element, param) {
+ return this.optional(element) || this.getLength($.trim(value), element) <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
+ rangelength: function(value, element, param) {
+ var length = this.getLength($.trim(value), element);
+ return this.optional(element) || ( length >= param[0] && length <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/min
+ min: function( value, element, param ) {
+ return this.optional(element) || value >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/max
+ max: function( value, element, param ) {
+ return this.optional(element) || value <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/range
+ range: function( value, element, param ) {
+ return this.optional(element) || ( value >= param[0] && value <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/email
+ email: function(value, element) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
+ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/url
+ url: function(value, element) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
+ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/date
+ date: function(value, element) {
+ return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
+ dateISO: function(value, element) {
+ return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/number
+ number: function(value, element) {
+ return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/digits
+ digits: function(value, element) {
+ return this.optional(element) || /^\d+$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
+ // based on http://en.wikipedia.org/wiki/Luhn
+ creditcard: function(value, element) {
+ if ( this.optional(element) )
+ return "dependency-mismatch";
+ // accept only spaces, digits and dashes
+ if (/[^0-9 -]+/.test(value))
+ return false;
+ var nCheck = 0,
+ nDigit = 0,
+ bEven = false;
+
+ value = value.replace(/\D/g, "");
+
+ for (var n = value.length - 1; n >= 0; n--) {
+ var cDigit = value.charAt(n);
+ var nDigit = parseInt(cDigit, 10);
+ if (bEven) {
+ if ((nDigit *= 2) > 9)
+ nDigit -= 9;
+ }
+ nCheck += nDigit;
+ bEven = !bEven;
+ }
+
+ return (nCheck % 10) == 0;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/accept
+ accept: function(value, element, param) {
+ param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
+ equalTo: function(value, element, param) {
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
+ var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
+ $(element).valid();
+ });
+ return value == target.val();
+ }
+
+ }
+
+});
+
+// deprecated, use $.validator.format instead
+$.format = $.validator.format;
+
+})(jQuery);
+
+// ajax mode: abort
+// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
+// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
+;(function($) {
+ var pendingRequests = {};
+ // Use a prefilter if available (1.5+)
+ if ( $.ajaxPrefilter ) {
+ $.ajaxPrefilter(function(settings, _, xhr) {
+ var port = settings.port;
+ if (settings.mode == "abort") {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = xhr;
+ }
+ });
+ } else {
+ // Proxy ajax
+ var ajax = $.ajax;
+ $.ajax = function(settings) {
+ var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
+ port = ( "port" in settings ? settings : $.ajaxSettings ).port;
+ if (mode == "abort") {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ return (pendingRequests[port] = ajax.apply(this, arguments));
+ }
+ return ajax.apply(this, arguments);
+ };
+ }
+})(jQuery);
+
+// provides cross-browser focusin and focusout events
+// IE has native support, in other browsers, use event caputuring (neither bubbles)
+
+// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
+// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
+;(function($) {
+ // only implement if not provided by jQuery core (since 1.4)
+ // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
+ if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
+ $.each({
+ focus: 'focusin',
+ blur: 'focusout'
+ }, function( original, fix ){
+ $.event.special[fix] = {
+ setup:function() {
+ this.addEventListener( original, handler, true );
+ },
+ teardown:function() {
+ this.removeEventListener( original, handler, true );
+ },
+ handler: function(e) {
+ arguments[0] = $.event.fix(e);
+ arguments[0].type = fix;
+ return $.event.handle.apply(this, arguments);
+ }
+ };
+ function handler(e) {
+ e = $.event.fix(e);
+ e.type = fix;
+ return $.event.handle.call(this, e);
+ }
+ });
+ };
+ $.extend($.fn, {
+ validateDelegate: function(delegate, type, handler) {
+ return this.bind(type, function(event) {
+ var target = $(event.target);
+ if (target.is(delegate)) {
+ return handler.apply(target, arguments);
+ }
+ });
+ }
+ });
+})(jQuery);
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jqueryFileTree-1.0.1.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jqueryFileTree-1.0.1.js
new file mode 100755
index 000000000..289b8e329
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/jqueryFileTree-1.0.1.js
@@ -0,0 +1,102 @@
+// jQuery File Tree Plugin
+//
+// Version 1.01
+//
+// Cory S.N. LaViska
+// A Beautiful Site (http://abeautifulsite.net/)
+// 24 March 2008
+//
+// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
+//
+// Usage: $('.fileTreeDemo').fileTree( options, callback )
+//
+// Options: root - root folder to display; default = /
+// script - location of the serverside AJAX file to use; default = jqueryFileTree.php
+// folderEvent - event to trigger expand/collapse; default = click
+// expandSpeed - default = 500 (ms); use -1 for no animation
+// collapseSpeed - default = 500 (ms); use -1 for no animation
+// expandEasing - easing function to use on expand (optional)
+// collapseEasing - easing function to use on collapse (optional)
+// multiFolder - whether or not to limit the browser to one subfolder at a time
+// loadMessage - Message to display while initial tree loads (can be HTML)
+//
+// History:
+//
+// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
+// 1.00 - released (24 March 2008)
+//
+// TERMS OF USE
+//
+// This plugin is dual-licensed under the GNU General Public License and the MIT License and
+// is copyright 2008 A Beautiful Site, LLC.
+//
+if(jQuery) (function($){
+
+ $.extend($.fn, {
+ fileTree: function(o, h) {
+ // Defaults
+ if( !o ) var o = {};
+ if( o.root == undefined ) o.root = '/';
+ if( o.script == undefined ) o.script = 'jqueryFileTree.php';
+ if( o.folderEvent == undefined ) o.folderEvent = 'click';
+ if( o.expandSpeed == undefined ) o.expandSpeed= 500;
+ if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
+ if( o.expandEasing == undefined ) o.expandEasing = null;
+ if( o.collapseEasing == undefined ) o.collapseEasing = null;
+ if( o.multiFolder == undefined ) o.multiFolder = true;
+ if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
+
+ $(this).each( function() {
+
+ function showTree(c, t) {
+ $(c).addClass('wait');
+ $(".jqueryFileTree.start").remove();
+ $.get(o.script, { p: t }, function(data) {
+ $(c).find('.start').html('');
+ var artifactContentEntries=mapArtifactContentEntries(data);
+ $(artifactContentEntries ).each(function(idx, elem){
+ elem.text=elem.path.substr( t.length, elem.path.length);
+ });
+ var htmlContent = $("#artifact_content_tree_partial" ).tmpl(
+ {artifactContentEntries:artifactContentEntries}
+ );
+ $(c).removeClass('wait').append(htmlContent);
+ if( o.root == t ) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
+ bindTree(c);
+ });
+ }
+
+ function bindTree(t) {
+ $(t).find('LI A').bind(o.folderEvent, function() {
+ if( $(this).parent().hasClass('directory') ) {
+ if( $(this).parent().hasClass('collapsed') ) {
+ // Expand
+ if( !o.multiFolder ) {
+ $(this).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
+ $(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
+ }
+ $(this).parent().find('UL').remove(); // cleanup
+ showTree( $(this).parent(), escape($(this).attr('rel')) );//.match( /.*\// )
+ $(this).parent().removeClass('collapsed').addClass('expanded');
+ } else {
+ // Collapse
+ $(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
+ $(this).parent().removeClass('expanded').addClass('collapsed');
+ }
+ } else {
+ h($(this).attr('rel'));
+ }
+ return false;
+ });
+ // Prevent A from triggering the # on non-click events
+ if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
+ }
+ // Loading message
+ $(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
+ // Get the initial file list
+ showTree( $(this), escape(o.root) );
+ });
+ }
+ });
+
+})(jQuery); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-2.2.0.debug.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-2.2.0.debug.js
new file mode 100644
index 000000000..61c2a0e22
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-2.2.0.debug.js
@@ -0,0 +1,3577 @@
+// Knockout JavaScript library v2.2.0
+// (c) Steven Sanderson - http://knockoutjs.com/
+// License: MIT (http://www.opensource.org/licenses/mit-license.php)
+
+(function(){
+var DEBUG=true;
+(function(window,document,navigator,jQuery,undefined){
+!function(factory) {
+ // Support three module loading scenarios
+ if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
+ // [1] CommonJS/Node.js
+ var target = module['exports'] || exports; // module.exports is for Node.js
+ factory(target);
+ } else if (typeof define === 'function' && define['amd']) {
+ // [2] AMD anonymous module
+ define(['exports'], factory);
+ } else {
+ // [3] No module loader (plain <script> tag) - put directly in global namespace
+ factory(window['ko'] = {});
+ }
+}(function(koExports){
+// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
+// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
+var ko = typeof koExports !== 'undefined' ? koExports : {};
+// Google Closure Compiler helpers (used only to make the minified file smaller)
+ko.exportSymbol = function(koPath, object) {
+ var tokens = koPath.split(".");
+
+ // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
+ // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
+ var target = ko;
+
+ for (var i = 0; i < tokens.length - 1; i++)
+ target = target[tokens[i]];
+ target[tokens[tokens.length - 1]] = object;
+};
+ko.exportProperty = function(owner, publicName, object) {
+ owner[publicName] = object;
+};
+ko.version = "2.2.0";
+
+ko.exportSymbol('version', ko.version);
+ko.utils = new (function () {
+ var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
+
+ // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
+ var knownEvents = {}, knownEventTypesByEventName = {};
+ var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
+ knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
+ knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
+ for (var eventType in knownEvents) {
+ var knownEventsForType = knownEvents[eventType];
+ if (knownEventsForType.length) {
+ for (var i = 0, j = knownEventsForType.length; i < j; i++)
+ knownEventTypesByEventName[knownEventsForType[i]] = eventType;
+ }
+ }
+ var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
+
+ // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
+ // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
+ // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
+ // If there is a future need to detect specific versions of IE10+, we will amend this.
+ var ieVersion = (function() {
+ var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
+
+ // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
+ while (
+ div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
+ iElems[0]
+ );
+ return version > 4 ? version : undefined;
+ }());
+ var isIe6 = ieVersion === 6,
+ isIe7 = ieVersion === 7;
+
+ function isClickOnCheckableElement(element, eventType) {
+ if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
+ if (eventType.toLowerCase() != "click") return false;
+ var inputType = element.type;
+ return (inputType == "checkbox") || (inputType == "radio");
+ }
+
+ return {
+ fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
+
+ arrayForEach: function (array, action) {
+ for (var i = 0, j = array.length; i < j; i++)
+ action(array[i]);
+ },
+
+ arrayIndexOf: function (array, item) {
+ if (typeof Array.prototype.indexOf == "function")
+ return Array.prototype.indexOf.call(array, item);
+ for (var i = 0, j = array.length; i < j; i++)
+ if (array[i] === item)
+ return i;
+ return -1;
+ },
+
+ arrayFirst: function (array, predicate, predicateOwner) {
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate.call(predicateOwner, array[i]))
+ return array[i];
+ return null;
+ },
+
+ arrayRemoveItem: function (array, itemToRemove) {
+ var index = ko.utils.arrayIndexOf(array, itemToRemove);
+ if (index >= 0)
+ array.splice(index, 1);
+ },
+
+ arrayGetDistinctValues: function (array) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++) {
+ if (ko.utils.arrayIndexOf(result, array[i]) < 0)
+ result.push(array[i]);
+ }
+ return result;
+ },
+
+ arrayMap: function (array, mapping) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ result.push(mapping(array[i]));
+ return result;
+ },
+
+ arrayFilter: function (array, predicate) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate(array[i]))
+ result.push(array[i]);
+ return result;
+ },
+
+ arrayPushAll: function (array, valuesToPush) {
+ if (valuesToPush instanceof Array)
+ array.push.apply(array, valuesToPush);
+ else
+ for (var i = 0, j = valuesToPush.length; i < j; i++)
+ array.push(valuesToPush[i]);
+ return array;
+ },
+
+ extend: function (target, source) {
+ if (source) {
+ for(var prop in source) {
+ if(source.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ }
+ }
+ }
+ return target;
+ },
+
+ emptyDomNode: function (domNode) {
+ while (domNode.firstChild) {
+ ko.removeNode(domNode.firstChild);
+ }
+ },
+
+ moveCleanedNodesToContainerElement: function(nodes) {
+ // Ensure it's a real array, as we're about to reparent the nodes and
+ // we don't want the underlying collection to change while we're doing that.
+ var nodesArray = ko.utils.makeArray(nodes);
+
+ var container = document.createElement('div');
+ for (var i = 0, j = nodesArray.length; i < j; i++) {
+ container.appendChild(ko.cleanNode(nodesArray[i]));
+ }
+ return container;
+ },
+
+ cloneNodes: function (nodesArray, shouldCleanNodes) {
+ for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
+ var clonedNode = nodesArray[i].cloneNode(true);
+ newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
+ }
+ return newNodesArray;
+ },
+
+ setDomNodeChildren: function (domNode, childNodes) {
+ ko.utils.emptyDomNode(domNode);
+ if (childNodes) {
+ for (var i = 0, j = childNodes.length; i < j; i++)
+ domNode.appendChild(childNodes[i]);
+ }
+ },
+
+ replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
+ var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
+ if (nodesToReplaceArray.length > 0) {
+ var insertionPoint = nodesToReplaceArray[0];
+ var parent = insertionPoint.parentNode;
+ for (var i = 0, j = newNodesArray.length; i < j; i++)
+ parent.insertBefore(newNodesArray[i], insertionPoint);
+ for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
+ ko.removeNode(nodesToReplaceArray[i]);
+ }
+ }
+ },
+
+ setOptionNodeSelectionState: function (optionNode, isSelected) {
+ // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
+ if (ieVersion < 7)
+ optionNode.setAttribute("selected", isSelected);
+ else
+ optionNode.selected = isSelected;
+ },
+
+ stringTrim: function (string) {
+ return (string || "").replace(stringTrimRegex, "");
+ },
+
+ stringTokenize: function (string, delimiter) {
+ var result = [];
+ var tokens = (string || "").split(delimiter);
+ for (var i = 0, j = tokens.length; i < j; i++) {
+ var trimmed = ko.utils.stringTrim(tokens[i]);
+ if (trimmed !== "")
+ result.push(trimmed);
+ }
+ return result;
+ },
+
+ stringStartsWith: function (string, startsWith) {
+ string = string || "";
+ if (startsWith.length > string.length)
+ return false;
+ return string.substring(0, startsWith.length) === startsWith;
+ },
+
+ domNodeIsContainedBy: function (node, containedByNode) {
+ if (containedByNode.compareDocumentPosition)
+ return (containedByNode.compareDocumentPosition(node) & 16) == 16;
+ while (node != null) {
+ if (node == containedByNode)
+ return true;
+ node = node.parentNode;
+ }
+ return false;
+ },
+
+ domNodeIsAttachedToDocument: function (node) {
+ return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
+ },
+
+ tagNameLower: function(element) {
+ // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
+ // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
+ // we don't need to do the .toLowerCase() as it will always be lower case anyway.
+ return element && element.tagName && element.tagName.toLowerCase();
+ },
+
+ registerEventHandler: function (element, eventType, handler) {
+ var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
+ if (!mustUseAttachEvent && typeof jQuery != "undefined") {
+ if (isClickOnCheckableElement(element, eventType)) {
+ // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
+ // it toggles the element checked state *after* the click event handlers run, whereas native
+ // click events toggle the checked state *before* the event handler.
+ // Fix this by intecepting the handler and applying the correct checkedness before it runs.
+ var originalHandler = handler;
+ handler = function(event, eventData) {
+ var jQuerySuppliedCheckedState = this.checked;
+ if (eventData)
+ this.checked = eventData.checkedStateBeforeEvent !== true;
+ originalHandler.call(this, event);
+ this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
+ };
+ }
+ jQuery(element)['bind'](eventType, handler);
+ } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
+ element.addEventListener(eventType, handler, false);
+ else if (typeof element.attachEvent != "undefined")
+ element.attachEvent("on" + eventType, function (event) {
+ handler.call(element, event);
+ });
+ else
+ throw new Error("Browser doesn't support addEventListener or attachEvent");
+ },
+
+ triggerEvent: function (element, eventType) {
+ if (!(element && element.nodeType))
+ throw new Error("element must be a DOM node when calling triggerEvent");
+
+ if (typeof jQuery != "undefined") {
+ var eventData = [];
+ if (isClickOnCheckableElement(element, eventType)) {
+ // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
+ eventData.push({ checkedStateBeforeEvent: element.checked });
+ }
+ jQuery(element)['trigger'](eventType, eventData);
+ } else if (typeof document.createEvent == "function") {
+ if (typeof element.dispatchEvent == "function") {
+ var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
+ var event = document.createEvent(eventCategory);
+ event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
+ element.dispatchEvent(event);
+ }
+ else
+ throw new Error("The supplied element doesn't support dispatchEvent");
+ } else if (typeof element.fireEvent != "undefined") {
+ // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
+ // so to make it consistent, we'll do it manually here
+ if (isClickOnCheckableElement(element, eventType))
+ element.checked = element.checked !== true;
+ element.fireEvent("on" + eventType);
+ }
+ else
+ throw new Error("Browser doesn't support triggering events");
+ },
+
+ unwrapObservable: function (value) {
+ return ko.isObservable(value) ? value() : value;
+ },
+
+ peekObservable: function (value) {
+ return ko.isObservable(value) ? value.peek() : value;
+ },
+
+ toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
+ if (classNames) {
+ var cssClassNameRegex = /[\w-]+/g,
+ currentClassNames = node.className.match(cssClassNameRegex) || [];
+ ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
+ var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
+ if (indexOfClass >= 0) {
+ if (!shouldHaveClass)
+ currentClassNames.splice(indexOfClass, 1);
+ } else {
+ if (shouldHaveClass)
+ currentClassNames.push(className);
+ }
+ });
+ node.className = currentClassNames.join(" ");
+ }
+ },
+
+ setTextContent: function(element, textContent) {
+ var value = ko.utils.unwrapObservable(textContent);
+ if ((value === null) || (value === undefined))
+ value = "";
+
+ if (element.nodeType === 3) {
+ element.data = value;
+ } else {
+ // We need there to be exactly one child: a text node.
+ // If there are no children, more than one, or if it's not a text node,
+ // we'll clear everything and create a single text node.
+ var innerTextNode = ko.virtualElements.firstChild(element);
+ if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
+ ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
+ } else {
+ innerTextNode.data = value;
+ }
+
+ ko.utils.forceRefresh(element);
+ }
+ },
+
+ setElementName: function(element, name) {
+ element.name = name;
+
+ // Workaround IE 6/7 issue
+ // - https://github.com/SteveSanderson/knockout/issues/197
+ // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
+ if (ieVersion <= 7) {
+ try {
+ element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
+ }
+ catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
+ }
+ },
+
+ forceRefresh: function(node) {
+ // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
+ if (ieVersion >= 9) {
+ // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
+ var elem = node.nodeType == 1 ? node : node.parentNode;
+ if (elem.style)
+ elem.style.zoom = elem.style.zoom;
+ }
+ },
+
+ ensureSelectElementIsRenderedCorrectly: function(selectElement) {
+ // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
+ // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
+ if (ieVersion >= 9) {
+ var originalWidth = selectElement.style.width;
+ selectElement.style.width = 0;
+ selectElement.style.width = originalWidth;
+ }
+ },
+
+ range: function (min, max) {
+ min = ko.utils.unwrapObservable(min);
+ max = ko.utils.unwrapObservable(max);
+ var result = [];
+ for (var i = min; i <= max; i++)
+ result.push(i);
+ return result;
+ },
+
+ makeArray: function(arrayLikeObject) {
+ var result = [];
+ for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
+ result.push(arrayLikeObject[i]);
+ };
+ return result;
+ },
+
+ isIe6 : isIe6,
+ isIe7 : isIe7,
+ ieVersion : ieVersion,
+
+ getFormFields: function(form, fieldName) {
+ var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
+ var isMatchingField = (typeof fieldName == 'string')
+ ? function(field) { return field.name === fieldName }
+ : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
+ var matches = [];
+ for (var i = fields.length - 1; i >= 0; i--) {
+ if (isMatchingField(fields[i]))
+ matches.push(fields[i]);
+ };
+ return matches;
+ },
+
+ parseJson: function (jsonString) {
+ if (typeof jsonString == "string") {
+ jsonString = ko.utils.stringTrim(jsonString);
+ if (jsonString) {
+ if (window.JSON && window.JSON.parse) // Use native parsing where available
+ return window.JSON.parse(jsonString);
+ return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
+ }
+ }
+ return null;
+ },
+
+ stringifyJson: function (data, replacer, space) { // replacer and space are optional
+ if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
+ throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
+ return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
+ },
+
+ postJson: function (urlOrForm, data, options) {
+ options = options || {};
+ var params = options['params'] || {};
+ var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
+ var url = urlOrForm;
+
+ // If we were given a form, use its 'action' URL and pick out any requested field values
+ if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
+ var originalForm = urlOrForm;
+ url = originalForm.action;
+ for (var i = includeFields.length - 1; i >= 0; i--) {
+ var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
+ for (var j = fields.length - 1; j >= 0; j--)
+ params[fields[j].name] = fields[j].value;
+ }
+ }
+
+ data = ko.utils.unwrapObservable(data);
+ var form = document.createElement("form");
+ form.style.display = "none";
+ form.action = url;
+ form.method = "post";
+ for (var key in data) {
+ var input = document.createElement("input");
+ input.name = key;
+ input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
+ form.appendChild(input);
+ }
+ for (var key in params) {
+ var input = document.createElement("input");
+ input.name = key;
+ input.value = params[key];
+ form.appendChild(input);
+ }
+ document.body.appendChild(form);
+ options['submitter'] ? options['submitter'](form) : form.submit();
+ setTimeout(function () { form.parentNode.removeChild(form); }, 0);
+ }
+ }
+})();
+
+ko.exportSymbol('utils', ko.utils);
+ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
+ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
+ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
+ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
+ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
+ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
+ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
+ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
+ko.exportSymbol('utils.extend', ko.utils.extend);
+ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
+ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
+ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
+ko.exportSymbol('utils.postJson', ko.utils.postJson);
+ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
+ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
+ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
+ko.exportSymbol('utils.range', ko.utils.range);
+ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
+ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
+ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
+
+if (!Function.prototype['bind']) {
+ // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
+ // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
+ Function.prototype['bind'] = function (object) {
+ var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
+ return function () {
+ return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
+ };
+ };
+}
+
+ko.utils.domData = new (function () {
+ var uniqueId = 0;
+ var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
+ var dataStore = {};
+ return {
+ get: function (node, key) {
+ var allDataForNode = ko.utils.domData.getAll(node, false);
+ return allDataForNode === undefined ? undefined : allDataForNode[key];
+ },
+ set: function (node, key, value) {
+ if (value === undefined) {
+ // Make sure we don't actually create a new domData key if we are actually deleting a value
+ if (ko.utils.domData.getAll(node, false) === undefined)
+ return;
+ }
+ var allDataForNode = ko.utils.domData.getAll(node, true);
+ allDataForNode[key] = value;
+ },
+ getAll: function (node, createIfNotFound) {
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
+ var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
+ if (!hasExistingDataStore) {
+ if (!createIfNotFound)
+ return undefined;
+ dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
+ dataStore[dataStoreKey] = {};
+ }
+ return dataStore[dataStoreKey];
+ },
+ clear: function (node) {
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
+ if (dataStoreKey) {
+ delete dataStore[dataStoreKey];
+ node[dataStoreKeyExpandoPropertyName] = null;
+ return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
+ }
+ return false;
+ }
+ }
+})();
+
+ko.exportSymbol('utils.domData', ko.utils.domData);
+ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
+
+ko.utils.domNodeDisposal = new (function () {
+ var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
+ var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
+ var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
+
+ function getDisposeCallbacksCollection(node, createIfNotFound) {
+ var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
+ if ((allDisposeCallbacks === undefined) && createIfNotFound) {
+ allDisposeCallbacks = [];
+ ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
+ }
+ return allDisposeCallbacks;
+ }
+ function destroyCallbacksCollection(node) {
+ ko.utils.domData.set(node, domDataKey, undefined);
+ }
+
+ function cleanSingleNode(node) {
+ // Run all the dispose callbacks
+ var callbacks = getDisposeCallbacksCollection(node, false);
+ if (callbacks) {
+ callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
+ for (var i = 0; i < callbacks.length; i++)
+ callbacks[i](node);
+ }
+
+ // Also erase the DOM data
+ ko.utils.domData.clear(node);
+
+ // Special support for jQuery here because it's so commonly used.
+ // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
+ // so notify it to tear down any resources associated with the node & descendants here.
+ if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
+ jQuery['cleanData']([node]);
+
+ // Also clear any immediate-child comment nodes, as these wouldn't have been found by
+ // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
+ if (cleanableNodeTypesWithDescendants[node.nodeType])
+ cleanImmediateCommentTypeChildren(node);
+ }
+
+ function cleanImmediateCommentTypeChildren(nodeWithChildren) {
+ var child, nextChild = nodeWithChildren.firstChild;
+ while (child = nextChild) {
+ nextChild = child.nextSibling;
+ if (child.nodeType === 8)
+ cleanSingleNode(child);
+ }
+ }
+
+ return {
+ addDisposeCallback : function(node, callback) {
+ if (typeof callback != "function")
+ throw new Error("Callback must be a function");
+ getDisposeCallbacksCollection(node, true).push(callback);
+ },
+
+ removeDisposeCallback : function(node, callback) {
+ var callbacksCollection = getDisposeCallbacksCollection(node, false);
+ if (callbacksCollection) {
+ ko.utils.arrayRemoveItem(callbacksCollection, callback);
+ if (callbacksCollection.length == 0)
+ destroyCallbacksCollection(node);
+ }
+ },
+
+ cleanNode : function(node) {
+ // First clean this node, where applicable
+ if (cleanableNodeTypes[node.nodeType]) {
+ cleanSingleNode(node);
+
+ // ... then its descendants, where applicable
+ if (cleanableNodeTypesWithDescendants[node.nodeType]) {
+ // Clone the descendants list in case it changes during iteration
+ var descendants = [];
+ ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
+ for (var i = 0, j = descendants.length; i < j; i++)
+ cleanSingleNode(descendants[i]);
+ }
+ }
+ return node;
+ },
+
+ removeNode : function(node) {
+ ko.cleanNode(node);
+ if (node.parentNode)
+ node.parentNode.removeChild(node);
+ }
+ }
+})();
+ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
+ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
+ko.exportSymbol('cleanNode', ko.cleanNode);
+ko.exportSymbol('removeNode', ko.removeNode);
+ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
+ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
+ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
+(function () {
+ var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
+
+ function simpleHtmlParse(html) {
+ // Based on jQuery's "clean" function, but only accounting for table-related elements.
+ // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
+
+ // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
+ // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
+ // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
+ // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
+
+ // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
+ var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
+ !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
+ /* anything else */ [0, "", ""];
+
+ // Go to html and back, then peel off extra wrappers
+ // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
+ var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
+ if (typeof window['innerShiv'] == "function") {
+ div.appendChild(window['innerShiv'](markup));
+ } else {
+ div.innerHTML = markup;
+ }
+
+ // Move to the right depth
+ while (wrap[0]--)
+ div = div.lastChild;
+
+ return ko.utils.makeArray(div.lastChild.childNodes);
+ }
+
+ function jQueryHtmlParse(html) {
+ var elems = jQuery['clean']([html]);
+
+ // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
+ // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
+ // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
+ if (elems && elems[0]) {
+ // Find the top-most parent element that's a direct child of a document fragment
+ var elem = elems[0];
+ while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
+ elem = elem.parentNode;
+ // ... then detach it
+ if (elem.parentNode)
+ elem.parentNode.removeChild(elem);
+ }
+
+ return elems;
+ }
+
+ ko.utils.parseHtmlFragment = function(html) {
+ return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
+ : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
+ };
+
+ ko.utils.setHtml = function(node, html) {
+ ko.utils.emptyDomNode(node);
+
+ // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
+ html = ko.utils.unwrapObservable(html);
+
+ if ((html !== null) && (html !== undefined)) {
+ if (typeof html != 'string')
+ html = html.toString();
+
+ // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
+ // for example <tr> elements which are not normally allowed to exist on their own.
+ // If you've referenced jQuery we'll use that rather than duplicating its code.
+ if (typeof jQuery != 'undefined') {
+ jQuery(node)['html'](html);
+ } else {
+ // ... otherwise, use KO's own parsing logic.
+ var parsedNodes = ko.utils.parseHtmlFragment(html);
+ for (var i = 0; i < parsedNodes.length; i++)
+ node.appendChild(parsedNodes[i]);
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
+ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
+
+ko.memoization = (function () {
+ var memos = {};
+
+ function randomMax8HexChars() {
+ return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
+ }
+ function generateRandomId() {
+ return randomMax8HexChars() + randomMax8HexChars();
+ }
+ function findMemoNodes(rootNode, appendToArray) {
+ if (!rootNode)
+ return;
+ if (rootNode.nodeType == 8) {
+ var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
+ if (memoId != null)
+ appendToArray.push({ domNode: rootNode, memoId: memoId });
+ } else if (rootNode.nodeType == 1) {
+ for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
+ findMemoNodes(childNodes[i], appendToArray);
+ }
+ }
+
+ return {
+ memoize: function (callback) {
+ if (typeof callback != "function")
+ throw new Error("You can only pass a function to ko.memoization.memoize()");
+ var memoId = generateRandomId();
+ memos[memoId] = callback;
+ return "<!--[ko_memo:" + memoId + "]-->";
+ },
+
+ unmemoize: function (memoId, callbackParams) {
+ var callback = memos[memoId];
+ if (callback === undefined)
+ throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
+ try {
+ callback.apply(null, callbackParams || []);
+ return true;
+ }
+ finally { delete memos[memoId]; }
+ },
+
+ unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
+ var memos = [];
+ findMemoNodes(domNode, memos);
+ for (var i = 0, j = memos.length; i < j; i++) {
+ var node = memos[i].domNode;
+ var combinedParams = [node];
+ if (extraCallbackParamsArray)
+ ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
+ ko.memoization.unmemoize(memos[i].memoId, combinedParams);
+ node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
+ if (node.parentNode)
+ node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
+ }
+ },
+
+ parseMemoText: function (memoText) {
+ var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
+ return match ? match[1] : null;
+ }
+ };
+})();
+
+ko.exportSymbol('memoization', ko.memoization);
+ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
+ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
+ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
+ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
+ko.extenders = {
+ 'throttle': function(target, timeout) {
+ // Throttling means two things:
+
+ // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
+ // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
+ target['throttleEvaluation'] = timeout;
+
+ // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
+ // so the target cannot change value synchronously or faster than a certain rate
+ var writeTimeoutInstance = null;
+ return ko.dependentObservable({
+ 'read': target,
+ 'write': function(value) {
+ clearTimeout(writeTimeoutInstance);
+ writeTimeoutInstance = setTimeout(function() {
+ target(value);
+ }, timeout);
+ }
+ });
+ },
+
+ 'notify': function(target, notifyWhen) {
+ target["equalityComparer"] = notifyWhen == "always"
+ ? function() { return false } // Treat all values as not equal
+ : ko.observable["fn"]["equalityComparer"];
+ return target;
+ }
+};
+
+function applyExtenders(requestedExtenders) {
+ var target = this;
+ if (requestedExtenders) {
+ for (var key in requestedExtenders) {
+ var extenderHandler = ko.extenders[key];
+ if (typeof extenderHandler == 'function') {
+ target = extenderHandler(target, requestedExtenders[key]);
+ }
+ }
+ }
+ return target;
+}
+
+ko.exportSymbol('extenders', ko.extenders);
+
+ko.subscription = function (target, callback, disposeCallback) {
+ this.target = target;
+ this.callback = callback;
+ this.disposeCallback = disposeCallback;
+ ko.exportProperty(this, 'dispose', this.dispose);
+};
+ko.subscription.prototype.dispose = function () {
+ this.isDisposed = true;
+ this.disposeCallback();
+};
+
+ko.subscribable = function () {
+ this._subscriptions = {};
+
+ ko.utils.extend(this, ko.subscribable['fn']);
+ ko.exportProperty(this, 'subscribe', this.subscribe);
+ ko.exportProperty(this, 'extend', this.extend);
+ ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
+}
+
+var defaultEvent = "change";
+
+ko.subscribable['fn'] = {
+ subscribe: function (callback, callbackTarget, event) {
+ event = event || defaultEvent;
+ var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
+
+ var subscription = new ko.subscription(this, boundCallback, function () {
+ ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
+ }.bind(this));
+
+ if (!this._subscriptions[event])
+ this._subscriptions[event] = [];
+ this._subscriptions[event].push(subscription);
+ return subscription;
+ },
+
+ "notifySubscribers": function (valueToNotify, event) {
+ event = event || defaultEvent;
+ if (this._subscriptions[event]) {
+ ko.dependencyDetection.ignore(function() {
+ ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
+ // In case a subscription was disposed during the arrayForEach cycle, check
+ // for isDisposed on each subscription before invoking its callback
+ if (subscription && (subscription.isDisposed !== true))
+ subscription.callback(valueToNotify);
+ });
+ }, this);
+ }
+ },
+
+ getSubscriptionsCount: function () {
+ var total = 0;
+ for (var eventName in this._subscriptions) {
+ if (this._subscriptions.hasOwnProperty(eventName))
+ total += this._subscriptions[eventName].length;
+ }
+ return total;
+ },
+
+ extend: applyExtenders
+};
+
+
+ko.isSubscribable = function (instance) {
+ return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
+};
+
+ko.exportSymbol('subscribable', ko.subscribable);
+ko.exportSymbol('isSubscribable', ko.isSubscribable);
+
+ko.dependencyDetection = (function () {
+ var _frames = [];
+
+ return {
+ begin: function (callback) {
+ _frames.push({ callback: callback, distinctDependencies:[] });
+ },
+
+ end: function () {
+ _frames.pop();
+ },
+
+ registerDependency: function (subscribable) {
+ if (!ko.isSubscribable(subscribable))
+ throw new Error("Only subscribable things can act as dependencies");
+ if (_frames.length > 0) {
+ var topFrame = _frames[_frames.length - 1];
+ if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
+ return;
+ topFrame.distinctDependencies.push(subscribable);
+ topFrame.callback(subscribable);
+ }
+ },
+
+ ignore: function(callback, callbackTarget, callbackArgs) {
+ try {
+ _frames.push(null);
+ return callback.apply(callbackTarget, callbackArgs || []);
+ } finally {
+ _frames.pop();
+ }
+ }
+ };
+})();
+var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
+
+ko.observable = function (initialValue) {
+ var _latestValue = initialValue;
+
+ function observable() {
+ if (arguments.length > 0) {
+ // Write
+
+ // Ignore writes if the value hasn't changed
+ if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
+ observable.valueWillMutate();
+ _latestValue = arguments[0];
+ if (DEBUG) observable._latestValue = _latestValue;
+ observable.valueHasMutated();
+ }
+ return this; // Permits chained assignments
+ }
+ else {
+ // Read
+ ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
+ return _latestValue;
+ }
+ }
+ if (DEBUG) observable._latestValue = _latestValue;
+ ko.subscribable.call(observable);
+ observable.peek = function() { return _latestValue };
+ observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
+ observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
+ ko.utils.extend(observable, ko.observable['fn']);
+
+ ko.exportProperty(observable, 'peek', observable.peek);
+ ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
+ ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
+
+ return observable;
+}
+
+ko.observable['fn'] = {
+ "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
+ var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
+ return oldValueIsPrimitive ? (a === b) : false;
+ }
+};
+
+var protoProperty = ko.observable.protoProperty = "__ko_proto__";
+ko.observable['fn'][protoProperty] = ko.observable;
+
+ko.hasPrototype = function(instance, prototype) {
+ if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
+ if (instance[protoProperty] === prototype) return true;
+ return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
+};
+
+ko.isObservable = function (instance) {
+ return ko.hasPrototype(instance, ko.observable);
+}
+ko.isWriteableObservable = function (instance) {
+ // Observable
+ if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
+ return true;
+ // Writeable dependent observable
+ if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
+ return true;
+ // Anything else
+ return false;
+}
+
+
+ko.exportSymbol('observable', ko.observable);
+ko.exportSymbol('isObservable', ko.isObservable);
+ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
+ko.observableArray = function (initialValues) {
+ if (arguments.length == 0) {
+ // Zero-parameter constructor initializes to empty array
+ initialValues = [];
+ }
+ if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
+ throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
+
+ var result = ko.observable(initialValues);
+ ko.utils.extend(result, ko.observableArray['fn']);
+ return result;
+}
+
+ko.observableArray['fn'] = {
+ 'remove': function (valueOrPredicate) {
+ var underlyingArray = this.peek();
+ var removedValues = [];
+ var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
+ for (var i = 0; i < underlyingArray.length; i++) {
+ var value = underlyingArray[i];
+ if (predicate(value)) {
+ if (removedValues.length === 0) {
+ this.valueWillMutate();
+ }
+ removedValues.push(value);
+ underlyingArray.splice(i, 1);
+ i--;
+ }
+ }
+ if (removedValues.length) {
+ this.valueHasMutated();
+ }
+ return removedValues;
+ },
+
+ 'removeAll': function (arrayOfValues) {
+ // If you passed zero args, we remove everything
+ if (arrayOfValues === undefined) {
+ var underlyingArray = this.peek();
+ var allValues = underlyingArray.slice(0);
+ this.valueWillMutate();
+ underlyingArray.splice(0, underlyingArray.length);
+ this.valueHasMutated();
+ return allValues;
+ }
+ // If you passed an arg, we interpret it as an array of entries to remove
+ if (!arrayOfValues)
+ return [];
+ return this['remove'](function (value) {
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
+ });
+ },
+
+ 'destroy': function (valueOrPredicate) {
+ var underlyingArray = this.peek();
+ var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
+ this.valueWillMutate();
+ for (var i = underlyingArray.length - 1; i >= 0; i--) {
+ var value = underlyingArray[i];
+ if (predicate(value))
+ underlyingArray[i]["_destroy"] = true;
+ }
+ this.valueHasMutated();
+ },
+
+ 'destroyAll': function (arrayOfValues) {
+ // If you passed zero args, we destroy everything
+ if (arrayOfValues === undefined)
+ return this['destroy'](function() { return true });
+
+ // If you passed an arg, we interpret it as an array of entries to destroy
+ if (!arrayOfValues)
+ return [];
+ return this['destroy'](function (value) {
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
+ });
+ },
+
+ 'indexOf': function (item) {
+ var underlyingArray = this();
+ return ko.utils.arrayIndexOf(underlyingArray, item);
+ },
+
+ 'replace': function(oldItem, newItem) {
+ var index = this['indexOf'](oldItem);
+ if (index >= 0) {
+ this.valueWillMutate();
+ this.peek()[index] = newItem;
+ this.valueHasMutated();
+ }
+ }
+}
+
+// Populate ko.observableArray.fn with read/write functions from native arrays
+// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
+// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
+ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
+ ko.observableArray['fn'][methodName] = function () {
+ // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
+ // (for consistency with mutating regular observables)
+ var underlyingArray = this.peek();
+ this.valueWillMutate();
+ var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
+ this.valueHasMutated();
+ return methodCallResult;
+ };
+});
+
+// Populate ko.observableArray.fn with read-only functions from native arrays
+ko.utils.arrayForEach(["slice"], function (methodName) {
+ ko.observableArray['fn'][methodName] = function () {
+ var underlyingArray = this();
+ return underlyingArray[methodName].apply(underlyingArray, arguments);
+ };
+});
+
+ko.exportSymbol('observableArray', ko.observableArray);
+ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
+ var _latestValue,
+ _hasBeenEvaluated = false,
+ _isBeingEvaluated = false,
+ readFunction = evaluatorFunctionOrOptions;
+
+ if (readFunction && typeof readFunction == "object") {
+ // Single-parameter syntax - everything is on this "options" param
+ options = readFunction;
+ readFunction = options["read"];
+ } else {
+ // Multi-parameter syntax - construct the options according to the params passed
+ options = options || {};
+ if (!readFunction)
+ readFunction = options["read"];
+ }
+ if (typeof readFunction != "function")
+ throw new Error("Pass a function that returns the value of the ko.computed");
+
+ function addSubscriptionToDependency(subscribable) {
+ _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
+ }
+
+ function disposeAllSubscriptionsToDependencies() {
+ ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
+ subscription.dispose();
+ });
+ _subscriptionsToDependencies = [];
+ }
+
+ function evaluatePossiblyAsync() {
+ var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
+ if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
+ clearTimeout(evaluationTimeoutInstance);
+ evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
+ } else
+ evaluateImmediate();
+ }
+
+ function evaluateImmediate() {
+ if (_isBeingEvaluated) {
+ // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
+ // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
+ // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
+ // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
+ return;
+ }
+
+ // Don't dispose on first evaluation, because the "disposeWhen" callback might
+ // e.g., dispose when the associated DOM element isn't in the doc, and it's not
+ // going to be in the doc until *after* the first evaluation
+ if (_hasBeenEvaluated && disposeWhen()) {
+ dispose();
+ return;
+ }
+
+ _isBeingEvaluated = true;
+ try {
+ // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
+ // Then, during evaluation, we cross off any that are in fact still being used.
+ var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
+
+ ko.dependencyDetection.begin(function(subscribable) {
+ var inOld;
+ if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
+ disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
+ else
+ addSubscriptionToDependency(subscribable); // Brand new subscription - add it
+ });
+
+ var newValue = readFunction.call(evaluatorFunctionTarget);
+
+ // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
+ for (var i = disposalCandidates.length - 1; i >= 0; i--) {
+ if (disposalCandidates[i])
+ _subscriptionsToDependencies.splice(i, 1)[0].dispose();
+ }
+ _hasBeenEvaluated = true;
+
+ dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
+ _latestValue = newValue;
+ if (DEBUG) dependentObservable._latestValue = _latestValue;
+ } finally {
+ ko.dependencyDetection.end();
+ }
+
+ dependentObservable["notifySubscribers"](_latestValue);
+ _isBeingEvaluated = false;
+ if (!_subscriptionsToDependencies.length)
+ dispose();
+ }
+
+ function dependentObservable() {
+ if (arguments.length > 0) {
+ if (typeof writeFunction === "function") {
+ // Writing a value
+ writeFunction.apply(evaluatorFunctionTarget, arguments);
+ } else {
+ throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
+ }
+ return this; // Permits chained assignments
+ } else {
+ // Reading the value
+ if (!_hasBeenEvaluated)
+ evaluateImmediate();
+ ko.dependencyDetection.registerDependency(dependentObservable);
+ return _latestValue;
+ }
+ }
+
+ function peek() {
+ if (!_hasBeenEvaluated)
+ evaluateImmediate();
+ return _latestValue;
+ }
+
+ function isActive() {
+ return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
+ }
+
+ // By here, "options" is always non-null
+ var writeFunction = options["write"],
+ disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
+ disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
+ dispose = disposeAllSubscriptionsToDependencies,
+ _subscriptionsToDependencies = [],
+ evaluationTimeoutInstance = null;
+
+ if (!evaluatorFunctionTarget)
+ evaluatorFunctionTarget = options["owner"];
+
+ dependentObservable.peek = peek;
+ dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
+ dependentObservable.hasWriteFunction = typeof options["write"] === "function";
+ dependentObservable.dispose = function () { dispose(); };
+ dependentObservable.isActive = isActive;
+
+ ko.subscribable.call(dependentObservable);
+ ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
+
+ ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
+ ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
+ ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
+ ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
+
+ // Evaluate, unless deferEvaluation is true
+ if (options['deferEvaluation'] !== true)
+ evaluateImmediate();
+
+ // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
+ // But skip if isActive is false (there will never be any dependencies to dispose).
+ // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
+ // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
+ if (disposeWhenNodeIsRemoved && isActive()) {
+ dispose = function() {
+ ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
+ disposeAllSubscriptionsToDependencies();
+ };
+ ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
+ var existingDisposeWhenFunction = disposeWhen;
+ disposeWhen = function () {
+ return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
+ }
+ }
+
+ return dependentObservable;
+};
+
+ko.isComputed = function(instance) {
+ return ko.hasPrototype(instance, ko.dependentObservable);
+};
+
+var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
+ko.dependentObservable[protoProp] = ko.observable;
+
+ko.dependentObservable['fn'] = {};
+ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
+
+ko.exportSymbol('dependentObservable', ko.dependentObservable);
+ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
+ko.exportSymbol('isComputed', ko.isComputed);
+
+(function() {
+ var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
+
+ ko.toJS = function(rootObject) {
+ if (arguments.length == 0)
+ throw new Error("When calling ko.toJS, pass the object you want to convert.");
+
+ // We just unwrap everything at every level in the object graph
+ return mapJsObjectGraph(rootObject, function(valueToMap) {
+ // Loop because an observable's value might in turn be another observable wrapper
+ for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
+ valueToMap = valueToMap();
+ return valueToMap;
+ });
+ };
+
+ ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
+ var plainJavaScriptObject = ko.toJS(rootObject);
+ return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
+ };
+
+ function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
+ visitedObjects = visitedObjects || new objectLookup();
+
+ rootObject = mapInputCallback(rootObject);
+ var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
+ if (!canHaveProperties)
+ return rootObject;
+
+ var outputProperties = rootObject instanceof Array ? [] : {};
+ visitedObjects.save(rootObject, outputProperties);
+
+ visitPropertiesOrArrayEntries(rootObject, function(indexer) {
+ var propertyValue = mapInputCallback(rootObject[indexer]);
+
+ switch (typeof propertyValue) {
+ case "boolean":
+ case "number":
+ case "string":
+ case "function":
+ outputProperties[indexer] = propertyValue;
+ break;
+ case "object":
+ case "undefined":
+ var previouslyMappedValue = visitedObjects.get(propertyValue);
+ outputProperties[indexer] = (previouslyMappedValue !== undefined)
+ ? previouslyMappedValue
+ : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
+ break;
+ }
+ });
+
+ return outputProperties;
+ }
+
+ function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
+ if (rootObject instanceof Array) {
+ for (var i = 0; i < rootObject.length; i++)
+ visitorCallback(i);
+
+ // For arrays, also respect toJSON property for custom mappings (fixes #278)
+ if (typeof rootObject['toJSON'] == 'function')
+ visitorCallback('toJSON');
+ } else {
+ for (var propertyName in rootObject)
+ visitorCallback(propertyName);
+ }
+ };
+
+ function objectLookup() {
+ var keys = [];
+ var values = [];
+ this.save = function(key, value) {
+ var existingIndex = ko.utils.arrayIndexOf(keys, key);
+ if (existingIndex >= 0)
+ values[existingIndex] = value;
+ else {
+ keys.push(key);
+ values.push(value);
+ }
+ };
+ this.get = function(key) {
+ var existingIndex = ko.utils.arrayIndexOf(keys, key);
+ return (existingIndex >= 0) ? values[existingIndex] : undefined;
+ };
+ };
+})();
+
+ko.exportSymbol('toJS', ko.toJS);
+ko.exportSymbol('toJSON', ko.toJSON);
+(function () {
+ var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
+
+ // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
+ // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
+ // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
+ ko.selectExtensions = {
+ readValue : function(element) {
+ switch (ko.utils.tagNameLower(element)) {
+ case 'option':
+ if (element[hasDomDataExpandoProperty] === true)
+ return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
+ return ko.utils.ieVersion <= 7
+ ? (element.getAttributeNode('value').specified ? element.value : element.text)
+ : element.value;
+ case 'select':
+ return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
+ default:
+ return element.value;
+ }
+ },
+
+ writeValue: function(element, value) {
+ switch (ko.utils.tagNameLower(element)) {
+ case 'option':
+ switch(typeof value) {
+ case "string":
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
+ if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
+ delete element[hasDomDataExpandoProperty];
+ }
+ element.value = value;
+ break;
+ default:
+ // Store arbitrary object using DomData
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
+ element[hasDomDataExpandoProperty] = true;
+
+ // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
+ element.value = typeof value === "number" ? value : "";
+ break;
+ }
+ break;
+ case 'select':
+ for (var i = element.options.length - 1; i >= 0; i--) {
+ if (ko.selectExtensions.readValue(element.options[i]) == value) {
+ element.selectedIndex = i;
+ break;
+ }
+ }
+ break;
+ default:
+ if ((value === null) || (value === undefined))
+ value = "";
+ element.value = value;
+ break;
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('selectExtensions', ko.selectExtensions);
+ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
+ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
+ko.expressionRewriting = (function () {
+ var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
+ var javaScriptReservedWords = ["true", "false"];
+
+ // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
+ // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
+ var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
+
+ function restoreTokens(string, tokens) {
+ var prevValue = null;
+ while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
+ prevValue = string;
+ string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
+ return tokens[tokenIndex];
+ });
+ }
+ return string;
+ }
+
+ function getWriteableValue(expression) {
+ if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
+ return false;
+ var match = expression.match(javaScriptAssignmentTarget);
+ return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
+ }
+
+ function ensureQuoted(key) {
+ var trimmedKey = ko.utils.stringTrim(key);
+ switch (trimmedKey.length && trimmedKey.charAt(0)) {
+ case "'":
+ case '"':
+ return key;
+ default:
+ return "'" + trimmedKey + "'";
+ }
+ }
+
+ return {
+ bindingRewriteValidators: [],
+
+ parseObjectLiteral: function(objectLiteralString) {
+ // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
+ // that is sufficient just to split an object literal string into a set of top-level key-value pairs
+
+ var str = ko.utils.stringTrim(objectLiteralString);
+ if (str.length < 3)
+ return [];
+ if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
+ str = str.substring(1, str.length - 1);
+
+ // Pull out any string literals and regex literals
+ var tokens = [];
+ var tokenStart = null, tokenEndChar;
+ for (var position = 0; position < str.length; position++) {
+ var c = str.charAt(position);
+ if (tokenStart === null) {
+ switch (c) {
+ case '"':
+ case "'":
+ case "/":
+ tokenStart = position;
+ tokenEndChar = c;
+ break;
+ }
+ } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
+ var token = str.substring(tokenStart, position + 1);
+ tokens.push(token);
+ var replacement = "@ko_token_" + (tokens.length - 1) + "@";
+ str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
+ position -= (token.length - replacement.length);
+ tokenStart = null;
+ }
+ }
+
+ // Next pull out balanced paren, brace, and bracket blocks
+ tokenStart = null;
+ tokenEndChar = null;
+ var tokenDepth = 0, tokenStartChar = null;
+ for (var position = 0; position < str.length; position++) {
+ var c = str.charAt(position);
+ if (tokenStart === null) {
+ switch (c) {
+ case "{": tokenStart = position; tokenStartChar = c;
+ tokenEndChar = "}";
+ break;
+ case "(": tokenStart = position; tokenStartChar = c;
+ tokenEndChar = ")";
+ break;
+ case "[": tokenStart = position; tokenStartChar = c;
+ tokenEndChar = "]";
+ break;
+ }
+ }
+
+ if (c === tokenStartChar)
+ tokenDepth++;
+ else if (c === tokenEndChar) {
+ tokenDepth--;
+ if (tokenDepth === 0) {
+ var token = str.substring(tokenStart, position + 1);
+ tokens.push(token);
+ var replacement = "@ko_token_" + (tokens.length - 1) + "@";
+ str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
+ position -= (token.length - replacement.length);
+ tokenStart = null;
+ }
+ }
+ }
+
+ // Now we can safely split on commas to get the key/value pairs
+ var result = [];
+ var keyValuePairs = str.split(",");
+ for (var i = 0, j = keyValuePairs.length; i < j; i++) {
+ var pair = keyValuePairs[i];
+ var colonPos = pair.indexOf(":");
+ if ((colonPos > 0) && (colonPos < pair.length - 1)) {
+ var key = pair.substring(0, colonPos);
+ var value = pair.substring(colonPos + 1);
+ result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
+ } else {
+ result.push({ 'unknown': restoreTokens(pair, tokens) });
+ }
+ }
+ return result;
+ },
+
+ preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
+ var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
+ ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
+ : objectLiteralStringOrKeyValueArray;
+ var resultStrings = [], propertyAccessorResultStrings = [];
+
+ var keyValueEntry;
+ for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
+ if (resultStrings.length > 0)
+ resultStrings.push(",");
+
+ if (keyValueEntry['key']) {
+ var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
+ resultStrings.push(quotedKey);
+ resultStrings.push(":");
+ resultStrings.push(val);
+
+ if (val = getWriteableValue(ko.utils.stringTrim(val))) {
+ if (propertyAccessorResultStrings.length > 0)
+ propertyAccessorResultStrings.push(", ");
+ propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
+ }
+ } else if (keyValueEntry['unknown']) {
+ resultStrings.push(keyValueEntry['unknown']);
+ }
+ }
+
+ var combinedResult = resultStrings.join("");
+ if (propertyAccessorResultStrings.length > 0) {
+ var allPropertyAccessors = propertyAccessorResultStrings.join("");
+ combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
+ }
+
+ return combinedResult;
+ },
+
+ keyValueArrayContainsKey: function(keyValueArray, key) {
+ for (var i = 0; i < keyValueArray.length; i++)
+ if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
+ return true;
+ return false;
+ },
+
+ // Internal, private KO utility for updating model properties from within bindings
+ // property: If the property being updated is (or might be) an observable, pass it here
+ // If it turns out to be a writable observable, it will be written to directly
+ // allBindingsAccessor: All bindings in the current execution context.
+ // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
+ // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
+ // value: The value to be written
+ // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
+ // it is !== existing value on that writable observable
+ writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
+ if (!property || !ko.isWriteableObservable(property)) {
+ var propWriters = allBindingsAccessor()['_ko_property_writers'];
+ if (propWriters && propWriters[key])
+ propWriters[key](value);
+ } else if (!checkIfDifferent || property.peek() !== value) {
+ property(value);
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
+ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
+ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
+ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
+
+// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
+// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
+ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
+ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
+ // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
+ // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
+ // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
+ // of that virtual hierarchy
+ //
+ // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
+ // without having to scatter special cases all over the binding and templating code.
+
+ // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
+ // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
+ // So, use node.text where available, and node.nodeValue elsewhere
+ var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
+
+ var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
+ var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
+ var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
+
+ function isStartComment(node) {
+ return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
+ }
+
+ function isEndComment(node) {
+ return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
+ }
+
+ function getVirtualChildren(startComment, allowUnbalanced) {
+ var currentNode = startComment;
+ var depth = 1;
+ var children = [];
+ while (currentNode = currentNode.nextSibling) {
+ if (isEndComment(currentNode)) {
+ depth--;
+ if (depth === 0)
+ return children;
+ }
+
+ children.push(currentNode);
+
+ if (isStartComment(currentNode))
+ depth++;
+ }
+ if (!allowUnbalanced)
+ throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
+ return null;
+ }
+
+ function getMatchingEndComment(startComment, allowUnbalanced) {
+ var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
+ if (allVirtualChildren) {
+ if (allVirtualChildren.length > 0)
+ return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
+ return startComment.nextSibling;
+ } else
+ return null; // Must have no matching end comment, and allowUnbalanced is true
+ }
+
+ function getUnbalancedChildTags(node) {
+ // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
+ // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
+ var childNode = node.firstChild, captureRemaining = null;
+ if (childNode) {
+ do {
+ if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
+ captureRemaining.push(childNode);
+ else if (isStartComment(childNode)) {
+ var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
+ if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
+ childNode = matchingEndComment;
+ else
+ captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
+ } else if (isEndComment(childNode)) {
+ captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
+ }
+ } while (childNode = childNode.nextSibling);
+ }
+ return captureRemaining;
+ }
+
+ ko.virtualElements = {
+ allowedBindings: {},
+
+ childNodes: function(node) {
+ return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
+ },
+
+ emptyNode: function(node) {
+ if (!isStartComment(node))
+ ko.utils.emptyDomNode(node);
+ else {
+ var virtualChildren = ko.virtualElements.childNodes(node);
+ for (var i = 0, j = virtualChildren.length; i < j; i++)
+ ko.removeNode(virtualChildren[i]);
+ }
+ },
+
+ setDomNodeChildren: function(node, childNodes) {
+ if (!isStartComment(node))
+ ko.utils.setDomNodeChildren(node, childNodes);
+ else {
+ ko.virtualElements.emptyNode(node);
+ var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
+ for (var i = 0, j = childNodes.length; i < j; i++)
+ endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
+ }
+ },
+
+ prepend: function(containerNode, nodeToPrepend) {
+ if (!isStartComment(containerNode)) {
+ if (containerNode.firstChild)
+ containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
+ else
+ containerNode.appendChild(nodeToPrepend);
+ } else {
+ // Start comments must always have a parent and at least one following sibling (the end comment)
+ containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
+ }
+ },
+
+ insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
+ if (!insertAfterNode) {
+ ko.virtualElements.prepend(containerNode, nodeToInsert);
+ } else if (!isStartComment(containerNode)) {
+ // Insert after insertion point
+ if (insertAfterNode.nextSibling)
+ containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
+ else
+ containerNode.appendChild(nodeToInsert);
+ } else {
+ // Children of start comments must always have a parent and at least one following sibling (the end comment)
+ containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
+ }
+ },
+
+ firstChild: function(node) {
+ if (!isStartComment(node))
+ return node.firstChild;
+ if (!node.nextSibling || isEndComment(node.nextSibling))
+ return null;
+ return node.nextSibling;
+ },
+
+ nextSibling: function(node) {
+ if (isStartComment(node))
+ node = getMatchingEndComment(node);
+ if (node.nextSibling && isEndComment(node.nextSibling))
+ return null;
+ return node.nextSibling;
+ },
+
+ virtualNodeBindingValue: function(node) {
+ var regexMatch = isStartComment(node);
+ return regexMatch ? regexMatch[1] : null;
+ },
+
+ normaliseVirtualElementDomStructure: function(elementVerified) {
+ // Workaround for https://github.com/SteveSanderson/knockout/issues/155
+ // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
+ // that are direct descendants of <ul> into the preceding <li>)
+ if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
+ return;
+
+ // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
+ // must be intended to appear *after* that child, so move them there.
+ var childNode = elementVerified.firstChild;
+ if (childNode) {
+ do {
+ if (childNode.nodeType === 1) {
+ var unbalancedTags = getUnbalancedChildTags(childNode);
+ if (unbalancedTags) {
+ // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
+ var nodeToInsertBefore = childNode.nextSibling;
+ for (var i = 0; i < unbalancedTags.length; i++) {
+ if (nodeToInsertBefore)
+ elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
+ else
+ elementVerified.appendChild(unbalancedTags[i]);
+ }
+ }
+ }
+ } while (childNode = childNode.nextSibling);
+ }
+ }
+ };
+})();
+ko.exportSymbol('virtualElements', ko.virtualElements);
+ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
+ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
+//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
+ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
+//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
+ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
+ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
+(function() {
+ var defaultBindingAttributeName = "data-bind";
+
+ ko.bindingProvider = function() {
+ this.bindingCache = {};
+ };
+
+ ko.utils.extend(ko.bindingProvider.prototype, {
+ 'nodeHasBindings': function(node) {
+ switch (node.nodeType) {
+ case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
+ case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
+ default: return false;
+ }
+ },
+
+ 'getBindings': function(node, bindingContext) {
+ var bindingsString = this['getBindingsString'](node, bindingContext);
+ return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
+ },
+
+ // The following function is only used internally by this default provider.
+ // It's not part of the interface definition for a general binding provider.
+ 'getBindingsString': function(node, bindingContext) {
+ switch (node.nodeType) {
+ case 1: return node.getAttribute(defaultBindingAttributeName); // Element
+ case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
+ default: return null;
+ }
+ },
+
+ // The following function is only used internally by this default provider.
+ // It's not part of the interface definition for a general binding provider.
+ 'parseBindingsString': function(bindingsString, bindingContext, node) {
+ try {
+ var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
+ return bindingFunction(bindingContext, node);
+ } catch (ex) {
+ throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
+ }
+ }
+ });
+
+ ko.bindingProvider['instance'] = new ko.bindingProvider();
+
+ function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
+ var cacheKey = bindingsString;
+ return cache[cacheKey]
+ || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
+ }
+
+ function createBindingsStringEvaluator(bindingsString) {
+ // Build the source for a function that evaluates "expression"
+ // For each scope variable, add an extra level of "with" nesting
+ // Example result: with(sc1) { with(sc0) { return (expression) } }
+ var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
+ functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
+ return new Function("$context", "$element", functionBody);
+ }
+})();
+
+ko.exportSymbol('bindingProvider', ko.bindingProvider);
+(function () {
+ ko.bindingHandlers = {};
+
+ ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
+ if (parentBindingContext) {
+ ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
+ this['$parentContext'] = parentBindingContext;
+ this['$parent'] = parentBindingContext['$data'];
+ this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
+ this['$parents'].unshift(this['$parent']);
+ } else {
+ this['$parents'] = [];
+ this['$root'] = dataItem;
+ // Export 'ko' in the binding context so it will be available in bindings and templates
+ // even if 'ko' isn't exported as a global, such as when using an AMD loader.
+ // See https://github.com/SteveSanderson/knockout/issues/490
+ this['ko'] = ko;
+ }
+ this['$data'] = dataItem;
+ if (dataItemAlias)
+ this[dataItemAlias] = dataItem;
+ }
+ ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
+ return new ko.bindingContext(dataItem, this, dataItemAlias);
+ };
+ ko.bindingContext.prototype['extend'] = function(properties) {
+ var clone = ko.utils.extend(new ko.bindingContext(), this);
+ return ko.utils.extend(clone, properties);
+ };
+
+ function validateThatBindingIsAllowedForVirtualElements(bindingName) {
+ var validator = ko.virtualElements.allowedBindings[bindingName];
+ if (!validator)
+ throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
+ }
+
+ function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
+ var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
+ while (currentChild = nextInQueue) {
+ // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
+ nextInQueue = ko.virtualElements.nextSibling(currentChild);
+ applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
+ }
+ }
+
+ function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
+ var shouldBindDescendants = true;
+
+ // Perf optimisation: Apply bindings only if...
+ // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
+ // Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
+ // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
+ var isElement = (nodeVerified.nodeType === 1);
+ if (isElement) // Workaround IE <= 8 HTML parsing weirdness
+ ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
+
+ var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
+ || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
+ if (shouldApplyBindings)
+ shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
+
+ if (shouldBindDescendants) {
+ // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
+ // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
+ // hence bindingContextsMayDifferFromDomParentElement is false
+ // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
+ // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
+ // hence bindingContextsMayDifferFromDomParentElement is true
+ applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
+ }
+ }
+
+ function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
+ // Need to be sure that inits are only run once, and updates never run until all the inits have been run
+ var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
+
+ // Each time the dependentObservable is evaluated (after data changes),
+ // the binding attribute is reparsed so that it can pick out the correct
+ // model properties in the context of the changed data.
+ // DOM event callbacks need to be able to access this changed data,
+ // so we need a single parsedBindings variable (shared by all callbacks
+ // associated with this node's bindings) that all the closures can access.
+ var parsedBindings;
+ function makeValueAccessor(bindingKey) {
+ return function () { return parsedBindings[bindingKey] }
+ }
+ function parsedBindingsAccessor() {
+ return parsedBindings;
+ }
+
+ var bindingHandlerThatControlsDescendantBindings;
+ ko.dependentObservable(
+ function () {
+ // Ensure we have a nonnull binding context to work with
+ var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
+ ? viewModelOrBindingContext
+ : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
+ var viewModel = bindingContextInstance['$data'];
+
+ // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
+ // we can easily recover it just by scanning up the node's ancestors in the DOM
+ // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
+ if (bindingContextMayDifferFromDomParentElement)
+ ko.storedBindingContextForNode(node, bindingContextInstance);
+
+ // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
+ var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
+ parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
+
+ if (parsedBindings) {
+ // First run all the inits, so bindings can register for notification on changes
+ if (initPhase === 0) {
+ initPhase = 1;
+ for (var bindingKey in parsedBindings) {
+ var binding = ko.bindingHandlers[bindingKey];
+ if (binding && node.nodeType === 8)
+ validateThatBindingIsAllowedForVirtualElements(bindingKey);
+
+ if (binding && typeof binding["init"] == "function") {
+ var handlerInitFn = binding["init"];
+ var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
+
+ // If this binding handler claims to control descendant bindings, make a note of this
+ if (initResult && initResult['controlsDescendantBindings']) {
+ if (bindingHandlerThatControlsDescendantBindings !== undefined)
+ throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
+ bindingHandlerThatControlsDescendantBindings = bindingKey;
+ }
+ }
+ }
+ initPhase = 2;
+ }
+
+ // ... then run all the updates, which might trigger changes even on the first evaluation
+ if (initPhase === 2) {
+ for (var bindingKey in parsedBindings) {
+ var binding = ko.bindingHandlers[bindingKey];
+ if (binding && typeof binding["update"] == "function") {
+ var handlerUpdateFn = binding["update"];
+ handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
+ }
+ }
+ }
+ }
+ },
+ null,
+ { disposeWhenNodeIsRemoved : node }
+ );
+
+ return {
+ shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
+ };
+ };
+
+ var storedBindingContextDomDataKey = "__ko_bindingContext__";
+ ko.storedBindingContextForNode = function (node, bindingContext) {
+ if (arguments.length == 2)
+ ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
+ else
+ return ko.utils.domData.get(node, storedBindingContextDomDataKey);
+ }
+
+ ko.applyBindingsToNode = function (node, bindings, viewModel) {
+ if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
+ ko.virtualElements.normaliseVirtualElementDomStructure(node);
+ return applyBindingsToNodeInternal(node, bindings, viewModel, true);
+ };
+
+ ko.applyBindingsToDescendants = function(viewModel, rootNode) {
+ if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
+ applyBindingsToDescendantsInternal(viewModel, rootNode, true);
+ };
+
+ ko.applyBindings = function (viewModel, rootNode) {
+ if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
+ throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
+ rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
+
+ applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
+ };
+
+ // Retrieving binding context from arbitrary nodes
+ ko.contextFor = function(node) {
+ // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
+ switch (node.nodeType) {
+ case 1:
+ case 8:
+ var context = ko.storedBindingContextForNode(node);
+ if (context) return context;
+ if (node.parentNode) return ko.contextFor(node.parentNode);
+ break;
+ }
+ return undefined;
+ };
+ ko.dataFor = function(node) {
+ var context = ko.contextFor(node);
+ return context ? context['$data'] : undefined;
+ };
+
+ ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
+ ko.exportSymbol('applyBindings', ko.applyBindings);
+ ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
+ ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
+ ko.exportSymbol('contextFor', ko.contextFor);
+ ko.exportSymbol('dataFor', ko.dataFor);
+})();
+var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
+ko.bindingHandlers['attr'] = {
+ 'update': function(element, valueAccessor, allBindingsAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor()) || {};
+ for (var attrName in value) {
+ if (typeof attrName == "string") {
+ var attrValue = ko.utils.unwrapObservable(value[attrName]);
+
+ // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
+ // when someProp is a "no value"-like value (strictly null, false, or undefined)
+ // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
+ var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
+ if (toRemove)
+ element.removeAttribute(attrName);
+
+ // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
+ // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
+ // but instead of figuring out the mode, we'll just set the attribute through the Javascript
+ // property for IE <= 8.
+ if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
+ attrName = attrHtmlToJavascriptMap[attrName];
+ if (toRemove)
+ element.removeAttribute(attrName);
+ else
+ element[attrName] = attrValue;
+ } else if (!toRemove) {
+ element.setAttribute(attrName, attrValue.toString());
+ }
+
+ // Treat "name" specially - although you can think of it as an attribute, it also needs
+ // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
+ // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
+ // entirely, and there's no strong reason to allow for such casing in HTML.
+ if (attrName === "name") {
+ ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
+ }
+ }
+ }
+ }
+};
+ko.bindingHandlers['checked'] = {
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
+ var updateHandler = function() {
+ var valueToWrite;
+ if (element.type == "checkbox") {
+ valueToWrite = element.checked;
+ } else if ((element.type == "radio") && (element.checked)) {
+ valueToWrite = element.value;
+ } else {
+ return; // "checked" binding only responds to checkboxes and selected radio buttons
+ }
+
+ var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
+ if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
+ // For checkboxes bound to an array, we add/remove the checkbox value to that array
+ // This works for both observable and non-observable arrays
+ var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
+ if (element.checked && (existingEntryIndex < 0))
+ modelValue.push(element.value);
+ else if ((!element.checked) && (existingEntryIndex >= 0))
+ modelValue.splice(existingEntryIndex, 1);
+ } else {
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
+ }
+ };
+ ko.utils.registerEventHandler(element, "click", updateHandler);
+
+ // IE 6 won't allow radio buttons to be selected unless they have a name
+ if ((element.type == "radio") && !element.name)
+ ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
+ },
+ 'update': function (element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+
+ if (element.type == "checkbox") {
+ if (value instanceof Array) {
+ // When bound to an array, the checkbox being checked represents its value being present in that array
+ element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
+ } else {
+ // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
+ element.checked = value;
+ }
+ } else if (element.type == "radio") {
+ element.checked = (element.value == value);
+ }
+ }
+};
+var classesWrittenByBindingKey = '__ko__cssValue';
+ko.bindingHandlers['css'] = {
+ 'update': function (element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ if (typeof value == "object") {
+ for (var className in value) {
+ var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
+ ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
+ }
+ } else {
+ value = String(value || ''); // Make sure we don't try to store or set a non-string value
+ ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
+ element[classesWrittenByBindingKey] = value;
+ ko.utils.toggleDomNodeCssClass(element, value, true);
+ }
+ }
+};
+ko.bindingHandlers['enable'] = {
+ 'update': function (element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ if (value && element.disabled)
+ element.removeAttribute("disabled");
+ else if ((!value) && (!element.disabled))
+ element.disabled = true;
+ }
+};
+
+ko.bindingHandlers['disable'] = {
+ 'update': function (element, valueAccessor) {
+ ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
+ }
+};
+// For certain common events (currently just 'click'), allow a simplified data-binding syntax
+// e.g. click:handler instead of the usual full-length event:{click:handler}
+function makeEventHandlerShortcut(eventName) {
+ ko.bindingHandlers[eventName] = {
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
+ var newValueAccessor = function () {
+ var result = {};
+ result[eventName] = valueAccessor();
+ return result;
+ };
+ return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
+ }
+ }
+}
+
+ko.bindingHandlers['event'] = {
+ 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
+ var eventsToHandle = valueAccessor() || {};
+ for(var eventNameOutsideClosure in eventsToHandle) {
+ (function() {
+ var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
+ if (typeof eventName == "string") {
+ ko.utils.registerEventHandler(element, eventName, function (event) {
+ var handlerReturnValue;
+ var handlerFunction = valueAccessor()[eventName];
+ if (!handlerFunction)
+ return;
+ var allBindings = allBindingsAccessor();
+
+ try {
+ // Take all the event args, and prefix with the viewmodel
+ var argsForHandler = ko.utils.makeArray(arguments);
+ argsForHandler.unshift(viewModel);
+ handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
+ } finally {
+ if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
+ if (event.preventDefault)
+ event.preventDefault();
+ else
+ event.returnValue = false;
+ }
+ }
+
+ var bubble = allBindings[eventName + 'Bubble'] !== false;
+ if (!bubble) {
+ event.cancelBubble = true;
+ if (event.stopPropagation)
+ event.stopPropagation();
+ }
+ });
+ }
+ })();
+ }
+ }
+};
+// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
+// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
+ko.bindingHandlers['foreach'] = {
+ makeTemplateValueAccessor: function(valueAccessor) {
+ return function() {
+ var modelValue = valueAccessor(),
+ unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
+
+ // If unwrappedValue is the array, pass in the wrapped value on its own
+ // The value will be unwrapped and tracked within the template binding
+ // (See https://github.com/SteveSanderson/knockout/issues/523)
+ if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
+ return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
+
+ // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
+ ko.utils.unwrapObservable(modelValue);
+ return {
+ 'foreach': unwrappedValue['data'],
+ 'as': unwrappedValue['as'],
+ 'includeDestroyed': unwrappedValue['includeDestroyed'],
+ 'afterAdd': unwrappedValue['afterAdd'],
+ 'beforeRemove': unwrappedValue['beforeRemove'],
+ 'afterRender': unwrappedValue['afterRender'],
+ 'beforeMove': unwrappedValue['beforeMove'],
+ 'afterMove': unwrappedValue['afterMove'],
+ 'templateEngine': ko.nativeTemplateEngine.instance
+ };
+ };
+ },
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
+ },
+ 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
+ }
+};
+ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
+ko.virtualElements.allowedBindings['foreach'] = true;
+var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
+ko.bindingHandlers['hasfocus'] = {
+ 'init': function(element, valueAccessor, allBindingsAccessor) {
+ var handleElementFocusChange = function(isFocused) {
+ // Where possible, ignore which event was raised and determine focus state using activeElement,
+ // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
+ // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
+ // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
+ // from calling 'blur()' on the element when it loses focus.
+ // Discussion at https://github.com/SteveSanderson/knockout/pull/352
+ element[hasfocusUpdatingProperty] = true;
+ var ownerDoc = element.ownerDocument;
+ if ("activeElement" in ownerDoc) {
+ isFocused = (ownerDoc.activeElement === element);
+ }
+ var modelValue = valueAccessor();
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
+ element[hasfocusUpdatingProperty] = false;
+ };
+ var handleElementFocusIn = handleElementFocusChange.bind(null, true);
+ var handleElementFocusOut = handleElementFocusChange.bind(null, false);
+
+ ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
+ ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
+ ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
+ ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
+ },
+ 'update': function(element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ if (!element[hasfocusUpdatingProperty]) {
+ value ? element.focus() : element.blur();
+ ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
+ }
+ }
+};
+ko.bindingHandlers['html'] = {
+ 'init': function() {
+ // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
+ return { 'controlsDescendantBindings': true };
+ },
+ 'update': function (element, valueAccessor) {
+ // setHtml will unwrap the value if needed
+ ko.utils.setHtml(element, valueAccessor());
+ }
+};
+var withIfDomDataKey = '__ko_withIfBindingData';
+// Makes a binding like with or if
+function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
+ ko.bindingHandlers[bindingKey] = {
+ 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ ko.utils.domData.set(element, withIfDomDataKey, {});
+ return { 'controlsDescendantBindings': true };
+ },
+ 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
+ dataValue = ko.utils.unwrapObservable(valueAccessor()),
+ shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
+ isFirstRender = !withIfData.savedNodes,
+ needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
+
+ if (needsRefresh) {
+ if (isFirstRender) {
+ withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
+ }
+
+ if (shouldDisplay) {
+ if (!isFirstRender) {
+ ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
+ }
+ ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
+ } else {
+ ko.virtualElements.emptyNode(element);
+ }
+
+ withIfData.didDisplayOnLastUpdate = shouldDisplay;
+ }
+ }
+ };
+ ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
+ ko.virtualElements.allowedBindings[bindingKey] = true;
+}
+
+// Construct the actual binding handlers
+makeWithIfBinding('if');
+makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
+makeWithIfBinding('with', true /* isWith */, false /* isNot */,
+ function(bindingContext, dataValue) {
+ return bindingContext['createChildContext'](dataValue);
+ }
+);
+function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
+ if (preferModelValue) {
+ if (modelValue !== ko.selectExtensions.readValue(element))
+ ko.selectExtensions.writeValue(element, modelValue);
+ }
+
+ // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
+ // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
+ // change the model value to match the dropdown.
+ if (modelValue !== ko.selectExtensions.readValue(element))
+ ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
+};
+
+ko.bindingHandlers['options'] = {
+ 'update': function (element, valueAccessor, allBindingsAccessor) {
+ if (ko.utils.tagNameLower(element) !== "select")
+ throw new Error("options binding applies only to SELECT elements");
+
+ var selectWasPreviouslyEmpty = element.length == 0;
+ var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
+ return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
+ }), function (node) {
+ return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
+ });
+ var previousScrollTop = element.scrollTop;
+
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ var selectedValue = element.value;
+
+ // Remove all existing <option>s.
+ // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
+ while (element.length > 0) {
+ ko.cleanNode(element.options[0]);
+ element.remove(0);
+ }
+
+ if (value) {
+ var allBindings = allBindingsAccessor(),
+ includeDestroyed = allBindings['optionsIncludeDestroyed'];
+
+ if (typeof value.length != "number")
+ value = [value];
+ if (allBindings['optionsCaption']) {
+ var option = document.createElement("option");
+ ko.utils.setHtml(option, allBindings['optionsCaption']);
+ ko.selectExtensions.writeValue(option, undefined);
+ element.appendChild(option);
+ }
+
+ for (var i = 0, j = value.length; i < j; i++) {
+ // Skip destroyed items
+ var arrayEntry = value[i];
+ if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
+ continue;
+
+ var option = document.createElement("option");
+
+ function applyToObject(object, predicate, defaultValue) {
+ var predicateType = typeof predicate;
+ if (predicateType == "function") // Given a function; run it against the data value
+ return predicate(object);
+ else if (predicateType == "string") // Given a string; treat it as a property name on the data value
+ return object[predicate];
+ else // Given no optionsText arg; use the data value itself
+ return defaultValue;
+ }
+
+ // Apply a value to the option element
+ var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
+ ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
+
+ // Apply some text to the option element
+ var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
+ ko.utils.setTextContent(option, optionText);
+
+ element.appendChild(option);
+ }
+
+ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
+ // That's why we first added them without selection. Now it's time to set the selection.
+ var newOptions = element.getElementsByTagName("option");
+ var countSelectionsRetained = 0;
+ for (var i = 0, j = newOptions.length; i < j; i++) {
+ if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
+ ko.utils.setOptionNodeSelectionState(newOptions[i], true);
+ countSelectionsRetained++;
+ }
+ }
+
+ element.scrollTop = previousScrollTop;
+
+ if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
+ // Ensure consistency between model value and selected option.
+ // If the dropdown is being populated for the first time here (or was otherwise previously empty),
+ // the dropdown selection state is meaningless, so we preserve the model value.
+ ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
+ }
+
+ // Workaround for IE9 bug
+ ko.utils.ensureSelectElementIsRenderedCorrectly(element);
+ }
+ }
+};
+ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
+ko.bindingHandlers['selectedOptions'] = {
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
+ ko.utils.registerEventHandler(element, "change", function () {
+ var value = valueAccessor(), valueToWrite = [];
+ ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
+ if (node.selected)
+ valueToWrite.push(ko.selectExtensions.readValue(node));
+ });
+ ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
+ });
+ },
+ 'update': function (element, valueAccessor) {
+ if (ko.utils.tagNameLower(element) != "select")
+ throw new Error("values binding applies only to SELECT elements");
+
+ var newValue = ko.utils.unwrapObservable(valueAccessor());
+ if (newValue && typeof newValue.length == "number") {
+ ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
+ var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
+ ko.utils.setOptionNodeSelectionState(node, isSelected);
+ });
+ }
+ }
+};
+ko.bindingHandlers['style'] = {
+ 'update': function (element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor() || {});
+ for (var styleName in value) {
+ if (typeof styleName == "string") {
+ var styleValue = ko.utils.unwrapObservable(value[styleName]);
+ element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
+ }
+ }
+ }
+};
+ko.bindingHandlers['submit'] = {
+ 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
+ if (typeof valueAccessor() != "function")
+ throw new Error("The value for a submit binding must be a function");
+ ko.utils.registerEventHandler(element, "submit", function (event) {
+ var handlerReturnValue;
+ var value = valueAccessor();
+ try { handlerReturnValue = value.call(viewModel, element); }
+ finally {
+ if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
+ if (event.preventDefault)
+ event.preventDefault();
+ else
+ event.returnValue = false;
+ }
+ }
+ });
+ }
+};
+ko.bindingHandlers['text'] = {
+ 'update': function (element, valueAccessor) {
+ ko.utils.setTextContent(element, valueAccessor());
+ }
+};
+ko.virtualElements.allowedBindings['text'] = true;
+ko.bindingHandlers['uniqueName'] = {
+ 'init': function (element, valueAccessor) {
+ if (valueAccessor()) {
+ var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
+ ko.utils.setElementName(element, name);
+ }
+ }
+};
+ko.bindingHandlers['uniqueName'].currentIndex = 0;
+ko.bindingHandlers['value'] = {
+ 'init': function (element, valueAccessor, allBindingsAccessor) {
+ // Always catch "change" event; possibly other events too if asked
+ var eventsToCatch = ["change"];
+ var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
+ var propertyChangedFired = false;
+ if (requestedEventsToCatch) {
+ if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
+ requestedEventsToCatch = [requestedEventsToCatch];
+ ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
+ eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
+ }
+
+ var valueUpdateHandler = function() {
+ propertyChangedFired = false;
+ var modelValue = valueAccessor();
+ var elementValue = ko.selectExtensions.readValue(element);
+ ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
+ }
+
+ // Workaround for https://github.com/SteveSanderson/knockout/issues/122
+ // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
+ var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
+ && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
+ if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
+ ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
+ ko.utils.registerEventHandler(element, "blur", function() {
+ if (propertyChangedFired) {
+ valueUpdateHandler();
+ }
+ });
+ }
+
+ ko.utils.arrayForEach(eventsToCatch, function(eventName) {
+ // The syntax "after<eventname>" means "run the handler asynchronously after the event"
+ // This is useful, for example, to catch "keydown" events after the browser has updated the control
+ // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
+ var handler = valueUpdateHandler;
+ if (ko.utils.stringStartsWith(eventName, "after")) {
+ handler = function() { setTimeout(valueUpdateHandler, 0) };
+ eventName = eventName.substring("after".length);
+ }
+ ko.utils.registerEventHandler(element, eventName, handler);
+ });
+ },
+ 'update': function (element, valueAccessor) {
+ var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
+ var newValue = ko.utils.unwrapObservable(valueAccessor());
+ var elementValue = ko.selectExtensions.readValue(element);
+ var valueHasChanged = (newValue != elementValue);
+
+ // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
+ // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
+ if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
+ valueHasChanged = true;
+
+ if (valueHasChanged) {
+ var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
+ applyValueAction();
+
+ // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
+ // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
+ // to apply the value as well.
+ var alsoApplyAsynchronously = valueIsSelectOption;
+ if (alsoApplyAsynchronously)
+ setTimeout(applyValueAction, 0);
+ }
+
+ // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
+ // because you're not allowed to have a model value that disagrees with a visible UI selection.
+ if (valueIsSelectOption && (element.length > 0))
+ ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
+ }
+};
+ko.bindingHandlers['visible'] = {
+ 'update': function (element, valueAccessor) {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ var isCurrentlyVisible = !(element.style.display == "none");
+ if (value && !isCurrentlyVisible)
+ element.style.display = "";
+ else if ((!value) && isCurrentlyVisible)
+ element.style.display = "none";
+ }
+};
+// 'click' is just a shorthand for the usual full-length event:{click:handler}
+makeEventHandlerShortcut('click');
+// If you want to make a custom template engine,
+//
+// [1] Inherit from this class (like ko.nativeTemplateEngine does)
+// [2] Override 'renderTemplateSource', supplying a function with this signature:
+//
+// function (templateSource, bindingContext, options) {
+// // - templateSource.text() is the text of the template you should render
+// // - bindingContext.$data is the data you should pass into the template
+// // - you might also want to make bindingContext.$parent, bindingContext.$parents,
+// // and bindingContext.$root available in the template too
+// // - options gives you access to any other properties set on "data-bind: { template: options }"
+// //
+// // Return value: an array of DOM nodes
+// }
+//
+// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
+//
+// function (script) {
+// // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
+// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
+// }
+//
+// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
+// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
+// and then you don't need to override 'createJavaScriptEvaluatorBlock'.
+
+ko.templateEngine = function () { };
+
+ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
+ throw new Error("Override renderTemplateSource");
+};
+
+ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
+ throw new Error("Override createJavaScriptEvaluatorBlock");
+};
+
+ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
+ // Named template
+ if (typeof template == "string") {
+ templateDocument = templateDocument || document;
+ var elem = templateDocument.getElementById(template);
+ if (!elem)
+ throw new Error("Cannot find template with ID " + template);
+ return new ko.templateSources.domElement(elem);
+ } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
+ // Anonymous template
+ return new ko.templateSources.anonymousTemplate(template);
+ } else
+ throw new Error("Unknown template type: " + template);
+};
+
+ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
+ var templateSource = this['makeTemplateSource'](template, templateDocument);
+ return this['renderTemplateSource'](templateSource, bindingContext, options);
+};
+
+ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
+ // Skip rewriting if requested
+ if (this['allowTemplateRewriting'] === false)
+ return true;
+ return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
+};
+
+ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
+ var templateSource = this['makeTemplateSource'](template, templateDocument);
+ var rewritten = rewriterCallback(templateSource['text']());
+ templateSource['text'](rewritten);
+ templateSource['data']("isRewritten", true);
+};
+
+ko.exportSymbol('templateEngine', ko.templateEngine);
+
+ko.templateRewriting = (function () {
+ var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
+ var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
+
+ function validateDataBindValuesForRewriting(keyValueArray) {
+ var allValidators = ko.expressionRewriting.bindingRewriteValidators;
+ for (var i = 0; i < keyValueArray.length; i++) {
+ var key = keyValueArray[i]['key'];
+ if (allValidators.hasOwnProperty(key)) {
+ var validator = allValidators[key];
+
+ if (typeof validator === "function") {
+ var possibleErrorMessage = validator(keyValueArray[i]['value']);
+ if (possibleErrorMessage)
+ throw new Error(possibleErrorMessage);
+ } else if (!validator) {
+ throw new Error("This template engine does not support the '" + key + "' binding within its templates");
+ }
+ }
+ }
+ }
+
+ function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
+ var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
+ validateDataBindValuesForRewriting(dataBindKeyValueArray);
+ var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
+
+ // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
+ // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
+ // extra indirection.
+ var applyBindingsToNextSiblingScript =
+ "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
+ return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
+ }
+
+ return {
+ ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
+ if (!templateEngine['isTemplateRewritten'](template, templateDocument))
+ templateEngine['rewriteTemplate'](template, function (htmlString) {
+ return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
+ }, templateDocument);
+ },
+
+ memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
+ return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
+ return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
+ }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
+ return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
+ });
+ },
+
+ applyMemoizedBindingsToNextSibling: function (bindings) {
+ return ko.memoization.memoize(function (domNode, bindingContext) {
+ if (domNode.nextSibling)
+ ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
+ });
+ }
+ }
+})();
+
+
+// Exported only because it has to be referenced by string lookup from within rewritten template
+ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
+(function() {
+ // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
+ // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
+ //
+ // Two are provided by default:
+ // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
+ // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
+ // without reading/writing the actual element text content, since it will be overwritten
+ // with the rendered template output.
+ // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
+ // Template sources need to have the following functions:
+ // text() - returns the template text from your storage location
+ // text(value) - writes the supplied template text to your storage location
+ // data(key) - reads values stored using data(key, value) - see below
+ // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
+ //
+ // Optionally, template sources can also have the following functions:
+ // nodes() - returns a DOM element containing the nodes of this template, where available
+ // nodes(value) - writes the given DOM element to your storage location
+ // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
+ // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
+ //
+ // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
+ // using and overriding "makeTemplateSource" to return an instance of your custom template source.
+
+ ko.templateSources = {};
+
+ // ---- ko.templateSources.domElement -----
+
+ ko.templateSources.domElement = function(element) {
+ this.domElement = element;
+ }
+
+ ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
+ var tagNameLower = ko.utils.tagNameLower(this.domElement),
+ elemContentsProperty = tagNameLower === "script" ? "text"
+ : tagNameLower === "textarea" ? "value"
+ : "innerHTML";
+
+ if (arguments.length == 0) {
+ return this.domElement[elemContentsProperty];
+ } else {
+ var valueToWrite = arguments[0];
+ if (elemContentsProperty === "innerHTML")
+ ko.utils.setHtml(this.domElement, valueToWrite);
+ else
+ this.domElement[elemContentsProperty] = valueToWrite;
+ }
+ };
+
+ ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
+ if (arguments.length === 1) {
+ return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
+ } else {
+ ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
+ }
+ };
+
+ // ---- ko.templateSources.anonymousTemplate -----
+ // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
+ // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
+ // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
+
+ var anonymousTemplatesDomDataKey = "__ko_anon_template__";
+ ko.templateSources.anonymousTemplate = function(element) {
+ this.domElement = element;
+ }
+ ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
+ ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
+ if (arguments.length == 0) {
+ var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
+ if (templateData.textData === undefined && templateData.containerData)
+ templateData.textData = templateData.containerData.innerHTML;
+ return templateData.textData;
+ } else {
+ var valueToWrite = arguments[0];
+ ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
+ }
+ };
+ ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
+ if (arguments.length == 0) {
+ var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
+ return templateData.containerData;
+ } else {
+ var valueToWrite = arguments[0];
+ ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
+ }
+ };
+
+ ko.exportSymbol('templateSources', ko.templateSources);
+ ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
+ ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
+})();
+(function () {
+ var _templateEngine;
+ ko.setTemplateEngine = function (templateEngine) {
+ if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
+ throw new Error("templateEngine must inherit from ko.templateEngine");
+ _templateEngine = templateEngine;
+ }
+
+ function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
+ var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
+ while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
+ nextInQueue = ko.virtualElements.nextSibling(node);
+ if (node.nodeType === 1 || node.nodeType === 8)
+ action(node);
+ }
+ }
+
+ function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
+ // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
+ // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
+ // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
+ // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
+ // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
+
+ if (continuousNodeArray.length) {
+ var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
+
+ // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
+ // whereas a regular applyBindings won't introduce new memoized nodes
+ invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
+ ko.applyBindings(bindingContext, node);
+ });
+ invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
+ ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
+ });
+ }
+ }
+
+ function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
+ return nodeOrNodeArray.nodeType ? nodeOrNodeArray
+ : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
+ : null;
+ }
+
+ function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
+ options = options || {};
+ var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
+ var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
+ var templateEngineToUse = (options['templateEngine'] || _templateEngine);
+ ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
+ var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
+
+ // Loosely check result is an array of DOM nodes
+ if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
+ throw new Error("Template engine must return an array of DOM nodes");
+
+ var haveAddedNodesToParent = false;
+ switch (renderMode) {
+ case "replaceChildren":
+ ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
+ haveAddedNodesToParent = true;
+ break;
+ case "replaceNode":
+ ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
+ haveAddedNodesToParent = true;
+ break;
+ case "ignoreTargetNode": break;
+ default:
+ throw new Error("Unknown renderMode: " + renderMode);
+ }
+
+ if (haveAddedNodesToParent) {
+ activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
+ if (options['afterRender'])
+ ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
+ }
+
+ return renderedNodesArray;
+ }
+
+ ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
+ options = options || {};
+ if ((options['templateEngine'] || _templateEngine) == undefined)
+ throw new Error("Set a template engine before calling renderTemplate");
+ renderMode = renderMode || "replaceChildren";
+
+ if (targetNodeOrNodeArray) {
+ var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
+
+ var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
+ var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
+
+ return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
+ function () {
+ // Ensure we've got a proper binding context to work with
+ var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
+ ? dataOrBindingContext
+ : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
+
+ // Support selecting template as a function of the data being rendered
+ var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
+
+ var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
+ if (renderMode == "replaceNode") {
+ targetNodeOrNodeArray = renderedNodesArray;
+ firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
+ }
+ },
+ null,
+ { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
+ );
+ } else {
+ // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
+ return ko.memoization.memoize(function (domNode) {
+ ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
+ });
+ }
+ };
+
+ ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
+ // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
+ // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
+ var arrayItemContext;
+
+ // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
+ var executeTemplateForArrayItem = function (arrayValue, index) {
+ // Support selecting template as a function of the data being rendered
+ arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
+ arrayItemContext['$index'] = index;
+ var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
+ return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
+ }
+
+ // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
+ var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
+ activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
+ if (options['afterRender'])
+ options['afterRender'](addedNodesArray, arrayValue);
+ };
+
+ return ko.dependentObservable(function () {
+ var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
+ if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
+ unwrappedArray = [unwrappedArray];
+
+ // Filter out any entries marked as destroyed
+ var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
+ return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
+ });
+
+ // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
+ // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
+ ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
+
+ }, null, { disposeWhenNodeIsRemoved: targetNode });
+ };
+
+ var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
+ function disposeOldComputedAndStoreNewOne(element, newComputed) {
+ var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
+ if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
+ oldComputed.dispose();
+ ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
+ }
+
+ ko.bindingHandlers['template'] = {
+ 'init': function(element, valueAccessor) {
+ // Support anonymous templates
+ var bindingValue = ko.utils.unwrapObservable(valueAccessor());
+ if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
+ // It's an anonymous template - store the element contents, then clear the element
+ var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
+ container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
+ new ko.templateSources.anonymousTemplate(element)['nodes'](container);
+ }
+ return { 'controlsDescendantBindings': true };
+ },
+ 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ var templateName = ko.utils.unwrapObservable(valueAccessor()),
+ options = {},
+ shouldDisplay = true,
+ dataValue,
+ templateComputed = null;
+
+ if (typeof templateName != "string") {
+ options = templateName;
+ templateName = options['name'];
+
+ // Support "if"/"ifnot" conditions
+ if ('if' in options)
+ shouldDisplay = ko.utils.unwrapObservable(options['if']);
+ if (shouldDisplay && 'ifnot' in options)
+ shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
+
+ dataValue = ko.utils.unwrapObservable(options['data']);
+ }
+
+ if ('foreach' in options) {
+ // Render once for each data point (treating data set as empty if shouldDisplay==false)
+ var dataArray = (shouldDisplay && options['foreach']) || [];
+ templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
+ } else if (!shouldDisplay) {
+ ko.virtualElements.emptyNode(element);
+ } else {
+ // Render once for this single data point (or use the viewModel if no data was provided)
+ var innerBindingContext = ('data' in options) ?
+ bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
+ bindingContext; // Given no explicit 'data' value, we retain the same binding context
+ templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
+ }
+
+ // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
+ disposeOldComputedAndStoreNewOne(element, templateComputed);
+ }
+ };
+
+ // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
+ ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
+ var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
+
+ if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
+ return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
+
+ if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
+ return null; // Named templates can be rewritten, so return "no error"
+ return "This template engine does not support anonymous templates nested within its templates";
+ };
+
+ ko.virtualElements.allowedBindings['template'] = true;
+})();
+
+ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
+ko.exportSymbol('renderTemplate', ko.renderTemplate);
+
+ko.utils.compareArrays = (function () {
+ var statusNotInOld = 'added', statusNotInNew = 'deleted';
+
+ // Simple calculation based on Levenshtein distance.
+ function compareArrays(oldArray, newArray, dontLimitMoves) {
+ oldArray = oldArray || [];
+ newArray = newArray || [];
+
+ if (oldArray.length <= newArray.length)
+ return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
+ else
+ return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
+ }
+
+ function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
+ var myMin = Math.min,
+ myMax = Math.max,
+ editDistanceMatrix = [],
+ smlIndex, smlIndexMax = smlArray.length,
+ bigIndex, bigIndexMax = bigArray.length,
+ compareRange = (bigIndexMax - smlIndexMax) || 1,
+ maxDistance = smlIndexMax + bigIndexMax + 1,
+ thisRow, lastRow,
+ bigIndexMaxForRow, bigIndexMinForRow;
+
+ for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
+ lastRow = thisRow;
+ editDistanceMatrix.push(thisRow = []);
+ bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
+ bigIndexMinForRow = myMax(0, smlIndex - 1);
+ for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
+ if (!bigIndex)
+ thisRow[bigIndex] = smlIndex + 1;
+ else if (!smlIndex) // Top row - transform empty array into new array via additions
+ thisRow[bigIndex] = bigIndex + 1;
+ else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
+ thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
+ else {
+ var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
+ var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
+ thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
+ }
+ }
+ }
+
+ var editScript = [], meMinusOne, notInSml = [], notInBig = [];
+ for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
+ meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
+ if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
+ notInSml.push(editScript[editScript.length] = { // added
+ 'status': statusNotInSml,
+ 'value': bigArray[--bigIndex],
+ 'index': bigIndex });
+ } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
+ notInBig.push(editScript[editScript.length] = { // deleted
+ 'status': statusNotInBig,
+ 'value': smlArray[--smlIndex],
+ 'index': smlIndex });
+ } else {
+ editScript.push({
+ 'status': "retained",
+ 'value': bigArray[--bigIndex] });
+ --smlIndex;
+ }
+ }
+
+ if (notInSml.length && notInBig.length) {
+ // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
+ // smlIndexMax keeps the time complexity of this algorithm linear.
+ var limitFailedCompares = smlIndexMax * 10, failedCompares,
+ a, d, notInSmlItem, notInBigItem;
+ // Go through the items that have been added and deleted and try to find matches between them.
+ for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
+ for (d = 0; notInBigItem = notInBig[d]; d++) {
+ if (notInSmlItem['value'] === notInBigItem['value']) {
+ notInSmlItem['moved'] = notInBigItem['index'];
+ notInBigItem['moved'] = notInSmlItem['index'];
+ notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
+ failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
+ break;
+ }
+ }
+ failedCompares += d;
+ }
+ }
+ return editScript.reverse();
+ }
+
+ return compareArrays;
+})();
+
+ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
+
+(function () {
+ // Objective:
+ // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
+ // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
+ // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
+ // so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
+ // previously mapped - retain those nodes, and just insert/delete other ones
+
+ // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
+ // You can use this, for example, to activate bindings on those nodes.
+
+ function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
+ // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
+ // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
+ // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
+ // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
+ // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
+ //
+ // Rules:
+ // [A] Any leading nodes that aren't in the document any more should be ignored
+ // These most likely correspond to memoization nodes that were already removed during binding
+ // See https://github.com/SteveSanderson/knockout/pull/440
+ // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
+ // have already been removed, and include any nodes that have been inserted among the previous collection
+
+ // Rule [A]
+ while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
+ contiguousNodeArray.splice(0, 1);
+
+ // Rule [B]
+ if (contiguousNodeArray.length > 1) {
+ // Build up the actual new contiguous node set
+ var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
+ while (current !== last) {
+ current = current.nextSibling;
+ if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
+ return;
+ newContiguousSet.push(current);
+ }
+
+ // ... then mutate the input array to match this.
+ // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
+ Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
+ }
+ return contiguousNodeArray;
+ }
+
+ function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
+ // Map this array value inside a dependentObservable so we re-map when any dependency changes
+ var mappedNodes = [];
+ var dependentObservable = ko.dependentObservable(function() {
+ var newMappedNodes = mapping(valueToMap, index) || [];
+
+ // On subsequent evaluations, just replace the previously-inserted DOM nodes
+ if (mappedNodes.length > 0) {
+ ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
+ if (callbackAfterAddingNodes)
+ ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
+ }
+
+ // Replace the contents of the mappedNodes array, thereby updating the record
+ // of which nodes would be deleted if valueToMap was itself later removed
+ mappedNodes.splice(0, mappedNodes.length);
+ ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
+ }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
+ return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
+ }
+
+ var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
+
+ ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
+ // Compare the provided array against the previous one
+ array = array || [];
+ options = options || {};
+ var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
+ var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
+ var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
+ var editScript = ko.utils.compareArrays(lastArray, array);
+
+ // Build the new mapping result
+ var newMappingResult = [];
+ var lastMappingResultIndex = 0;
+ var newMappingResultIndex = 0;
+
+ var nodesToDelete = [];
+ var itemsToProcess = [];
+ var itemsForBeforeRemoveCallbacks = [];
+ var itemsForMoveCallbacks = [];
+ var itemsForAfterAddCallbacks = [];
+ var mapData;
+
+ function itemMovedOrRetained(editScriptIndex, oldPosition) {
+ mapData = lastMappingResult[oldPosition];
+ if (newMappingResultIndex !== oldPosition)
+ itemsForMoveCallbacks[editScriptIndex] = mapData;
+ // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
+ mapData.indexObservable(newMappingResultIndex++);
+ fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
+ newMappingResult.push(mapData);
+ itemsToProcess.push(mapData);
+ }
+
+ function callCallback(callback, items) {
+ if (callback) {
+ for (var i = 0, n = items.length; i < n; i++) {
+ if (items[i]) {
+ ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
+ callback(node, i, items[i].arrayEntry);
+ });
+ }
+ }
+ }
+ }
+
+ for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
+ movedIndex = editScriptItem['moved'];
+ switch (editScriptItem['status']) {
+ case "deleted":
+ if (movedIndex === undefined) {
+ mapData = lastMappingResult[lastMappingResultIndex];
+
+ // Stop tracking changes to the mapping for these nodes
+ if (mapData.dependentObservable)
+ mapData.dependentObservable.dispose();
+
+ // Queue these nodes for later removal
+ nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
+ if (options['beforeRemove']) {
+ itemsForBeforeRemoveCallbacks[i] = mapData;
+ itemsToProcess.push(mapData);
+ }
+ }
+ lastMappingResultIndex++;
+ break;
+
+ case "retained":
+ itemMovedOrRetained(i, lastMappingResultIndex++);
+ break;
+
+ case "added":
+ if (movedIndex !== undefined) {
+ itemMovedOrRetained(i, movedIndex);
+ } else {
+ mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
+ newMappingResult.push(mapData);
+ itemsToProcess.push(mapData);
+ if (!isFirstExecution)
+ itemsForAfterAddCallbacks[i] = mapData;
+ }
+ break;
+ }
+ }
+
+ // Call beforeMove first before any changes have been made to the DOM
+ callCallback(options['beforeMove'], itemsForMoveCallbacks);
+
+ // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
+ ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
+
+ // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
+ for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
+ // Get nodes for newly added items
+ if (!mapData.mappedNodes)
+ ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
+
+ // Put nodes in the right place if they aren't there already
+ for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
+ if (node !== nextNode)
+ ko.virtualElements.insertAfter(domNode, node, lastNode);
+ }
+
+ // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
+ if (!mapData.initialized && callbackAfterAddingNodes) {
+ callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
+ mapData.initialized = true;
+ }
+ }
+
+ // If there's a beforeRemove callback, call it after reordering.
+ // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
+ // some sort of animation, which is why we first reorder the nodes that will be removed. If the
+ // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
+ // Perhaps we'll make that change in the future if this scenario becomes more common.
+ callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
+
+ // Finally call afterMove and afterAdd callbacks
+ callCallback(options['afterMove'], itemsForMoveCallbacks);
+ callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
+
+ // Store a copy of the array items we just considered so we can difference it next time
+ ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
+ }
+})();
+
+ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
+ko.nativeTemplateEngine = function () {
+ this['allowTemplateRewriting'] = false;
+}
+
+ko.nativeTemplateEngine.prototype = new ko.templateEngine();
+ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
+ var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
+ templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
+ templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
+
+ if (templateNodes) {
+ return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
+ } else {
+ var templateText = templateSource['text']();
+ return ko.utils.parseHtmlFragment(templateText);
+ }
+};
+
+ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
+ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
+
+ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
+(function() {
+ ko.jqueryTmplTemplateEngine = function () {
+ // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
+ // doesn't expose a version number, so we have to infer it.
+ // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
+ // which KO internally refers to as version "2", so older versions are no longer detected.
+ var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
+ if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
+ return 0;
+ // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
+ try {
+ if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
+ // Since 1.0.0pre, custom tags should append markup to an array called "__"
+ return 2; // Final version of jquery.tmpl
+ }
+ } catch(ex) { /* Apparently not the version we were looking for */ }
+
+ return 1; // Any older version that we don't support
+ })();
+
+ function ensureHasReferencedJQueryTemplates() {
+ if (jQueryTmplVersion < 2)
+ throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
+ }
+
+ function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
+ return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
+ }
+
+ this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
+ options = options || {};
+ ensureHasReferencedJQueryTemplates();
+
+ // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
+ var precompiled = templateSource['data']('precompiled');
+ if (!precompiled) {
+ var templateText = templateSource['text']() || "";
+ // Wrap in "with($whatever.koBindingContext) { ... }"
+ templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
+
+ precompiled = jQuery['template'](null, templateText);
+ templateSource['data']('precompiled', precompiled);
+ }
+
+ var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
+ var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
+
+ var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
+ resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
+
+ jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
+ return resultNodes;
+ };
+
+ this['createJavaScriptEvaluatorBlock'] = function(script) {
+ return "{{ko_code ((function() { return " + script + " })()) }}";
+ };
+
+ this['addTemplate'] = function(templateName, templateMarkup) {
+ document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
+ };
+
+ if (jQueryTmplVersion > 0) {
+ jQuery['tmpl']['tag']['ko_code'] = {
+ open: "__.push($1 || '');"
+ };
+ jQuery['tmpl']['tag']['ko_with'] = {
+ open: "with($1) {",
+ close: "} "
+ };
+ }
+ };
+
+ ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
+
+ // Use this one by default *only if jquery.tmpl is referenced*
+ var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
+ if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
+ ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
+
+ ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
+})();
+});
+})(window,document,navigator,window["jQuery"]);
+})();
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-sortable.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-sortable.js
new file mode 100644
index 000000000..f4259528b
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout-sortable.js
@@ -0,0 +1,285 @@
+//knockout-sortable 0.6.6 | (c) 2012 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
+(function(factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD anonymous module
+ define(["knockout", "jquery", "jquery.ui"], factory);
+ } else {
+ // No module loader (plain <script> tag) - put directly in global namespace
+ factory(window.ko, jQuery);
+ }
+})(function(ko, $, undefined) {
+ var ITEMKEY = "ko_sortItem",
+ LISTKEY = "ko_sortList",
+ PARENTKEY = "ko_parentList",
+ DRAGKEY = "ko_dragItem";
+
+ //internal afterRender that adds meta-data to children
+ var addMetaDataAfterRender = function(elements, data) {
+ ko.utils.arrayForEach(elements, function(element) {
+ if (element.nodeType === 1) {
+ ko.utils.domData.set(element, ITEMKEY, data);
+ ko.utils.domData.set(element, PARENTKEY, ko.utils.domData.get(element.parentNode, LISTKEY));
+ }
+ });
+ };
+
+ //prepare the proper options for the template binding
+ var prepareTemplateOptions = function(valueAccessor, dataName) {
+ var result = {},
+ options = ko.utils.unwrapObservable(valueAccessor()),
+ actualAfterRender;
+
+ //build our options to pass to the template engine
+ if (options.data) {
+ result[dataName] = options.data;
+ result.name = options.template;
+ } else {
+ result[dataName] = valueAccessor();
+ }
+
+ ko.utils.arrayForEach(["afterAdd", "afterRender", "beforeRemove", "includeDestroyed", "templateEngine", "templateOptions"], function (option) {
+ result[option] = options[option] || ko.bindingHandlers.sortable[option];
+ });
+
+ //use an afterRender function to add meta-data
+ if (dataName === "foreach") {
+ if (result.afterRender) {
+ //wrap the existing function, if it was passed
+ actualAfterRender = result.afterRender;
+ result.afterRender = function(element, data) {
+ addMetaDataAfterRender.call(data, element, data);
+ actualAfterRender.call(data, element, data);
+ };
+ } else {
+ result.afterRender = addMetaDataAfterRender;
+ }
+ }
+
+ //return options to pass to the template binding
+ return result;
+ };
+
+ //connect items with observableArrays
+ ko.bindingHandlers.sortable = {
+ init: function(element, valueAccessor, allBindingsAccessor, data, context) {
+ var $element = $(element),
+ value = ko.utils.unwrapObservable(valueAccessor()) || {},
+ templateOptions = prepareTemplateOptions(valueAccessor, "foreach"),
+ sortable = {},
+ startActual, updateActual;
+
+ //remove leading/trailing text nodes from anonymous templates
+ ko.utils.arrayForEach(element.childNodes, function(node) {
+ if (node && node.nodeType === 3) {
+ node.parentNode.removeChild(node);
+ }
+ });
+
+ //build a new object that has the global options with overrides from the binding
+ $.extend(true, sortable, ko.bindingHandlers.sortable);
+ if (value.options && sortable.options) {
+ ko.utils.extend(sortable.options, value.options);
+ delete value.options;
+ }
+ ko.utils.extend(sortable, value);
+
+ //if allowDrop is an observable or a function, then execute it in a computed observable
+ if (sortable.connectClass && (ko.isObservable(sortable.allowDrop) || typeof sortable.allowDrop == "function")) {
+ ko.computed({
+ read: function() {
+ var value = ko.utils.unwrapObservable(sortable.allowDrop),
+ shouldAdd = typeof value == "function" ? value.call(this, templateOptions.foreach) : value;
+ ko.utils.toggleDomNodeCssClass(element, sortable.connectClass, shouldAdd);
+ },
+ disposeWhenNodeIsRemoved: element
+ }, this);
+ } else {
+ ko.utils.toggleDomNodeCssClass(element, sortable.connectClass, sortable.allowDrop);
+ }
+
+ //wrap the template binding
+ ko.bindingHandlers.template.init(element, function() { return templateOptions; }, allBindingsAccessor, data, context);
+
+ //keep a reference to start/update functions that might have been passed in
+ startActual = sortable.options.start;
+ updateActual = sortable.options.update;
+
+ //initialize sortable binding after template binding has rendered in update function
+ setTimeout(function() {
+ var dragItem;
+ $element.sortable(ko.utils.extend(sortable.options, {
+ start: function(event, ui) {
+ //make sure that fields have a chance to update model
+ ui.item.find("input:focus").change();
+ if (startActual) {
+ startActual.apply(this, arguments);
+ }
+ },
+ receive: function(event, ui) {
+ dragItem = ko.utils.domData.get(ui.item[0], DRAGKEY);
+ if (dragItem && dragItem.clone) {
+ dragItem = dragItem.clone();
+ }
+ },
+ update: function(event, ui) {
+ var sourceParent, targetParent, targetIndex, i, targetUnwrapped, arg,
+ el = ui.item[0],
+ item = ko.utils.domData.get(el, ITEMKEY) || dragItem;
+
+ dragItem = null;
+
+ if (this === ui.item.parent()[0] && item) {
+ //identify parents
+ sourceParent = ko.utils.domData.get(el, PARENTKEY);
+ targetParent = ko.utils.domData.get(el.parentNode, LISTKEY);
+ targetIndex = ko.utils.arrayIndexOf(ui.item.parent().children(), el);
+
+ //take destroyed items into consideration
+ if (!templateOptions.includeDestroyed) {
+ if(targetParent){
+ targetUnwrapped = $.isFunction(targetParent)?targetParent():targetParent;
+ for (i = 0; i < targetIndex; i++) {
+ //add one for every destroyed item we find before the targetIndex in the target array
+ if (targetUnwrapped[i] && targetUnwrapped[i]._destroy) {
+ targetIndex++;
+ }
+ }
+ }
+ }
+
+ if (sortable.beforeMove || sortable.afterMove) {
+ arg = {
+ item: item,
+ sourceParent: sourceParent,
+ sourceParentNode: sourceParent && el.parentNode,
+ sourceIndex: sourceParent && sourceParent.indexOf(item),
+ targetParent: targetParent,
+ targetIndex: targetIndex,
+ cancelDrop: false
+ };
+ }
+
+ if (sortable.beforeMove) {
+ sortable.beforeMove.call(this, arg, event, ui);
+ if (arg.cancelDrop) {
+ //call cancel on the correct list
+ if (arg.sourceParent) {
+ $(arg.sourceParent === arg.targetParent ? this : ui.sender).sortable('cancel');
+ }
+ //for a draggable item just remove the element
+ else {
+ $(el).remove();
+ }
+
+ return;
+ }
+ }
+
+ if (targetIndex >= 0) {
+ if (sourceParent) {
+ if( $.isFunction(sourceParent.remove)) sourceParent.remove(item);
+ }
+
+ targetParent.splice(targetIndex, 0, item);
+ }
+
+ //rendering is handled by manipulating the observableArray; ignore dropped element
+ ko.utils.domData.set(el, ITEMKEY, null);
+ ui.item.remove();
+
+ //allow binding to accept a function to execute after moving the item
+ if (sortable.afterMove) {
+ sortable.afterMove.call(this, arg, event, ui);
+ }
+ }
+
+ if (updateActual) {
+ updateActual.apply(this, arguments);
+ }
+ },
+ connectWith: sortable.connectClass ? "." + sortable.connectClass : false
+ }));
+
+ //handle enabling/disabling sorting
+ if (sortable.isEnabled !== undefined) {
+ ko.computed({
+ read: function() {
+ $element.sortable(ko.utils.unwrapObservable(sortable.isEnabled) ? "enable" : "disable");
+ },
+ disposeWhenNodeIsRemoved: element
+ });
+ }
+ }, 0);
+
+ //handle disposal
+ ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
+ $element.sortable("destroy");
+ });
+
+ return { 'controlsDescendantBindings': true };
+ },
+ update: function(element, valueAccessor, allBindingsAccessor, data, context) {
+ var templateOptions = prepareTemplateOptions(valueAccessor, "foreach");
+
+ //attach meta-data
+ ko.utils.domData.set(element, LISTKEY, templateOptions.foreach);
+
+ //call template binding's update with correct options
+ ko.bindingHandlers.template.update(element, function() { return templateOptions; }, allBindingsAccessor, data, context);
+ },
+ connectClass: 'ko_container',
+ allowDrop: true,
+ afterMove: null,
+ beforeMove: null,
+ options: {}
+ };
+
+ //create a draggable that is appropriate for dropping into a sortable
+ ko.bindingHandlers.draggable = {
+ init: function(element, valueAccessor, allBindingsAccessor, data, context) {
+ var value = ko.utils.unwrapObservable(valueAccessor()) || {},
+ options = value.options || {},
+ draggableOptions = ko.utils.extend({}, ko.bindingHandlers.draggable.options),
+ templateOptions = prepareTemplateOptions(valueAccessor, "data"),
+ connectClass = value.connectClass || ko.bindingHandlers.draggable.connectClass,
+ isEnabled = value.isEnabled !== undefined ? value.isEnabled : ko.bindingHandlers.draggable.isEnabled;
+
+ value = value.data || value;
+
+ //set meta-data
+ ko.utils.domData.set(element, DRAGKEY, value);
+
+ //override global options with override options passed in
+ ko.utils.extend(draggableOptions, options);
+
+ //setup connection to a sortable
+
+ draggableOptions.connectToSortable = connectClass ? "." + connectClass : false;
+
+ //initialize draggable
+ $(element).draggable(draggableOptions);
+
+ //handle enabling/disabling sorting
+ if (isEnabled !== undefined) {
+ ko.computed({
+ read: function() {
+ $(element).draggable(ko.utils.unwrapObservable(isEnabled) ? "enable" : "disable");
+ },
+ disposeWhenNodeIsRemoved: element
+ });
+ }
+
+ return ko.bindingHandlers.template.init(element, function() { return templateOptions; }, allBindingsAccessor, data, context);
+ },
+ update: function(element, valueAccessor, allBindingsAccessor, data, context) {
+ var templateOptions = prepareTemplateOptions(valueAccessor, "data");
+
+ return ko.bindingHandlers.template.update(element, function() { return templateOptions; }, allBindingsAccessor, data, context);
+ },
+ connectClass: ko.bindingHandlers.sortable.connectClass,
+ options: {
+ helper: "clone"
+ }
+ };
+
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout.simpleGrid.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout.simpleGrid.js
new file mode 100644
index 000000000..f9fbafc23
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/knockout.simpleGrid.js
@@ -0,0 +1,86 @@
+// This is an example of one possible way to make a reusable component (or 'plugin'), consisting of:
+// * A view model class, which gives a way to configure the component and to interact with it (e.g., by exposing currentPageIndex as an observable, external code can change the page index)
+// * A custom binding (ko.bindingHandlers.simpleGrid in this example) so a developer can place instances of it into the DOM
+// - in this example, the custom binding works by rendering some predefined templates using the ko.jqueryTmplTemplateEngine template engine
+//
+// There are loads of ways this grid example could be expanded. For example,
+// * Letting the developer override the templates used to create the table header, table body, and page links div
+// * Adding a "sort by clicking column headers" option
+// * Creating some API to fetch table data using Ajax requests
+// ... etc
+
+
+
+(function(factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD anonymous module
+ define("knockout.simpleGrid",["jquery","knockout","utils","i18n"], factory);
+ } else {
+ // No module loader (plain <script> tag) - put directly in global namespace
+ factory(window.ko, jQuery);
+ }
+})(function ($,ko,utils,i18n) {
+
+
+ ko.simpleGrid = {
+ // Defines a view model class you can use to populate a grid
+ viewModel: function (configuration) {
+ this.data = configuration.data;
+ this.currentPageIndex = ko.observable(0);
+ this.pageSize = configuration.pageSize || 5;
+ this.columns = configuration.columns;
+
+ this.itemsOnCurrentPage = ko.computed(function () {
+ var startIndex = this.pageSize * this.currentPageIndex();
+ return this.data.slice(startIndex, startIndex + this.pageSize);
+ }, this);
+
+ this.maxPageIndex = ko.computed(function () {
+ return Math.ceil(ko.utils.unwrapObservable(this.data).length / this.pageSize);
+ }, this);
+ this.i18n=function(key){
+ return $.i18n.prop(key);
+ };
+ this.gridUpdateCallBack = configuration.gridUpdateCallBack;
+ this.pageLinksUpdateCallBack = configuration.pageLinksUpdateCallBack;
+
+ }
+ };
+
+ // Templates used to render the grid
+ var templateEngine = new ko.jqueryTmplTemplateEngine();
+
+
+ // The "simpleGrid" binding
+ ko.bindingHandlers.simpleGrid = {
+ // This method is called to initialize the node, and will also be called again if you change what the grid is bound to
+ update: function (element, viewModelAccessor, allBindingsAccessor) {
+ var viewModel = viewModelAccessor(), allBindings = allBindingsAccessor();
+
+ // Empty the element
+ while(element.firstChild) {
+ ko.removeNode(element.firstChild);
+ }
+
+ // Allow the default templates to be overridden
+ var gridTemplateName = allBindings.simpleGridTemplate || "ko_usersGrid_grid",
+ pageLinksTemplateName = allBindings.simpleGridPagerTemplate || "ko_simpleGrid_pageLinks";
+
+ // Render the main grid
+ var gridContainer = element.appendChild(document.createElement("DIV"));
+ ko.renderTemplate(gridTemplateName, viewModel, { templateEngine: templateEngine }, gridContainer, "replaceNode")
+ .subscribe(viewModel.gridUpdateCallBack?viewModel.gridUpdateCallBack:function(){});
+
+ if (viewModel.gridUpdateCallBack) viewModel.gridUpdateCallBack();
+
+ // Render the page links
+ var pageLinksContainer = $("#"+allBindings.pageLinksId).get(0);
+ var renderedTemplate = ko.renderTemplate(pageLinksTemplateName, viewModel, { templateEngine: templateEngine }, pageLinksContainer, "replaceNode");
+ if (renderedTemplate.subscribe){
+ renderedTemplate.subscribe(viewModel.pageLinksUpdateCallBack?viewModel.pageLinksUpdateCallBack:function(){});
+ }
+ if (viewModel.pageLinksUpdateCallBack) viewModel.pageLinksUpdateCallBack();
+ }
+ };
+})
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/order.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/order.js
new file mode 100644
index 000000000..5edd5ce03
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/order.js
@@ -0,0 +1,189 @@
+/**
+ * @license RequireJS order 1.0.5 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/requirejs for details
+ */
+/*jslint nomen: false, plusplus: false, strict: false */
+/*global require: false, define: false, window: false, document: false,
+ setTimeout: false */
+
+//Specify that requirejs optimizer should wrap this code in a closure that
+//maps the namespaced requirejs API to non-namespaced local variables.
+/*requirejs namespace: true */
+
+(function () {
+
+ //Sadly necessary browser inference due to differences in the way
+ //that browsers load and execute dynamically inserted javascript
+ //and whether the script/cache method works when ordered execution is
+ //desired. Currently, Gecko and Opera do not load/fire onload for scripts with
+ //type="script/cache" but they execute injected scripts in order
+ //unless the 'async' flag is present.
+ //However, this is all changing in latest browsers implementing HTML5
+ //spec. With compliant browsers .async true by default, and
+ //if false, then it will execute in order. Favor that test first for forward
+ //compatibility.
+ var testScript = typeof document !== "undefined" &&
+ typeof window !== "undefined" &&
+ document.createElement("script"),
+
+ supportsInOrderExecution = testScript && (testScript.async ||
+ ((window.opera &&
+ Object.prototype.toString.call(window.opera) === "[object Opera]") ||
+ //If Firefox 2 does not have to be supported, then
+ //a better check may be:
+ //('mozIsLocallyAvailable' in window.navigator)
+ ("MozAppearance" in document.documentElement.style))),
+
+ //This test is true for IE browsers, which will load scripts but only
+ //execute them once the script is added to the DOM.
+ supportsLoadSeparateFromExecute = testScript &&
+ testScript.readyState === 'uninitialized',
+
+ readyRegExp = /^(complete|loaded)$/,
+ cacheWaiting = [],
+ cached = {},
+ scriptNodes = {},
+ scriptWaiting = [];
+
+ //Done with the test script.
+ testScript = null;
+
+ //Callback used by the type="script/cache" callback that indicates a script
+ //has finished downloading.
+ function scriptCacheCallback(evt) {
+ var node = evt.currentTarget || evt.srcElement, i,
+ moduleName, resource;
+
+ if (evt.type === "load" || readyRegExp.test(node.readyState)) {
+ //Pull out the name of the module and the context.
+ moduleName = node.getAttribute("data-requiremodule");
+
+ //Mark this cache request as loaded
+ cached[moduleName] = true;
+
+ //Find out how many ordered modules have loaded
+ for (i = 0; (resource = cacheWaiting[i]); i++) {
+ if (cached[resource.name]) {
+ resource.req([resource.name], resource.onLoad);
+ } else {
+ //Something in the ordered list is not loaded,
+ //so wait.
+ break;
+ }
+ }
+
+ //If just loaded some items, remove them from cacheWaiting.
+ if (i > 0) {
+ cacheWaiting.splice(0, i);
+ }
+
+ //Remove this script tag from the DOM
+ //Use a setTimeout for cleanup because some older IE versions vomit
+ //if removing a script node while it is being evaluated.
+ setTimeout(function () {
+ node.parentNode.removeChild(node);
+ }, 15);
+ }
+ }
+
+ /**
+ * Used for the IE case, where fetching is done by creating script element
+ * but not attaching it to the DOM. This function will be called when that
+ * happens so it can be determined when the node can be attached to the
+ * DOM to trigger its execution.
+ */
+ function onFetchOnly(node) {
+ var i, loadedNode, resourceName;
+
+ //Mark this script as loaded.
+ node.setAttribute('data-orderloaded', 'loaded');
+
+ //Cycle through waiting scripts. If the matching node for them
+ //is loaded, and is in the right order, add it to the DOM
+ //to execute the script.
+ for (i = 0; (resourceName = scriptWaiting[i]); i++) {
+ loadedNode = scriptNodes[resourceName];
+ if (loadedNode &&
+ loadedNode.getAttribute('data-orderloaded') === 'loaded') {
+ delete scriptNodes[resourceName];
+ require.addScriptToDom(loadedNode);
+ } else {
+ break;
+ }
+ }
+
+ //If just loaded some items, remove them from waiting.
+ if (i > 0) {
+ scriptWaiting.splice(0, i);
+ }
+ }
+
+ define({
+ version: '1.0.5',
+
+ load: function (name, req, onLoad, config) {
+ var hasToUrl = !!req.nameToUrl,
+ url, node, context;
+
+ //If no nameToUrl, then probably a build with a loader that
+ //does not support it, and all modules are inlined.
+ if (!hasToUrl) {
+ req([name], onLoad);
+ return;
+ }
+
+ url = req.nameToUrl(name, null);
+
+ //Make sure the async attribute is not set for any pathway involving
+ //this script.
+ require.s.skipAsync[url] = true;
+ if (supportsInOrderExecution || config.isBuild) {
+ //Just a normal script tag append, but without async attribute
+ //on the script.
+ req([name], onLoad);
+ } else if (supportsLoadSeparateFromExecute) {
+ //Just fetch the URL, but do not execute it yet. The
+ //non-standards IE case. Really not so nice because it is
+ //assuming and touching requrejs internals. OK though since
+ //ordered execution should go away after a long while.
+ context = require.s.contexts._;
+
+ if (!context.urlFetched[url] && !context.loaded[name]) {
+ //Indicate the script is being fetched.
+ context.urlFetched[url] = true;
+
+ //Stuff from require.load
+ require.resourcesReady(false);
+ context.scriptCount += 1;
+
+ //Fetch the script now, remember it.
+ node = require.attach(url, context, name, null, null, onFetchOnly);
+ scriptNodes[name] = node;
+ scriptWaiting.push(name);
+ }
+
+ //Do a normal require for it, once it loads, use it as return
+ //value.
+ req([name], onLoad);
+ } else {
+ //Credit to LABjs author Kyle Simpson for finding that scripts
+ //with type="script/cache" allow scripts to be downloaded into
+ //browser cache but not executed. Use that
+ //so that subsequent addition of a real type="text/javascript"
+ //tag will cause the scripts to be executed immediately in the
+ //correct order.
+ if (req.specified(name)) {
+ req([name], onLoad);
+ } else {
+ cacheWaiting.push({
+ name: name,
+ req: req,
+ onLoad: onLoad
+ });
+ require.attach(url, null, name, scriptCacheCallback, "script/cache");
+ }
+ }
+ }
+ });
+}());
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/prettify.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/prettify.js
new file mode 100644
index 000000000..037c26da4
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/prettify.js
@@ -0,0 +1,1477 @@
+// Copyright (C) 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/**
+ * @fileoverview
+ * some functions for browser-side pretty printing of code contained in html.
+ *
+ * <p>
+ * For a fairly comprehensive set of languages see the
+ * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a>
+ * file that came with this source. At a minimum, the lexer should work on a
+ * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
+ * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk
+ * and a subset of Perl, but, because of commenting conventions, doesn't work on
+ * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
+ * <p>
+ * Usage: <ol>
+ * <li> include this source file in an html page via
+ * {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
+ * <li> define style rules. See the example page for examples.
+ * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
+ * {@code class=prettyprint.}
+ * You can also use the (html deprecated) {@code <xmp>} tag, but the pretty
+ * printer needs to do more substantial DOM manipulations to support that, so
+ * some css styles may not be preserved.
+ * </ol>
+ * That's it. I wanted to keep the API as simple as possible, so there's no
+ * need to specify which language the code is in, but if you wish, you can add
+ * another class to the {@code <pre>} or {@code <code>} element to specify the
+ * language, as in {@code <pre class="prettyprint lang-java">}. Any class that
+ * starts with "lang-" followed by a file extension, specifies the file type.
+ * See the "lang-*.js" files in this directory for code that implements
+ * per-language file handlers.
+ * <p>
+ * Change log:<br>
+ * cbeust, 2006/08/22
+ * <blockquote>
+ * Java annotations (start with "@") are now captured as literals ("lit")
+ * </blockquote>
+ * @requires console
+ */
+
+// JSLint declarations
+/*global console, document, navigator, setTimeout, window */
+
+/**
+ * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
+ * UI events.
+ * If set to {@code false}, {@code prettyPrint()} is synchronous.
+ */
+window['PR_SHOULD_USE_CONTINUATION'] = true;
+
+(function () {
+ // Keyword lists for various languages.
+ // We use things that coerce to strings to make them compact when minified
+ // and to defeat aggressive optimizers that fold large string constants.
+ var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
+ var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," +
+ "double,enum,extern,float,goto,int,long,register,short,signed,sizeof," +
+ "static,struct,switch,typedef,union,unsigned,void,volatile"];
+ var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
+ "new,operator,private,protected,public,this,throw,true,try,typeof"];
+ var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
+ "concept,concept_map,const_cast,constexpr,decltype," +
+ "dynamic_cast,explicit,export,friend,inline,late_check," +
+ "mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast," +
+ "template,typeid,typename,using,virtual,where"];
+ var JAVA_KEYWORDS = [COMMON_KEYWORDS,
+ "abstract,boolean,byte,extends,final,finally,implements,import," +
+ "instanceof,null,native,package,strictfp,super,synchronized,throws," +
+ "transient"];
+ var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
+ "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
+ "fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock," +
+ "object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed," +
+ "stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];
+ var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
+ "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
+ "true,try,unless,until,when,while,yes";
+ var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
+ "debugger,eval,export,function,get,null,set,undefined,var,with," +
+ "Infinity,NaN"];
+ var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
+ "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
+ "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
+ var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
+ "elif,except,exec,finally,from,global,import,in,is,lambda," +
+ "nonlocal,not,or,pass,print,raise,try,with,yield," +
+ "False,True,None"];
+ var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
+ "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
+ "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
+ "BEGIN,END"];
+ var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
+ "function,in,local,set,then,until"];
+ var ALL_KEYWORDS = [
+ CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS +
+ PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
+ var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;
+
+ // token style names. correspond to css classes
+ /**
+ * token style for a string literal
+ * @const
+ */
+ var PR_STRING = 'str';
+ /**
+ * token style for a keyword
+ * @const
+ */
+ var PR_KEYWORD = 'kwd';
+ /**
+ * token style for a comment
+ * @const
+ */
+ var PR_COMMENT = 'com';
+ /**
+ * token style for a type
+ * @const
+ */
+ var PR_TYPE = 'typ';
+ /**
+ * token style for a literal value. e.g. 1, null, true.
+ * @const
+ */
+ var PR_LITERAL = 'lit';
+ /**
+ * token style for a punctuation string.
+ * @const
+ */
+ var PR_PUNCTUATION = 'pun';
+ /**
+ * token style for a punctuation string.
+ * @const
+ */
+ var PR_PLAIN = 'pln';
+
+ /**
+ * token style for an sgml tag.
+ * @const
+ */
+ var PR_TAG = 'tag';
+ /**
+ * token style for a markup declaration such as a DOCTYPE.
+ * @const
+ */
+ var PR_DECLARATION = 'dec';
+ /**
+ * token style for embedded source.
+ * @const
+ */
+ var PR_SOURCE = 'src';
+ /**
+ * token style for an sgml attribute name.
+ * @const
+ */
+ var PR_ATTRIB_NAME = 'atn';
+ /**
+ * token style for an sgml attribute value.
+ * @const
+ */
+ var PR_ATTRIB_VALUE = 'atv';
+
+ /**
+ * A class that indicates a section of markup that is not code, e.g. to allow
+ * embedding of line numbers within code listings.
+ * @const
+ */
+ var PR_NOCODE = 'nocode';
+
+
+
+/**
+ * A set of tokens that can precede a regular expression literal in
+ * javascript
+ * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
+ * has the full list, but I've removed ones that might be problematic when
+ * seen in languages that don't support regular expression literals.
+ *
+ * <p>Specifically, I've removed any keywords that can't precede a regexp
+ * literal in a syntactically legal javascript program, and I've removed the
+ * "in" keyword since it's not a keyword in many languages, and might be used
+ * as a count of inches.
+ *
+ * <p>The link a above does not accurately describe EcmaScript rules since
+ * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
+ * very well in practice.
+ *
+ * @private
+ * @const
+ */
+var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
+
+// CAVEAT: this does not properly handle the case where a regular
+// expression immediately follows another since a regular expression may
+// have flags for case-sensitivity and the like. Having regexp tokens
+// adjacent is not valid in any language I'm aware of, so I'm punting.
+// TODO: maybe style special characters inside a regexp as punctuation.
+
+
+ /**
+ * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
+ * matches the union of the sets of strings matched by the input RegExp.
+ * Since it matches globally, if the input strings have a start-of-input
+ * anchor (/^.../), it is ignored for the purposes of unioning.
+ * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
+ * @return {RegExp} a global regex.
+ */
+ function combinePrefixPatterns(regexs) {
+ var capturedGroupIndex = 0;
+
+ var needToFoldCase = false;
+ var ignoreCase = false;
+ for (var i = 0, n = regexs.length; i < n; ++i) {
+ var regex = regexs[i];
+ if (regex.ignoreCase) {
+ ignoreCase = true;
+ } else if (/[a-z]/i.test(regex.source.replace(
+ /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
+ needToFoldCase = true;
+ ignoreCase = false;
+ break;
+ }
+ }
+
+ var escapeCharToCodeUnit = {
+ 'b': 8,
+ 't': 9,
+ 'n': 0xa,
+ 'v': 0xb,
+ 'f': 0xc,
+ 'r': 0xd
+ };
+
+ function decodeEscape(charsetPart) {
+ var cc0 = charsetPart.charCodeAt(0);
+ if (cc0 !== 92 /* \\ */) {
+ return cc0;
+ }
+ var c1 = charsetPart.charAt(1);
+ cc0 = escapeCharToCodeUnit[c1];
+ if (cc0) {
+ return cc0;
+ } else if ('0' <= c1 && c1 <= '7') {
+ return parseInt(charsetPart.substring(1), 8);
+ } else if (c1 === 'u' || c1 === 'x') {
+ return parseInt(charsetPart.substring(2), 16);
+ } else {
+ return charsetPart.charCodeAt(1);
+ }
+ }
+
+ function encodeEscape(charCode) {
+ if (charCode < 0x20) {
+ return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
+ }
+ var ch = String.fromCharCode(charCode);
+ if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
+ ch = '\\' + ch;
+ }
+ return ch;
+ }
+
+ function caseFoldCharset(charSet) {
+ var charsetParts = charSet.substring(1, charSet.length - 1).match(
+ new RegExp(
+ '\\\\u[0-9A-Fa-f]{4}'
+ + '|\\\\x[0-9A-Fa-f]{2}'
+ + '|\\\\[0-3][0-7]{0,2}'
+ + '|\\\\[0-7]{1,2}'
+ + '|\\\\[\\s\\S]'
+ + '|-'
+ + '|[^-\\\\]',
+ 'g'));
+ var groups = [];
+ var ranges = [];
+ var inverse = charsetParts[0] === '^';
+ for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
+ var p = charsetParts[i];
+ if (/\\[bdsw]/i.test(p)) { // Don't muck with named groups.
+ groups.push(p);
+ } else {
+ var start = decodeEscape(p);
+ var end;
+ if (i + 2 < n && '-' === charsetParts[i + 1]) {
+ end = decodeEscape(charsetParts[i + 2]);
+ i += 2;
+ } else {
+ end = start;
+ }
+ ranges.push([start, end]);
+ // If the range might intersect letters, then expand it.
+ // This case handling is too simplistic.
+ // It does not deal with non-latin case folding.
+ // It works for latin source code identifiers though.
+ if (!(end < 65 || start > 122)) {
+ if (!(end < 65 || start > 90)) {
+ ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
+ }
+ if (!(end < 97 || start > 122)) {
+ ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
+ }
+ }
+ }
+ }
+
+ // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
+ // -> [[1, 12], [14, 14], [16, 17]]
+ ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); });
+ var consolidatedRanges = [];
+ var lastRange = [NaN, NaN];
+ for (var i = 0; i < ranges.length; ++i) {
+ var range = ranges[i];
+ if (range[0] <= lastRange[1] + 1) {
+ lastRange[1] = Math.max(lastRange[1], range[1]);
+ } else {
+ consolidatedRanges.push(lastRange = range);
+ }
+ }
+
+ var out = ['['];
+ if (inverse) { out.push('^'); }
+ out.push.apply(out, groups);
+ for (var i = 0; i < consolidatedRanges.length; ++i) {
+ var range = consolidatedRanges[i];
+ out.push(encodeEscape(range[0]));
+ if (range[1] > range[0]) {
+ if (range[1] + 1 > range[0]) { out.push('-'); }
+ out.push(encodeEscape(range[1]));
+ }
+ }
+ out.push(']');
+ return out.join('');
+ }
+
+ function allowAnywhereFoldCaseAndRenumberGroups(regex) {
+ // Split into character sets, escape sequences, punctuation strings
+ // like ('(', '(?:', ')', '^'), and runs of characters that do not
+ // include any of the above.
+ var parts = regex.source.match(
+ new RegExp(
+ '(?:'
+ + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set
+ + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape
+ + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape
+ + '|\\\\[0-9]+' // a back-reference or octal escape
+ + '|\\\\[^ux0-9]' // other escape sequence
+ + '|\\(\\?[:!=]' // start of a non-capturing group
+ + '|[\\(\\)\\^]' // start/emd of a group, or line start
+ + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters
+ + ')',
+ 'g'));
+ var n = parts.length;
+
+ // Maps captured group numbers to the number they will occupy in
+ // the output or to -1 if that has not been determined, or to
+ // undefined if they need not be capturing in the output.
+ var capturedGroups = [];
+
+ // Walk over and identify back references to build the capturedGroups
+ // mapping.
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ var p = parts[i];
+ if (p === '(') {
+ // groups are 1-indexed, so max group index is count of '('
+ ++groupIndex;
+ } else if ('\\' === p.charAt(0)) {
+ var decimalValue = +p.substring(1);
+ if (decimalValue && decimalValue <= groupIndex) {
+ capturedGroups[decimalValue] = -1;
+ }
+ }
+ }
+
+ // Renumber groups and reduce capturing groups to non-capturing groups
+ // where possible.
+ for (var i = 1; i < capturedGroups.length; ++i) {
+ if (-1 === capturedGroups[i]) {
+ capturedGroups[i] = ++capturedGroupIndex;
+ }
+ }
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ var p = parts[i];
+ if (p === '(') {
+ ++groupIndex;
+ if (capturedGroups[groupIndex] === undefined) {
+ parts[i] = '(?:';
+ }
+ } else if ('\\' === p.charAt(0)) {
+ var decimalValue = +p.substring(1);
+ if (decimalValue && decimalValue <= groupIndex) {
+ parts[i] = '\\' + capturedGroups[groupIndex];
+ }
+ }
+ }
+
+ // Remove any prefix anchors so that the output will match anywhere.
+ // ^^ really does mean an anchored match though.
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
+ }
+
+ // Expand letters to groups to handle mixing of case-sensitive and
+ // case-insensitive patterns if necessary.
+ if (regex.ignoreCase && needToFoldCase) {
+ for (var i = 0; i < n; ++i) {
+ var p = parts[i];
+ var ch0 = p.charAt(0);
+ if (p.length >= 2 && ch0 === '[') {
+ parts[i] = caseFoldCharset(p);
+ } else if (ch0 !== '\\') {
+ // TODO: handle letters in numeric escapes.
+ parts[i] = p.replace(
+ /[a-zA-Z]/g,
+ function (ch) {
+ var cc = ch.charCodeAt(0);
+ return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
+ });
+ }
+ }
+ }
+
+ return parts.join('');
+ }
+
+ var rewritten = [];
+ for (var i = 0, n = regexs.length; i < n; ++i) {
+ var regex = regexs[i];
+ if (regex.global || regex.multiline) { throw new Error('' + regex); }
+ rewritten.push(
+ '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
+ }
+
+ return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
+ }
+
+
+ /**
+ * Split markup into a string of source code and an array mapping ranges in
+ * that string to the text nodes in which they appear.
+ *
+ * <p>
+ * The HTML DOM structure:</p>
+ * <pre>
+ * (Element "p"
+ * (Element "b"
+ * (Text "print ")) ; #1
+ * (Text "'Hello '") ; #2
+ * (Element "br") ; #3
+ * (Text " + 'World';")) ; #4
+ * </pre>
+ * <p>
+ * corresponds to the HTML
+ * {@code <p><b>print </b>'Hello '<br> + 'World';</p>}.</p>
+ *
+ * <p>
+ * It will produce the output:</p>
+ * <pre>
+ * {
+ * sourceCode: "print 'Hello '\n + 'World';",
+ * // 1 2
+ * // 012345678901234 5678901234567
+ * spans: [0, #1, 6, #2, 14, #3, 15, #4]
+ * }
+ * </pre>
+ * <p>
+ * where #1 is a reference to the {@code "print "} text node above, and so
+ * on for the other text nodes.
+ * </p>
+ *
+ * <p>
+ * The {@code} spans array is an array of pairs. Even elements are the start
+ * indices of substrings, and odd elements are the text nodes (or BR elements)
+ * that contain the text for those substrings.
+ * Substrings continue until the next index or the end of the source.
+ * </p>
+ *
+ * @param {Node} node an HTML DOM subtree containing source-code.
+ * @return {Object} source code and the text nodes in which they occur.
+ */
+ function extractSourceSpans(node) {
+ var nocode = /(?:^|\s)nocode(?:\s|$)/;
+
+ var chunks = [];
+ var length = 0;
+ var spans = [];
+ var k = 0;
+
+ var whitespace;
+ if (node.currentStyle) {
+ whitespace = node.currentStyle.whiteSpace;
+ } else if (window.getComputedStyle) {
+ whitespace = document.defaultView.getComputedStyle(node, null)
+ .getPropertyValue('white-space');
+ }
+ var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
+
+ function walk(node) {
+ switch (node.nodeType) {
+ case 1: // Element
+ if (nocode.test(node.className)) { return; }
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ walk(child);
+ }
+ var nodeName = node.nodeName;
+ if ('BR' === nodeName || 'LI' === nodeName) {
+ chunks[k] = '\n';
+ spans[k << 1] = length++;
+ spans[(k++ << 1) | 1] = node;
+ }
+ break;
+ case 3: case 4: // Text
+ var text = node.nodeValue;
+ if (text.length) {
+ if (!isPreformatted) {
+ text = text.replace(/[ \t\r\n]+/g, ' ');
+ } else {
+ text = text.replace(/\r\n?/g, '\n'); // Normalize newlines.
+ }
+ // TODO: handle tabs here?
+ chunks[k] = text;
+ spans[k << 1] = length;
+ length += text.length;
+ spans[(k++ << 1) | 1] = node;
+ }
+ break;
+ }
+ }
+
+ walk(node);
+
+ return {
+ sourceCode: chunks.join('').replace(/\n$/, ''),
+ spans: spans
+ };
+ }
+
+
+ /**
+ * Apply the given language handler to sourceCode and add the resulting
+ * decorations to out.
+ * @param {number} basePos the index of sourceCode within the chunk of source
+ * whose decorations are already present on out.
+ */
+ function appendDecorations(basePos, sourceCode, langHandler, out) {
+ if (!sourceCode) { return; }
+ var job = {
+ sourceCode: sourceCode,
+ basePos: basePos
+ };
+ langHandler(job);
+ out.push.apply(out, job.decorations);
+ }
+
+ var notWs = /\S/;
+
+ /**
+ * Given an element, if it contains only one child element and any text nodes
+ * it contains contain only space characters, return the sole child element.
+ * Otherwise returns undefined.
+ * <p>
+ * This is meant to return the CODE element in {@code <pre><code ...>} when
+ * there is a single child element that contains all the non-space textual
+ * content, but not to return anything where there are multiple child elements
+ * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
+ * is textual content.
+ */
+ function childContentWrapper(element) {
+ var wrapper = undefined;
+ for (var c = element.firstChild; c; c = c.nextSibling) {
+ var type = c.nodeType;
+ wrapper = (type === 1) // Element Node
+ ? (wrapper ? element : c)
+ : (type === 3) // Text Node
+ ? (notWs.test(c.nodeValue) ? element : wrapper)
+ : wrapper;
+ }
+ return wrapper === element ? undefined : wrapper;
+ }
+
+ /** Given triples of [style, pattern, context] returns a lexing function,
+ * The lexing function interprets the patterns to find token boundaries and
+ * returns a decoration list of the form
+ * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
+ * where index_n is an index into the sourceCode, and style_n is a style
+ * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to
+ * all characters in sourceCode[index_n-1:index_n].
+ *
+ * The stylePatterns is a list whose elements have the form
+ * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
+ *
+ * Style is a style constant like PR_PLAIN, or can be a string of the
+ * form 'lang-FOO', where FOO is a language extension describing the
+ * language of the portion of the token in $1 after pattern executes.
+ * E.g., if style is 'lang-lisp', and group 1 contains the text
+ * '(hello (world))', then that portion of the token will be passed to the
+ * registered lisp handler for formatting.
+ * The text before and after group 1 will be restyled using this decorator
+ * so decorators should take care that this doesn't result in infinite
+ * recursion. For example, the HTML lexer rule for SCRIPT elements looks
+ * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match
+ * '<script>foo()<\/script>', which would cause the current decorator to
+ * be called with '<script>' which would not match the same rule since
+ * group 1 must not be empty, so it would be instead styled as PR_TAG by
+ * the generic tag rule. The handler registered for the 'js' extension would
+ * then be called with 'foo()', and finally, the current decorator would
+ * be called with '<\/script>' which would not match the original rule and
+ * so the generic tag rule would identify it as a tag.
+ *
+ * Pattern must only match prefixes, and if it matches a prefix, then that
+ * match is considered a token with the same style.
+ *
+ * Context is applied to the last non-whitespace, non-comment token
+ * recognized.
+ *
+ * Shortcut is an optional string of characters, any of which, if the first
+ * character, gurantee that this pattern and only this pattern matches.
+ *
+ * @param {Array} shortcutStylePatterns patterns that always start with
+ * a known character. Must have a shortcut string.
+ * @param {Array} fallthroughStylePatterns patterns that will be tried in
+ * order if the shortcut ones fail. May have shortcuts.
+ *
+ * @return {function (Object)} a
+ * function that takes source code and returns a list of decorations.
+ */
+ function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
+ var shortcuts = {};
+ var tokenizer;
+ (function () {
+ var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
+ var allRegexs = [];
+ var regexKeys = {};
+ for (var i = 0, n = allPatterns.length; i < n; ++i) {
+ var patternParts = allPatterns[i];
+ var shortcutChars = patternParts[3];
+ if (shortcutChars) {
+ for (var c = shortcutChars.length; --c >= 0;) {
+ shortcuts[shortcutChars.charAt(c)] = patternParts;
+ }
+ }
+ var regex = patternParts[1];
+ var k = '' + regex;
+ if (!regexKeys.hasOwnProperty(k)) {
+ allRegexs.push(regex);
+ regexKeys[k] = null;
+ }
+ }
+ allRegexs.push(/[\0-\uffff]/);
+ tokenizer = combinePrefixPatterns(allRegexs);
+ })();
+
+ var nPatterns = fallthroughStylePatterns.length;
+
+ /**
+ * Lexes job.sourceCode and produces an output array job.decorations of
+ * style classes preceded by the position at which they start in
+ * job.sourceCode in order.
+ *
+ * @param {Object} job an object like <pre>{
+ * sourceCode: {string} sourceText plain text,
+ * basePos: {int} position of job.sourceCode in the larger chunk of
+ * sourceCode.
+ * }</pre>
+ */
+ var decorate = function (job) {
+ var sourceCode = job.sourceCode, basePos = job.basePos;
+ /** Even entries are positions in source in ascending order. Odd enties
+ * are style markers (e.g., PR_COMMENT) that run from that position until
+ * the end.
+ * @type {Array.<number|string>}
+ */
+ var decorations = [basePos, PR_PLAIN];
+ var pos = 0; // index into sourceCode
+ var tokens = sourceCode.match(tokenizer) || [];
+ var styleCache = {};
+
+ for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
+ var token = tokens[ti];
+ var style = styleCache[token];
+ var match = void 0;
+
+ var isEmbedded;
+ if (typeof style === 'string') {
+ isEmbedded = false;
+ } else {
+ var patternParts = shortcuts[token.charAt(0)];
+ if (patternParts) {
+ match = token.match(patternParts[1]);
+ style = patternParts[0];
+ } else {
+ for (var i = 0; i < nPatterns; ++i) {
+ patternParts = fallthroughStylePatterns[i];
+ match = token.match(patternParts[1]);
+ if (match) {
+ style = patternParts[0];
+ break;
+ }
+ }
+
+ if (!match) { // make sure that we make progress
+ style = PR_PLAIN;
+ }
+ }
+
+ isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
+ if (isEmbedded && !(match && typeof match[1] === 'string')) {
+ isEmbedded = false;
+ style = PR_SOURCE;
+ }
+
+ if (!isEmbedded) { styleCache[token] = style; }
+ }
+
+ var tokenStart = pos;
+ pos += token.length;
+
+ if (!isEmbedded) {
+ decorations.push(basePos + tokenStart, style);
+ } else { // Treat group 1 as an embedded block of source code.
+ var embeddedSource = match[1];
+ var embeddedSourceStart = token.indexOf(embeddedSource);
+ var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
+ if (match[2]) {
+ // If embeddedSource can be blank, then it would match at the
+ // beginning which would cause us to infinitely recurse on the
+ // entire token, so we catch the right context in match[2].
+ embeddedSourceEnd = token.length - match[2].length;
+ embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
+ }
+ var lang = style.substring(5);
+ // Decorate the left of the embedded source
+ appendDecorations(
+ basePos + tokenStart,
+ token.substring(0, embeddedSourceStart),
+ decorate, decorations);
+ // Decorate the embedded source
+ appendDecorations(
+ basePos + tokenStart + embeddedSourceStart,
+ embeddedSource,
+ langHandlerForExtension(lang, embeddedSource),
+ decorations);
+ // Decorate the right of the embedded section
+ appendDecorations(
+ basePos + tokenStart + embeddedSourceEnd,
+ token.substring(embeddedSourceEnd),
+ decorate, decorations);
+ }
+ }
+ job.decorations = decorations;
+ };
+ return decorate;
+ }
+
+ /** returns a function that produces a list of decorations from source text.
+ *
+ * This code treats ", ', and ` as string delimiters, and \ as a string
+ * escape. It does not recognize perl's qq() style strings.
+ * It has no special handling for double delimiter escapes as in basic, or
+ * the tripled delimiters used in python, but should work on those regardless
+ * although in those cases a single string literal may be broken up into
+ * multiple adjacent string literals.
+ *
+ * It recognizes C, C++, and shell style comments.
+ *
+ * @param {Object} options a set of optional parameters.
+ * @return {function (Object)} a function that examines the source code
+ * in the input job and builds the decoration list.
+ */
+ function sourceDecorator(options) {
+ var shortcutStylePatterns = [], fallthroughStylePatterns = [];
+ if (options['tripleQuotedStrings']) {
+ // '''multi-line-string''', 'single-line-string', and double-quoted
+ shortcutStylePatterns.push(
+ [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
+ null, '\'"']);
+ } else if (options['multiLineStrings']) {
+ // 'multi-line-string', "multi-line-string"
+ shortcutStylePatterns.push(
+ [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
+ null, '\'"`']);
+ } else {
+ // 'single-line-string', "single-line-string"
+ shortcutStylePatterns.push(
+ [PR_STRING,
+ /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
+ null, '"\'']);
+ }
+ if (options['verbatimStrings']) {
+ // verbatim-string-literal production from the C# grammar. See issue 93.
+ fallthroughStylePatterns.push(
+ [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
+ }
+ var hc = options['hashComments'];
+ if (hc) {
+ if (options['cStyleComments']) {
+ if (hc > 1) { // multiline hash comments
+ shortcutStylePatterns.push(
+ [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
+ } else {
+ // Stop C preprocessor declarations at an unclosed open comment
+ shortcutStylePatterns.push(
+ [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
+ null, '#']);
+ }
+ fallthroughStylePatterns.push(
+ [PR_STRING,
+ /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
+ null]);
+ } else {
+ shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
+ }
+ }
+ if (options['cStyleComments']) {
+ fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
+ fallthroughStylePatterns.push(
+ [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
+ }
+ if (options['regexLiterals']) {
+ /**
+ * @const
+ */
+ var REGEX_LITERAL = (
+ // A regular expression literal starts with a slash that is
+ // not followed by * or / so that it is not confused with
+ // comments.
+ '/(?=[^/*])'
+ // and then contains any number of raw characters,
+ + '(?:[^/\\x5B\\x5C]'
+ // escape sequences (\x5C),
+ + '|\\x5C[\\s\\S]'
+ // or non-nesting character sets (\x5B\x5D);
+ + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
+ // finally closed by a /.
+ + '/');
+ fallthroughStylePatterns.push(
+ ['lang-regex',
+ new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
+ ]);
+ }
+
+ var types = options['types'];
+ if (types) {
+ fallthroughStylePatterns.push([PR_TYPE, types]);
+ }
+
+ var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
+ if (keywords.length) {
+ fallthroughStylePatterns.push(
+ [PR_KEYWORD,
+ new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
+ null]);
+ }
+
+ shortcutStylePatterns.push([PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']);
+ fallthroughStylePatterns.push(
+ // TODO(mikesamuel): recognize non-latin letters and numerals in idents
+ [PR_LITERAL, /^@[a-z_$][a-z_$@0-9]*/i, null],
+ [PR_TYPE, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
+ [PR_PLAIN, /^[a-z_$][a-z_$@0-9]*/i, null],
+ [PR_LITERAL,
+ new RegExp(
+ '^(?:'
+ // A hex number
+ + '0x[a-f0-9]+'
+ // or an octal or decimal number,
+ + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
+ // possibly in scientific notation
+ + '(?:e[+\\-]?\\d+)?'
+ + ')'
+ // with an optional modifier like UL for unsigned long
+ + '[a-z]*', 'i'),
+ null, '0123456789'],
+ // Don't treat escaped quotes in bash as starting strings. See issue 144.
+ [PR_PLAIN, /^\\[\s\S]?/, null],
+ [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null]);
+
+ return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
+ }
+
+ var decorateSource = sourceDecorator({
+ 'keywords': ALL_KEYWORDS,
+ 'hashComments': true,
+ 'cStyleComments': true,
+ 'multiLineStrings': true,
+ 'regexLiterals': true
+ });
+
+ /**
+ * Given a DOM subtree, wraps it in a list, and puts each line into its own
+ * list item.
+ *
+ * @param {Node} node modified in place. Its content is pulled into an
+ * HTMLOListElement, and each line is moved into a separate list item.
+ * This requires cloning elements, so the input might not have unique
+ * IDs after numbering.
+ */
+ function numberLines(node, opt_startLineNum) {
+ var nocode = /(?:^|\s)nocode(?:\s|$)/;
+ var lineBreak = /\r\n?|\n/;
+
+ var document = node.ownerDocument;
+
+ var whitespace;
+ if (node.currentStyle) {
+ whitespace = node.currentStyle.whiteSpace;
+ } else if (window.getComputedStyle) {
+ whitespace = document.defaultView.getComputedStyle(node, null)
+ .getPropertyValue('white-space');
+ }
+ // If it's preformatted, then we need to split lines on line breaks
+ // in addition to <BR>s.
+ var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
+
+ var li = document.createElement('LI');
+ while (node.firstChild) {
+ li.appendChild(node.firstChild);
+ }
+ // An array of lines. We split below, so this is initialized to one
+ // un-split line.
+ var listItems = [li];
+
+ function walk(node) {
+ switch (node.nodeType) {
+ case 1: // Element
+ if (nocode.test(node.className)) { break; }
+ if ('BR' === node.nodeName) {
+ breakAfter(node);
+ // Discard the <BR> since it is now flush against a </LI>.
+ if (node.parentNode) {
+ node.parentNode.removeChild(node);
+ }
+ } else {
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ walk(child);
+ }
+ }
+ break;
+ case 3: case 4: // Text
+ if (isPreformatted) {
+ var text = node.nodeValue;
+ var match = text.match(lineBreak);
+ if (match) {
+ var firstLine = text.substring(0, match.index);
+ node.nodeValue = firstLine;
+ var tail = text.substring(match.index + match[0].length);
+ if (tail) {
+ var parent = node.parentNode;
+ parent.insertBefore(
+ document.createTextNode(tail), node.nextSibling);
+ }
+ breakAfter(node);
+ if (!firstLine) {
+ // Don't leave blank text nodes in the DOM.
+ node.parentNode.removeChild(node);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ // Split a line after the given node.
+ function breakAfter(lineEndNode) {
+ // If there's nothing to the right, then we can skip ending the line
+ // here, and move root-wards since splitting just before an end-tag
+ // would require us to create a bunch of empty copies.
+ while (!lineEndNode.nextSibling) {
+ lineEndNode = lineEndNode.parentNode;
+ if (!lineEndNode) { return; }
+ }
+
+ function breakLeftOf(limit, copy) {
+ // Clone shallowly if this node needs to be on both sides of the break.
+ var rightSide = copy ? limit.cloneNode(false) : limit;
+ var parent = limit.parentNode;
+ if (parent) {
+ // We clone the parent chain.
+ // This helps us resurrect important styling elements that cross lines.
+ // E.g. in <i>Foo<br>Bar</i>
+ // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
+ var parentClone = breakLeftOf(parent, 1);
+ // Move the clone and everything to the right of the original
+ // onto the cloned parent.
+ var next = limit.nextSibling;
+ parentClone.appendChild(rightSide);
+ for (var sibling = next; sibling; sibling = next) {
+ next = sibling.nextSibling;
+ parentClone.appendChild(sibling);
+ }
+ }
+ return rightSide;
+ }
+
+ var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
+
+ // Walk the parent chain until we reach an unattached LI.
+ for (var parent;
+ // Check nodeType since IE invents document fragments.
+ (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
+ copiedListItem = parent;
+ }
+ // Put it on the list of lines for later processing.
+ listItems.push(copiedListItem);
+ }
+
+ // Split lines while there are lines left to split.
+ for (var i = 0; // Number of lines that have been split so far.
+ i < listItems.length; // length updated by breakAfter calls.
+ ++i) {
+ walk(listItems[i]);
+ }
+
+ // Make sure numeric indices show correctly.
+ if (opt_startLineNum === (opt_startLineNum|0)) {
+ listItems[0].setAttribute('value', opt_startLineNum);
+ }
+
+ var ol = document.createElement('OL');
+ ol.className = 'linenums';
+ var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
+ for (var i = 0, n = listItems.length; i < n; ++i) {
+ li = listItems[i];
+ // Stick a class on the LIs so that stylesheets can
+ // color odd/even rows, or any other row pattern that
+ // is co-prime with 10.
+ li.className = 'L' + ((i + offset) % 10);
+ if (!li.firstChild) {
+ li.appendChild(document.createTextNode('\xA0'));
+ }
+ ol.appendChild(li);
+ }
+
+ node.appendChild(ol);
+ }
+
+ /**
+ * Breaks {@code job.sourceCode} around style boundaries in
+ * {@code job.decorations} and modifies {@code job.sourceNode} in place.
+ * @param {Object} job like <pre>{
+ * sourceCode: {string} source as plain text,
+ * spans: {Array.<number|Node>} alternating span start indices into source
+ * and the text node or element (e.g. {@code <BR>}) corresponding to that
+ * span.
+ * decorations: {Array.<number|string} an array of style classes preceded
+ * by the position at which they start in job.sourceCode in order
+ * }</pre>
+ * @private
+ */
+ function recombineTagsAndDecorations(job) {
+ var isIE = /\bMSIE\b/.test(navigator.userAgent);
+ var newlineRe = /\n/g;
+
+ var source = job.sourceCode;
+ var sourceLength = source.length;
+ // Index into source after the last code-unit recombined.
+ var sourceIndex = 0;
+
+ var spans = job.spans;
+ var nSpans = spans.length;
+ // Index into spans after the last span which ends at or before sourceIndex.
+ var spanIndex = 0;
+
+ var decorations = job.decorations;
+ var nDecorations = decorations.length;
+ // Index into decorations after the last decoration which ends at or before
+ // sourceIndex.
+ var decorationIndex = 0;
+
+ // Remove all zero-length decorations.
+ decorations[nDecorations] = sourceLength;
+ var decPos, i;
+ for (i = decPos = 0; i < nDecorations;) {
+ if (decorations[i] !== decorations[i + 2]) {
+ decorations[decPos++] = decorations[i++];
+ decorations[decPos++] = decorations[i++];
+ } else {
+ i += 2;
+ }
+ }
+ nDecorations = decPos;
+
+ // Simplify decorations.
+ for (i = decPos = 0; i < nDecorations;) {
+ var startPos = decorations[i];
+ // Conflate all adjacent decorations that use the same style.
+ var startDec = decorations[i + 1];
+ var end = i + 2;
+ while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
+ end += 2;
+ }
+ decorations[decPos++] = startPos;
+ decorations[decPos++] = startDec;
+ i = end;
+ }
+
+ nDecorations = decorations.length = decPos;
+
+ var decoration = null;
+ while (spanIndex < nSpans) {
+ var spanStart = spans[spanIndex];
+ var spanEnd = spans[spanIndex + 2] || sourceLength;
+
+ var decStart = decorations[decorationIndex];
+ var decEnd = decorations[decorationIndex + 2] || sourceLength;
+
+ var end = Math.min(spanEnd, decEnd);
+
+ var textNode = spans[spanIndex + 1];
+ var styledText;
+ if (textNode.nodeType !== 1 // Don't muck with <BR>s or <LI>s
+ // Don't introduce spans around empty text nodes.
+ && (styledText = source.substring(sourceIndex, end))) {
+ // This may seem bizarre, and it is. Emitting LF on IE causes the
+ // code to display with spaces instead of line breaks.
+ // Emitting Windows standard issue linebreaks (CRLF) causes a blank
+ // space to appear at the beginning of every line but the first.
+ // Emitting an old Mac OS 9 line separator makes everything spiffy.
+ if (isIE) { styledText = styledText.replace(newlineRe, '\r'); }
+ textNode.nodeValue = styledText;
+ var document = textNode.ownerDocument;
+ var span = document.createElement('SPAN');
+ span.className = decorations[decorationIndex + 1];
+ var parentNode = textNode.parentNode;
+ parentNode.replaceChild(span, textNode);
+ span.appendChild(textNode);
+ if (sourceIndex < spanEnd) { // Split off a text node.
+ spans[spanIndex + 1] = textNode
+ // TODO: Possibly optimize by using '' if there's no flicker.
+ = document.createTextNode(source.substring(end, spanEnd));
+ parentNode.insertBefore(textNode, span.nextSibling);
+ }
+ }
+
+ sourceIndex = end;
+
+ if (sourceIndex >= spanEnd) {
+ spanIndex += 2;
+ }
+ if (sourceIndex >= decEnd) {
+ decorationIndex += 2;
+ }
+ }
+ }
+
+
+ /** Maps language-specific file extensions to handlers. */
+ var langHandlerRegistry = {};
+ /** Register a language handler for the given file extensions.
+ * @param {function (Object)} handler a function from source code to a list
+ * of decorations. Takes a single argument job which describes the
+ * state of the computation. The single parameter has the form
+ * {@code {
+ * sourceCode: {string} as plain text.
+ * decorations: {Array.<number|string>} an array of style classes
+ * preceded by the position at which they start in
+ * job.sourceCode in order.
+ * The language handler should assigned this field.
+ * basePos: {int} the position of source in the larger source chunk.
+ * All positions in the output decorations array are relative
+ * to the larger source chunk.
+ * } }
+ * @param {Array.<string>} fileExtensions
+ */
+ function registerLangHandler(handler, fileExtensions) {
+ for (var i = fileExtensions.length; --i >= 0;) {
+ var ext = fileExtensions[i];
+ if (!langHandlerRegistry.hasOwnProperty(ext)) {
+ langHandlerRegistry[ext] = handler;
+ } else if (window['console']) {
+ console['warn']('cannot override language handler %s', ext);
+ }
+ }
+ }
+ function langHandlerForExtension(extension, source) {
+ if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
+ // Treat it as markup if the first non whitespace character is a < and
+ // the last non-whitespace character is a >.
+ extension = /^\s*</.test(source)
+ ? 'default-markup'
+ : 'default-code';
+ }
+ return langHandlerRegistry[extension];
+ }
+ registerLangHandler(decorateSource, ['default-code']);
+ registerLangHandler(
+ createSimpleLexer(
+ [],
+ [
+ [PR_PLAIN, /^[^<?]+/],
+ [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
+ [PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/],
+ // Unescaped content in an unknown language
+ ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/],
+ ['lang-', /^<%([\s\S]+?)(?:%>|$)/],
+ [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
+ ['lang-', /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
+ // Unescaped content in javascript. (Or possibly vbscript).
+ ['lang-js', /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
+ // Contains unescaped stylesheet content
+ ['lang-css', /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
+ ['lang-in.tag', /^(<\/?[a-z][^<>]*>)/i]
+ ]),
+ ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
+ registerLangHandler(
+ createSimpleLexer(
+ [
+ [PR_PLAIN, /^[\s]+/, null, ' \t\r\n'],
+ [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
+ ],
+ [
+ [PR_TAG, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
+ [PR_ATTRIB_NAME, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
+ ['lang-uq.val', /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
+ [PR_PUNCTUATION, /^[=<>\/]+/],
+ ['lang-js', /^on\w+\s*=\s*\"([^\"]+)\"/i],
+ ['lang-js', /^on\w+\s*=\s*\'([^\']+)\'/i],
+ ['lang-js', /^on\w+\s*=\s*([^\"\'>\s]+)/i],
+ ['lang-css', /^style\s*=\s*\"([^\"]+)\"/i],
+ ['lang-css', /^style\s*=\s*\'([^\']+)\'/i],
+ ['lang-css', /^style\s*=\s*([^\"\'>\s]+)/i]
+ ]),
+ ['in.tag']);
+ registerLangHandler(
+ createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': CPP_KEYWORDS,
+ 'hashComments': true,
+ 'cStyleComments': true,
+ 'types': C_TYPES
+ }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': 'null,true,false'
+ }), ['json']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': CSHARP_KEYWORDS,
+ 'hashComments': true,
+ 'cStyleComments': true,
+ 'verbatimStrings': true,
+ 'types': C_TYPES
+ }), ['cs']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': JAVA_KEYWORDS,
+ 'cStyleComments': true
+ }), ['java']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': SH_KEYWORDS,
+ 'hashComments': true,
+ 'multiLineStrings': true
+ }), ['bsh', 'csh', 'sh']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': PYTHON_KEYWORDS,
+ 'hashComments': true,
+ 'multiLineStrings': true,
+ 'tripleQuotedStrings': true
+ }), ['cv', 'py']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': PERL_KEYWORDS,
+ 'hashComments': true,
+ 'multiLineStrings': true,
+ 'regexLiterals': true
+ }), ['perl', 'pl', 'pm']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': RUBY_KEYWORDS,
+ 'hashComments': true,
+ 'multiLineStrings': true,
+ 'regexLiterals': true
+ }), ['rb']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': JSCRIPT_KEYWORDS,
+ 'cStyleComments': true,
+ 'regexLiterals': true
+ }), ['js']);
+ registerLangHandler(sourceDecorator({
+ 'keywords': COFFEE_KEYWORDS,
+ 'hashComments': 3, // ### style block comments
+ 'cStyleComments': true,
+ 'multilineStrings': true,
+ 'tripleQuotedStrings': true,
+ 'regexLiterals': true
+ }), ['coffee']);
+ registerLangHandler(createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
+
+ function applyDecorator(job) {
+ var opt_langExtension = job.langExtension;
+
+ try {
+ // Extract tags, and convert the source code to plain text.
+ var sourceAndSpans = extractSourceSpans(job.sourceNode);
+ /** Plain text. @type {string} */
+ var source = sourceAndSpans.sourceCode;
+ job.sourceCode = source;
+ job.spans = sourceAndSpans.spans;
+ job.basePos = 0;
+
+ // Apply the appropriate language handler
+ langHandlerForExtension(opt_langExtension, source)(job);
+
+ // Integrate the decorations and tags back into the source code,
+ // modifying the sourceNode in place.
+ recombineTagsAndDecorations(job);
+ } catch (e) {
+ if ('console' in window) {
+ console['log'](e && e['stack'] ? e['stack'] : e);
+ }
+ }
+ }
+
+ /**
+ * @param sourceCodeHtml {string} The HTML to pretty print.
+ * @param opt_langExtension {string} The language name to use.
+ * Typically, a filename extension like 'cpp' or 'java'.
+ * @param opt_numberLines {number|boolean} True to number lines,
+ * or the 1-indexed number of the first line in sourceCodeHtml.
+ */
+ function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
+ var container = document.createElement('PRE');
+ // This could cause images to load and onload listeners to fire.
+ // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
+ // We assume that the inner HTML is from a trusted source.
+ container.innerHTML = sourceCodeHtml;
+ if (opt_numberLines) {
+ numberLines(container, opt_numberLines);
+ }
+
+ var job = {
+ langExtension: opt_langExtension,
+ numberLines: opt_numberLines,
+ sourceNode: container
+ };
+ applyDecorator(job);
+ return container.innerHTML;
+ }
+
+ function prettyPrint(opt_whenDone) {
+ function byTagName(tn) { return document.getElementsByTagName(tn); }
+ // fetch a list of nodes to rewrite
+ var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
+ var elements = [];
+ for (var i = 0; i < codeSegments.length; ++i) {
+ for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
+ elements.push(codeSegments[i][j]);
+ }
+ }
+ codeSegments = null;
+
+ var clock = Date;
+ if (!clock['now']) {
+ clock = { 'now': function () { return +(new Date); } };
+ }
+
+ // The loop is broken into a series of continuations to make sure that we
+ // don't make the browser unresponsive when rewriting a large page.
+ var k = 0;
+ var prettyPrintingJob;
+
+ var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
+ var prettyPrintRe = /\bprettyprint\b/;
+
+ function doWork() {
+ var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ?
+ clock['now']() + 250 /* ms */ :
+ Infinity);
+ for (; k < elements.length && clock['now']() < endTime; k++) {
+ var cs = elements[k];
+ var className = cs.className;
+ if (className.indexOf('prettyprint') >= 0) {
+ // If the classes includes a language extensions, use it.
+ // Language extensions can be specified like
+ // <pre class="prettyprint lang-cpp">
+ // the language extension "cpp" is used to find a language handler as
+ // passed to PR.registerLangHandler.
+ // HTML5 recommends that a language be specified using "language-"
+ // as the prefix instead. Google Code Prettify supports both.
+ // http://dev.w3.org/html5/spec-author-view/the-code-element.html
+ var langExtension = className.match(langExtensionRe);
+ // Support <pre class="prettyprint"><code class="language-c">
+ var wrapper;
+ if (!langExtension && (wrapper = childContentWrapper(cs))
+ && "CODE" === wrapper.tagName) {
+ langExtension = wrapper.className.match(langExtensionRe);
+ }
+
+ if (langExtension) {
+ langExtension = langExtension[1];
+ }
+
+ // make sure this is not nested in an already prettified element
+ var nested = false;
+ for (var p = cs.parentNode; p; p = p.parentNode) {
+ if ((p.tagName === 'pre' || p.tagName === 'code' ||
+ p.tagName === 'xmp') &&
+ p.className && p.className.indexOf('prettyprint') >= 0) {
+ nested = true;
+ break;
+ }
+ }
+ if (!nested) {
+ // Look for a class like linenums or linenums:<n> where <n> is the
+ // 1-indexed number of the first line.
+ var lineNums = cs.className.match(/\blinenums\b(?::(\d+))?/);
+ lineNums = lineNums
+ ? lineNums[1] && lineNums[1].length ? +lineNums[1] : true
+ : false;
+ if (lineNums) { numberLines(cs, lineNums); }
+
+ // do the pretty printing
+ prettyPrintingJob = {
+ langExtension: langExtension,
+ sourceNode: cs,
+ numberLines: lineNums
+ };
+ applyDecorator(prettyPrintingJob);
+ }
+ }
+ }
+ if (k < elements.length) {
+ // finish up in a continuation
+ setTimeout(doWork, 250);
+ } else if (opt_whenDone) {
+ opt_whenDone();
+ }
+ }
+
+ doWork();
+ }
+
+ /**
+ * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
+ * {@code class=prettyprint} and prettify them.
+ *
+ * @param {Function?} opt_whenDone if specified, called when the last entry
+ * has been finished.
+ */
+ window['prettyPrintOne'] = prettyPrintOne;
+ /**
+ * Pretty print a chunk of code.
+ *
+ * @param {string} sourceCodeHtml code as html
+ * @return {string} code as html, but prettier
+ */
+ window['prettyPrint'] = prettyPrint;
+ /**
+ * Contains functions for creating and registering new language handlers.
+ * @type {Object}
+ */
+ window['PR'] = {
+ 'createSimpleLexer': createSimpleLexer,
+ 'registerLangHandler': registerLangHandler,
+ 'sourceDecorator': sourceDecorator,
+ 'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
+ 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
+ 'PR_COMMENT': PR_COMMENT,
+ 'PR_DECLARATION': PR_DECLARATION,
+ 'PR_KEYWORD': PR_KEYWORD,
+ 'PR_LITERAL': PR_LITERAL,
+ 'PR_NOCODE': PR_NOCODE,
+ 'PR_PLAIN': PR_PLAIN,
+ 'PR_PUNCTUATION': PR_PUNCTUATION,
+ 'PR_SOURCE': PR_SOURCE,
+ 'PR_STRING': PR_STRING,
+ 'PR_TAG': PR_TAG,
+ 'PR_TYPE': PR_TYPE
+ };
+})();
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/purl-2.2.1.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/purl-2.2.1.js
new file mode 100644
index 000000000..509ca0877
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/purl-2.2.1.js
@@ -0,0 +1,271 @@
+/*
+ * JQuery URL Parser plugin, v2.2.1
+ * Developed and maintanined by Mark Perkins, mark@allmarkedup.com
+ * Source repository: https://github.com/allmarkedup/jQuery-URL-Parser
+ * Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details.
+ */
+
+;(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD available; use anonymous module
+ if ( typeof jQuery !== 'undefined' ) {
+ define(['jquery'], factory);
+ } else {
+ define([], factory);
+ }
+ } else {
+ // No AMD available; mutate global vars
+ if ( typeof jQuery !== 'undefined' ) {
+ factory(jQuery);
+ } else {
+ factory();
+ }
+ }
+})(function($, undefined) {
+
+ var tag2attr = {
+ a : 'href',
+ img : 'src',
+ form : 'action',
+ base : 'href',
+ script : 'src',
+ iframe : 'src',
+ link : 'href'
+ },
+
+ key = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'], // keys available to query
+
+ aliases = { 'anchor' : 'fragment' }, // aliases for backwards compatability
+
+ parser = {
+ strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs
+ loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
+ },
+
+ toString = Object.prototype.toString,
+
+ isint = /^[0-9]+$/;
+
+ function parseUri( url, strictMode ) {
+ var str = decodeURI( url ),
+ res = parser[ strictMode || false ? 'strict' : 'loose' ].exec( str ),
+ uri = { attr : {}, param : {}, seg : {} },
+ i = 14;
+
+ while ( i-- ) {
+ uri.attr[ key[i] ] = res[i] || '';
+ }
+
+ // build query and fragment parameters
+ uri.param['query'] = parseString(uri.attr['query']);
+ uri.param['fragment'] = parseString(uri.attr['fragment']);
+
+ // split path and fragement into segments
+ uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');
+ uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');
+
+ // compile a 'base' domain attribute
+ uri.attr['base'] = uri.attr.host ? (uri.attr.protocol ? uri.attr.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : '';
+
+ return uri;
+ };
+
+ function getAttrName( elm ) {
+ var tn = elm.tagName;
+ if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()];
+ return tn;
+ }
+
+ function promote(parent, key) {
+ if (parent[key].length == 0) return parent[key] = {};
+ var t = {};
+ for (var i in parent[key]) t[i] = parent[key][i];
+ parent[key] = t;
+ return t;
+ }
+
+ function parse(parts, parent, key, val) {
+ var part = parts.shift();
+ if (!part) {
+ if (isArray(parent[key])) {
+ parent[key].push(val);
+ } else if ('object' == typeof parent[key]) {
+ parent[key] = val;
+ } else if ('undefined' == typeof parent[key]) {
+ parent[key] = val;
+ } else {
+ parent[key] = [parent[key], val];
+ }
+ } else {
+ var obj = parent[key] = parent[key] || [];
+ if (']' == part) {
+ if (isArray(obj)) {
+ if ('' != val) obj.push(val);
+ } else if ('object' == typeof obj) {
+ obj[keys(obj).length] = val;
+ } else {
+ obj = parent[key] = [parent[key], val];
+ }
+ } else if (~part.indexOf(']')) {
+ part = part.substr(0, part.length - 1);
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+ parse(parts, obj, part, val);
+ // key
+ } else {
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+ parse(parts, obj, part, val);
+ }
+ }
+ }
+
+ function merge(parent, key, val) {
+ if (~key.indexOf(']')) {
+ var parts = key.split('['),
+ len = parts.length,
+ last = len - 1;
+ parse(parts, parent, 'base', val);
+ } else {
+ if (!isint.test(key) && isArray(parent.base)) {
+ var t = {};
+ for (var k in parent.base) t[k] = parent.base[k];
+ parent.base = t;
+ }
+ set(parent.base, key, val);
+ }
+ return parent;
+ }
+
+ function parseString(str) {
+ return reduce(String(str).split(/&|;/), function(ret, pair) {
+ try {
+ pair = decodeURIComponent(pair.replace(/\+/g, ' '));
+ } catch(e) {
+ // ignore
+ }
+ var eql = pair.indexOf('='),
+ brace = lastBraceInKey(pair),
+ key = pair.substr(0, brace || eql),
+ val = pair.substr(brace || eql, pair.length),
+ val = val.substr(val.indexOf('=') + 1, val.length);
+
+ if ('' == key) key = pair, val = '';
+
+ return merge(ret, key, val);
+ }, { base: {} }).base;
+ }
+
+ function set(obj, key, val) {
+ var v = obj[key];
+ if (undefined === v) {
+ obj[key] = val;
+ } else if (isArray(v)) {
+ v.push(val);
+ } else {
+ obj[key] = [v, val];
+ }
+ }
+
+ function lastBraceInKey(str) {
+ var len = str.length,
+ brace, c;
+ for (var i = 0; i < len; ++i) {
+ c = str[i];
+ if (']' == c) brace = false;
+ if ('[' == c) brace = true;
+ if ('=' == c && !brace) return i;
+ }
+ }
+
+ function reduce(obj, accumulator){
+ var i = 0,
+ l = obj.length >> 0,
+ curr = arguments[2];
+ while (i < l) {
+ if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj);
+ ++i;
+ }
+ return curr;
+ }
+
+ function isArray(vArg) {
+ return Object.prototype.toString.call(vArg) === "[object Array]";
+ }
+
+ function keys(obj) {
+ var keys = [];
+ for ( prop in obj ) {
+ if ( obj.hasOwnProperty(prop) ) keys.push(prop);
+ }
+ return keys;
+ }
+
+ function purl( url, strictMode ) {
+ if ( arguments.length === 1 && url === true ) {
+ strictMode = true;
+ url = undefined;
+ }
+ strictMode = strictMode || false;
+ url = url || window.location.toString();
+
+ return {
+
+ data : parseUri(url, strictMode),
+
+ // get various attributes from the URI
+ attr : function( attr ) {
+ attr = aliases[attr] || attr;
+ return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr;
+ },
+
+ // return query string parameters
+ param : function( param ) {
+ return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query;
+ },
+
+ // return fragment parameters
+ fparam : function( param ) {
+ return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment;
+ },
+
+ // return path segments
+ segment : function( seg ) {
+ if ( typeof seg === 'undefined' ) {
+ return this.data.seg.path;
+ } else {
+ seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
+ return this.data.seg.path[seg];
+ }
+ },
+
+ // return fragment segments
+ fsegment : function( seg ) {
+ if ( typeof seg === 'undefined' ) {
+ return this.data.seg.fragment;
+ } else {
+ seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
+ return this.data.seg.fragment[seg];
+ }
+ }
+
+ };
+
+ };
+
+ if ( typeof $ !== 'undefined' ) {
+
+ $.fn.url = function( strictMode ) {
+ var url = '';
+ if ( this.length ) {
+ url = $(this).attr( getAttrName(this[0]) ) || '';
+ }
+ return purl( url, strictMode );
+ };
+
+ $.url = purl;
+
+ } else {
+ window.purl = purl;
+ }
+
+});
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback-tmpl.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback-tmpl.js
new file mode 100644
index 000000000..f9f4e2aae
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback-tmpl.js
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+require(['jquery',"jquery.tmpl",'i18n',"utils","text!templates/redback/user-edit.html",
+ "text!templates/redback/login.html"],
+ function(jquery,jqueryTmpl,i18n,utils,useredit, login) {
+
+ loadRedbackTemplate=function(){
+
+ var htmlFragment=$("#html-fragments");
+
+ // template loading
+ htmlFragment.append(useredit);
+ //$.tmpl(useredit).appendTo("#html-fragments");
+ $.tmpl(login).appendTo("#html-fragments");
+ //htmlFragment.append(login);
+ $.log("redback-tmpl.js loaded");
+ }
+ }
+); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback.js
new file mode 100644
index 000000000..4faafeefb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/redback.js
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("redback",["jquery","utils","jquery.validate","jquery.json","knockout",
+ "knockout.simpleGrid","redback.roles","redback.user","redback.users"], function(jquery,utils,jqueryValidate,jqueryJson,ko) {
+
+ // define a container object with various datas
+ window.redbackModel = {userOperationNames:null,key:null,i18n:$.i18n.map};
+
+ // unbinding
+ $("#user-create-form-cancel-button").on("click", function(){
+ $('#user-create').hide();
+ });
+
+
+ $("#user-create").on("submit",function(){
+ //nothing
+ });
+
+ /**
+ * call successFn on success with passing user object coming from cookie
+ */
+ userLogged=function(successFn,notLoggedFn) {
+ // call restServices/redbackServices/loginService/isLogged to know
+ // if a session exists and check the cookie
+ $.log("userLogged");
+ var userLogged = true;
+ $.ajax("restServices/redbackServices/loginService/isLogged", {
+ type: "GET",
+ success: function(data) {
+ var user = data ? mapUser(data):null;
+ window.user=user;
+ if(user){
+ reccordLoginCookie(user);
+ }
+ $.log("userLogged:"+(user!=null));
+ if (successFn){
+ successFn(user ? user:null);
+ }
+ if(!user){
+ if(notLoggedFn){
+ notLoggedFn();
+ }
+ }
+ }
+ });
+ }
+
+ Operation=function(name) {
+ this.name=ko.observable(name);
+ }
+
+ /**
+ * @param data Operation response from redback rest api
+ */
+ mapOperation=function(data) {
+ return new Operation(data.name,null);
+ }
+
+ Permission=function(name,operation,resource) {
+ this.name=ko.observable(name);
+ this.operation=ko.observable(operation);
+ this.resource=ko.observable(resource);
+ }
+
+ /**
+ * @param data Permission response from redback rest api
+ */
+ mapPermission=function(data) {
+ return new Permission(data.name,
+ data.operation?mapOperation(data.operation):null,
+ data.resource?mapResource(data.resource):null);
+ }
+
+ Resource=function(identifier,pattern) {
+ this.identifier=ko.observable(identifier);
+ this.pattern=ko.observable(pattern);
+ }
+
+ /**
+ * @param data Resource response from redback rest api
+ */
+ mapResource=function(data) {
+ return new Resource(data.identifier,data.pattern);
+ }
+
+ //---------------------------------------
+ // register part
+ //---------------------------------------
+
+ /**
+ * open the register modal box
+ */
+ registerBox=function(){
+ var modalRegister=$("#modal-register");
+ if (window.modalRegisterWindow==null) {
+ window.modalRegisterWindow = modalRegister.modal({backdrop:'static',show:false});
+ window.modalRegisterWindow.bind('hidden', function () {
+ $("#modal-register-err-message").hide();
+ })
+ }
+ window.modalRegisterWindow.modal('show');
+ $("#user-register-form").validate({
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#user-register-form",validator,errorMap,errorMap);
+ }
+ });
+ modalRegister.delegate("#modal-register-ok", "click keydown keypress", function(e) {
+ e.preventDefault();
+ register();
+ });
+ //$("#modal-register").focus();
+ }
+
+ UserRegistrationRequest=function(user,applicationUrl){
+ this.user=user;
+ this.applicationUrl=applicationUrl;
+ }
+
+ /**
+ * validate the register form and call REST service
+ */
+ register=function(){
+
+ $.log("redback.js#register");
+ var valid = $("#user-register-form").valid();
+ if (!valid) {
+ return;
+ }
+ clearUserMessages();
+ $("#modal-register-ok").attr("disabled","disabled");
+
+ $('#modal-register-footer').append(smallSpinnerImg());
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(data){
+ $.log("applicationUrl ok:"+data);
+
+ var user = {
+ username: $("#user-register-form-username").val(),
+ fullName: $("#user-register-form-fullname").val(),
+ email: $("#user-register-form-email").val()
+ };
+
+ var userRegistrationRequest=new UserRegistrationRequest(user,data);
+ $.ajax({
+ url: 'restServices/redbackServices/userService/registerUser',
+ data: JSON.stringify(userRegistrationRequest),
+ type: 'POST',
+ contentType: "application/json",
+ success: function(result){
+ var registered = false;
+ if (result == "-1") {
+ registered = false;
+ } else {
+ registered = true;
+ }
+
+ if (registered == true) {
+ window.modalRegisterWindow.modal('hide');
+ $("#register-link").hide();
+ // FIXME i18n
+ displaySuccessMessage("registered your key has been sent");
+ }
+ },
+ complete: function(){
+ $("#modal-register-ok").removeAttr("disabled");
+ removeSmallSpinnerImg();
+ },
+ error: function(result) {
+ window.modalRegisterWindow.modal('hide');
+ }
+ });
+ }
+ });
+
+ }
+
+ /**
+ * validate a registration key and go to change password key
+ * @param key
+ */
+ validateKey=function(key,registration) {
+ // FIXME spinner display
+ $.ajax({
+ url: 'restServices/redbackServices/userService/validateKey/'+key,
+ type: 'GET',
+ success: function(result){
+ window.redbackModel.key=key;
+ $.log("validateKey#sucess");
+ changePasswordBox(false,registration?registration:true,null);
+ },
+ complete: function(){
+ // hide spinner
+ },
+ error: function(result) {
+ $.log("validateKey#error");
+ }
+ })
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/roles.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/roles.js
new file mode 100644
index 000000000..5b6d7cb4c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/roles.js
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("redback.roles",["jquery","utils","i18n","jquery.validate","knockout","knockout.simpleGrid"],
+function(jquery,utils,i18n,jqueryValidate,ko,koSimpleGrid) {
+
+ Role = function(name,description,assignable,childRoleNames,parentRoleNames,users,parentsRolesUsers,permissions,otherUsers){
+
+ var self=this;
+
+ this.name = ko.observable(name);
+ this.name.subscribe(function(newValue){self.modified(true)});
+
+ this.description = ko.observable(description);
+ this.description.subscribe(function(newValue){self.modified(true)});
+
+ this.assignable = ko.observable(assignable);
+ this.assignable.subscribe(function(newValue){self.modified(true)});
+
+ this.childRoleNames = ko.observableArray(childRoleNames);//read only
+ this.childRoleNames.subscribe(function(newValue){self.modified(true)});
+
+ this.parentRoleNames = ko.observableArray(parentRoleNames);//read only
+ this.parentRoleNames.subscribe(function(newValue){self.modified(true)});
+
+ this.users = ko.observableArray(users?users:new Array());
+ this.users.subscribe(function(newValue){self.modified(true)});
+
+ this.parentsRolesUsers = ko.observableArray(parentsRolesUsers);//read only
+ this.parentsRolesUsers.subscribe(function(newValue){self.modified(true)});
+
+ this.permissions = ko.observableArray(permissions);//read only
+ this.permissions.subscribe(function(newValue){self.modified(true)});
+
+ // when editing a role other users not assign to this role are populated
+ this.otherUsers = ko.observableArray(otherUsers?otherUsers:new Array());
+ this.otherUsers.subscribe(function(newValue){self.modified(true)});
+
+ this.removedUsers= ko.observableArray(new Array());
+ this.removedUsers.subscribe(function(newValue){self.modified(true)});
+
+ this.modified=ko.observable(false);
+
+ this.usersModified=ko.observable(false);
+
+ this.updateDescription=function(){
+ var url = "restServices/redbackServices/roleManagementService/updateRoleDescription?";
+ var roleName = this.name();
+ url += "roleName="+encodeURIComponent(roleName);
+ url += "&roleDescription="+encodeURIComponent(this.description());
+ $.ajax(url,
+ {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ clearUserMessages();
+ displaySuccessMessage($.i18n.prop("role.updated",roleName));
+ },
+ error: function(data){
+ clearUserMessages();
+ displayErrorMessage("error updating role description");
+ }
+ }
+ );
+ }
+
+ this.updateUsers=function(){
+ var url = "restServices/redbackServices/roleManagementService/updateRoleUsers";
+ $.ajax(url,
+ {
+ type: "POST",
+ dataType: 'json',
+ contentType: 'application/json',
+ data: ko.toJSON(self),
+ success: function(data) {
+ clearUserMessages();
+ displaySuccessMessage($.i18n.prop("role.users.updated",self.name()));
+ self.usersModified(false);
+ self.modified(false);
+ },
+ error: function(data){
+ clearUserMessages();
+ displayErrorMessage("error updating users role");
+ }
+ }
+ );
+ }
+
+ }
+
+ /**
+ * view model used for roles grid
+ */
+ RolesViewModel=function() {
+ this.roles = ko.observableArray([]);
+
+ var self = this;
+
+
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: this.roles,
+ viewModel: this,
+ columns: [
+ {
+ headerText: $.i18n.prop('name'),
+ rowText: "name"
+ },
+ {
+ headerText: $.i18n.prop('description'),
+ rowText: "description"
+ }
+ ],
+ pageSize: 10
+ });
+
+ editRole=function(role){
+ var mainContent = $("#main-content");
+ mainContent.find("#roles-view-tabs-content #role-edit").html(mediumSpinnerImg());
+ // load missing attributes
+ $.ajax("restServices/redbackServices/roleManagementService/getRole/"+encodeURIComponent(role.name()),
+ {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedRole = mapRole(data);
+ role.parentRoleNames(mappedRole.parentRoleNames());
+ role.parentsRolesUsers(mappedRole.parentsRolesUsers());
+ role.users(mappedRole.users());
+ role.otherUsers(mappedRole.otherUsers());
+ role.modified(false);
+ var viewModel = new RoleViewModel(role);
+ ko.applyBindings(viewModel,mainContent.find("#roles-view-tabs-content #role-edit").get(0));
+ activateRoleEditTab();
+ mainContent.find("#role-view-users").tabs("show");
+ mainContent.find("#role-edit-users-tabs-content #role-view-users").addClass("active");
+ mainContent.find("#role-edit").collapse("show");
+ }
+ }
+ );
+ }
+
+ this.bulkSave=function(){
+ $.log("bulkSave");
+ return getModifiedRoles().length>0;
+ }
+
+ getModifiedRoles=function(){
+ var prx = $.grep(self.roles(),
+ function (role,i) {
+ return role.modified()||role.usersModified();
+ });
+ return prx;
+ }
+
+ updateModifiedRoles=function(){
+ var modifiedRoles = getModifiedRoles();
+ $.log("modifiedRoles:"+modifiedRoles);
+ openDialogConfirm(function(){
+ for(i=0;i<modifiedRoles.length;i++){
+ var modifiedRole=modifiedRoles[i];
+ if (modifiedRole.modified()){
+ modifiedRole.updateDescription();
+ modifiedRole.modified(false);
+ }
+ if (modifiedRole.usersModified()){
+ modifiedRole.updateUsers();
+ modifiedRole.usersModified(false);
+ }
+ }
+ closeDialogConfirm();
+ },
+ $.i18n.prop('ok'),
+ $.i18n.prop('cancel'),
+ $.i18n.prop('roles.bulk.save.confirm.title'),
+ $.i18n.prop('roles.bulk.save.confirm',modifiedRoles.length));
+
+
+ }
+
+ updateRole=function(modifiedRole){
+ if (modifiedRole.modified()){
+ modifiedRole.updateDescription();
+ modifiedRole.modified(false);
+ }
+ if (modifiedRole.usersModified()){
+ modifiedRole.updateUsers();
+ modifiedRole.usersModified(false);
+ }
+ }
+
+ }
+
+ displayRolesGrid = function(){
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+
+ $.ajax("restServices/redbackServices/roleManagementService/allRoles", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedRoles = $.map(data, function(item) {
+ return mapRole(item);
+ });
+ var rolesViewModel = new RolesViewModel();
+ rolesViewModel.roles(mappedRoles);
+ mainContent.html($("#rolesTabs").tmpl());
+ ko.applyBindings(rolesViewModel,mainContent.find("#roles-view").get(0));
+ mainContent.find("#roles-view-tabs #roles-view-tabs-a-roles-grid").tab("show");
+ activateRolesGridTab();
+ removeMediumSpinnerImg(mainContent);
+ }
+ }
+ );
+
+
+ }
+
+ RoleViewModel=function(role){
+ selectedOtherUsers= ko.observableArray();
+ selectedUsers= ko.observableArray();
+ currentRole=role;
+ var self=this;
+ addUser=function(){
+ $.log("addUser");
+ var removed = currentRole.otherUsers.removeAll(selectedOtherUsers());
+ for (var i = 0; i < removed.length; i++) {
+ $.log("add user:"+removed[i].username());
+ currentRole.users.push(removed[i]);
+ role.usersModified(true);
+ }
+ selectedOtherUsers([]);
+ $("#role-collapse" ).removeClass("in");
+ $("#role-users-collapse" ).addClass("in");
+ activateRoleUsersEditTab();
+ }
+
+ removeUser=function(){
+ $.log("removeUser");
+ var added = currentRole.users.removeAll(selectedUsers());
+ for (var i = 0; i < added.length; i++) {
+ currentRole.otherUsers.push(added[i]);
+ currentRole.removedUsers.push(added[i]);
+ role.usersModified(true);
+ }
+ selectedUsers([]);
+ $("#role-collapse" ).removeClass("in");
+ $("#role-users-collapse" ).addClass("in");
+ activateRoleUsersEditTab();
+ }
+
+ saveRoleDescription=function(){
+ currentRole.updateDescription();
+ }
+ saveUsers=function(){
+ currentRole.updateUsers();
+ }
+
+ updateMode=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#role-list-users").hide();
+ mainContent.find("#role-edit-users").show();
+ }
+ viewMode=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#role-edit-users").hide();
+ mainContent.find("#role-list-users").show();
+ }
+ }
+
+ /**
+ * @param data Role response from redback rest api
+ */
+ mapRole=function(data) {
+ // olamy this mapping has issues when fields are array or not
+ //return ko.mapping.fromJS(data);
+ // name, description, assignable,childRoleNames,parentRoleNames,users,parentsRolesUsers,permissions
+ //$.log("mapRole:"+data.name+":");
+ var childRoleNames = mapStringArray(data.childRoleNames);
+ var parentRoleNames = mapStringArray(data.parentRoleNames);
+ var users = data.users ? $.isArray(data.users) ? $.map(data.users, function(item) {
+ return mapUser(item);
+ }):new Array(mapUser(data.users)):null;
+
+ var parentsRolesUsers = data.parentsRolesUsers ? $.isArray(data.parentsRolesUsers)? $.map(data.parentsRolesUsers, function(item) {
+ return mapUser(item);
+ }):new Array(mapUser(data.parentsRolesUsers)):null;
+
+ var permissions = data.permissions? $.isArray(data.permissions) ? $.map(data.permissions, function(item){
+ return mapPermission(item);
+ }): new Array(mapPermission(data.permissions)) :null;
+
+ var otherUsers = data.otherUsers ? $.isArray(data.otherUsers)? $.map(data.otherUsers, function(item) {
+ return mapUser(item);
+ }):new Array(mapUser(data.otherUsers)):null;
+
+ return new Role(data.name, data.description?data.description:"",data.assignable,childRoleNames,parentRoleNames,users,parentsRolesUsers,permissions,otherUsers);
+ }
+
+ activateRolesGridTab=function(){
+ $("#main-content").find("#roles-view-tabs").find("li").removeClass("active");
+ $("#main-content").find("#roles-view-tabs-content").find("div").removeClass("active");
+ // activate roles grid tab
+ $("#main-content").find("#roles-view-tabs-content").find("#roles-view").addClass("active");
+ $("#main-content").find("#roles-view-tabs-li-roles-grid").addClass("active");
+ }
+
+ activateRoleEditTab=function(){
+ $("#main-content").find("#roles-view-tabs").find("li").removeClass("active");
+ $("#main-content").find("#roles-view-tabs-content").find("div").removeClass("active");
+ // activate role edit tab
+ $("#main-content").find("#roles-view-tabs-content").find("#role-edit").addClass("active");
+ $("#roles-view-tabs-li-roles-edit").addClass("active");
+ }
+
+ activateRoleUsersListTab=function(){
+ $("#main-content").find("#role-edit-users-li").removeClass("active");
+ $("#main-content").find("#role-edit-users").removeClass("active");
+ // activate roles grid tab
+ $("#main-content").find("#role-view-users-li").addClass("active");
+ $("#main-content").find("#role-view-users").addClass("active");
+ }
+
+ activateRoleUsersEditTab=function(){
+ $("#main-content").find("#role-view-users-li").removeClass("active");
+ $("#main-content").find("#role-view-users").removeClass("active");
+ // activate role edit tab
+ $("#main-content").find("#role-edit-users").addClass("active");
+ $("#role-edit-users-li").addClass("active");
+ }
+
+ ApplicationRoles = function(name,description,globalRoles,roleTemplates,resources){
+ //private String name;
+ this.name = ko.observable(name);
+ //private String description;
+ this.description = description? ko.observable(description):"";
+ //private Collection<String> globalRoles;
+ this.globalRoles = ko.observableArray(globalRoles);
+ //private Collection<RoleTemplate> roleTemplates;
+ this.roleTemplates = ko.observableArray(roleTemplates);
+ //private Collection<String> resources;
+ this.resources = ko.observableArray(resources);
+ }
+
+ mapApplicationRoles=function(data){
+ var roleTemplates = data.roleTemplates ? $.isArray(data.roleTemplates) ? $.map(data.roleTemplates, function(item) {
+ return mapRoleTemplate(item);
+ }):new Array(mapRoleTemplate(data.roleTemplates)):null;
+
+ return new ApplicationRoles(data.name,data.description,mapStringArray(data.globalRoles),roleTemplates,mapStringArray(data.resources));
+ }
+
+ RoleTemplate = function(id,namePrefix,delimiter,description,resource,roles){
+ //private String id;
+ this.id = ko.observable(id);
+ //private String namePrefix;
+ this.namePrefix = ko.observable(namePrefix);
+ //private String delimiter = " - ";
+ this.delimiter = ko.observable(delimiter);
+ //private String description;
+ this.description = description? ko.observable(description):"";
+ //private String resource;
+ this.resource = ko.observable(resource);
+ //private List<String> roles;
+ this.roles = ko.observableArray(roles);
+ }
+
+ mapRoleTemplate = function(data){
+ return new RoleTemplate(data.id,data.namePrefix,data.delimiter,data.description,mapStringArray(data.roles));
+ }
+
+}); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/user.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/user.js
new file mode 100644
index 000000000..f7d4bf2ee
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/user.js
@@ -0,0 +1,835 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("redback.user",["jquery","utils","i18n","jquery.validate","knockout","knockout.simpleGrid","purl"],
+function(jquery,utils,i18n,jqueryValidate,ko,koSimpleGrid,purl) {
+
+ /**
+ * object model for user with some function to create/update/delete users
+ * @param username
+ * @param password
+ * @param confirmPassword
+ * @param fullName
+ * @param email
+ * @param permanent
+ * @param validated
+ * @param timestampAccountCreation
+ * @param timestampLastLogin
+ * @param timestampLastPasswordChange
+ * @param locked
+ * @param passwordChangeRequired
+ * @param ownerViewModel
+ * @param readOnly
+ * @param uuserManagerId
+ */
+ User=function(username, password, confirmPassword,fullName,email,permanent,validated,timestampAccountCreation,
+ timestampLastLogin,timestampLastPasswordChange,locked,passwordChangeRequired,ownerViewModel,readOnly,userManagerId) {
+ var self=this;
+ // Potentially Editable Field.
+ this.username = ko.observable(username);
+ this.username.subscribe(function(newValue){self.modified(true)});
+ // Editable Fields.
+ this.password = ko.observable(password);
+ this.password.subscribe(function(newValue){self.modified(true)});
+
+ this.confirmPassword = ko.observable(confirmPassword);
+ this.confirmPassword.subscribe(function(newValue){self.modified(true)});
+
+ this.fullName = ko.observable(fullName);
+ this.fullName.subscribe(function(newValue){self.modified(true)});
+
+ this.email = ko.observable(email);
+ this.email.subscribe(function(newValue){self.modified(true)});
+
+ this.permanent = ko.observable(permanent);
+ this.permanent.subscribe(function(newValue){self.modified(true)});
+
+ this.validated = ko.observable(validated);
+ this.validated.subscribe(function(newValue){self.modified(true)});
+
+ // Display Only Fields.
+ this.timestampAccountCreation = ko.observable(timestampAccountCreation);
+ this.timestampLastLogin = ko.observable(timestampLastLogin);
+ this.timestampLastPasswordChange = ko.observable(timestampLastPasswordChange);
+ // admin only
+ this.locked = ko.observable(locked);
+ this.locked.subscribe(function(newValue){self.modified(true)});
+
+ this.passwordChangeRequired = ko.observable(passwordChangeRequired);
+ this.passwordChangeRequired.subscribe(function(newValue){self.modified(true)});
+
+ this.assignedRoles = ko.observableArray(new Array());
+ this.assignedRoles.subscribe(function(newValue){self.modified(true)});
+
+ this.modified=ko.observable(false);
+
+ this.readOnly=readOnly;
+
+ this.userManagerId=userManagerId;
+
+ this.rememberme=ko.observable(false);
+
+ this.logged=false;
+
+ this.remove = function() {
+ if (ownerViewModel) {
+ ownerViewModel.users.destroy(this);
+ }
+ };
+ this.create = function(successFnCallback) {
+ if (username == 'admin') {
+ this.createAdmin();
+ } else {
+ this.createUser(successFnCallback);
+ }
+ };
+ this.createUser = function(successFnCallback) {
+ $.log("user#createUser");
+ var valid = $("#user-create").valid();
+ if (!valid) {
+ return;
+ }
+ var currentUser = this;
+ $.ajax("restServices/redbackServices/userService/createUser", {
+ data: ko.toJSON(this),
+ contentType: 'application/json',
+ type: "POST",
+ dataType: 'json',
+ success: function(result) {
+ var created = result;
+ if (created == true) {
+ displaySuccessMessage( $.i18n.prop("user.created",currentUser.username()));
+ if (successFnCallback){
+ successFnCallback(currentUser);
+ }
+ clearForm("#main-content #user-create");
+ $("#main-content").find("#user-create").hide();
+ activateUsersGridTab();
+ return this;
+ } else {
+ displayErrorMessage("user cannot created");
+ }
+ }
+ });
+ };
+
+ this.createAdmin = function(succesCallbackFn,errorCallbackFn) {
+ $.log("user.js#createAdmin");
+ var valid = $("#user-create").valid();
+ $.log("create admin");
+ if (!valid) {
+ return;
+ }
+ var currentAdminUser = this;
+ $.ajax("restServices/redbackServices/userService/createAdminUser", {
+ data: ko.toJSON(this),
+ contentType: 'application/json',
+ type: "POST",
+ dataType: 'json',
+ success: function(result) {
+ var created = result;
+ if (created == true) {
+ displaySuccessMessage( $.i18n.prop("user.admin.created"));
+ var onSuccessCall=function(){
+ reccordLoginCookie(currentAdminUser);
+ window.archivaModel.adminExists=true;
+ screenChange();
+ checkCreateAdminLink();
+ checkSecurityLinks();
+ }
+ loginCall(currentAdminUser.username(), currentAdminUser.password(),false,onSuccessCall);
+ if(succesCallbackFn){
+ succesCallbackFn();
+ }
+ return this;
+ } else {
+ displayErrorMessage("admin user not created");
+ }
+ },
+ error: function(data){
+ if(errorCallbackFn){
+ errorCallbackFn();
+ }
+ }
+ });
+ };
+
+
+ this.update=function(){
+ var currentUser = this;
+ $.ajax("restServices/redbackServices/userService/updateUser", {
+ data: ko.toJSON(this),
+ contentType: 'application/json',
+ type: "POST",
+ dataType: 'json',
+ success: function(result) {
+ var updated = result;
+ if (updated == true) {
+ clearUserMessages();
+ displaySuccessMessage($.i18n.prop("user.updated",currentUser.username()));
+ $("#main-content").find("#users-view-tabs-li-user-edit").find("a").html($.i18n.prop("add"));
+ clearForm("#main-content #user-create");
+ activateUsersGridTab();
+ return this;
+ } else {
+ displayErrorMessage("user cannot be updated");
+ }
+ }
+ });
+ }
+
+ this.save=function(){
+ $.log("user.save create:"+window.redbackModel.createUser);
+ if (window.redbackModel.createUser==true){
+ var valid = $("#main-content").find("#user-create").valid();
+
+ if (valid==false) {
+ $.log("user#save valid:false");
+ return;
+ } else {
+ $.log("user#save valid:true");
+ return this.create();
+ }
+ } else {
+ return this.update();
+ }
+ }
+
+ this.updateAssignedRoles=function(){
+ $.log("user#updateAssignedRoles");
+ var curUser = this;
+ clearUserMessages();
+ $.ajax("restServices/redbackServices/roleManagementService/updateUserRoles", {
+ data: ko.toJSON(this),
+ contentType: 'application/json',
+ type: "POST",
+ dataType: 'json',
+ success: function(result) {
+ displaySuccessMessage($.i18n.prop("user.roles.updated",curUser.username()));
+ }
+ });
+ }
+
+ this.lock=function(){
+ this.locked(true);
+ var curUser = this;
+ clearUserMessages();
+ $.ajax("restServices/redbackServices/userService/lockUser/"+encodeURIComponent(curUser.username()), {
+ type: "GET",
+ success: function(result) {
+ displaySuccessMessage($.i18n.prop("user.locked",curUser.username()));
+ curUser.modified(false);
+ }
+ });
+ }
+
+ this.unlock=function(){
+ this.locked(false);
+ var curUser = this;
+ clearUserMessages();
+ $.ajax("restServices/redbackServices/userService/unlockUser/"+encodeURIComponent(curUser.username()), {
+ type: "GET",
+ success: function(result) {
+ displaySuccessMessage($.i18n.prop("user.unlocked",curUser.username()));
+ curUser.modified(false);
+ }
+ });
+ }
+
+ // value is boolean
+ this.changePasswordChangeRequired=function(value){
+ this.passwordChangeRequired(value);
+ var curUser = this;
+ var url = "restServices/redbackServices/userService/passwordChangeRequired/"+encodeURIComponent(curUser.username());
+ if (value==false){
+ url = "restServices/redbackServices/userService/passwordChangeNotRequired/"+encodeURIComponent(curUser.username());
+ }
+ $.ajax(url, {
+ type: "GET",
+ success: function(result) {
+ displaySuccessMessage($.i18n.prop("user.passwordChangeRequired.updated",curUser.username(),value));
+ curUser.modified(false);
+ }
+ });
+ };
+
+ }
+
+ /**
+ * view for admin user creation
+ */
+ AdminUserViewModel=function() {
+ this.user = new User("admin","","", "the administrator");
+ var self=this;
+ saveUser=function(){
+ if(! $("#user-create" ).valid() ) {
+ return;
+ }
+ self.user.createAdmin(function(){
+ // go to search when admin created
+ window.sammyArchivaApplication.setLocation("#search");
+ }
+ );
+ }
+ }
+
+ /**
+ * open a modal box to create admin user
+ */
+ adminCreateBox=function() {
+ var mainContent=$("#main-content");
+
+ $.ajax("restServices/redbackServices/userService/isAdminUserExists", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var adminExists = data;
+ window.archivaModel.adminExists=adminExists;
+ if (adminExists == false) {
+
+ window.redbackModel.createUser=true;
+ mainContent.attr("data-bind",'template: {name:"redback/user-edit-tmpl",data: user}');
+ var viewModel = new AdminUserViewModel();
+ ko.applyBindings(viewModel,mainContent.get(0));
+ $.log("adminCreateBox");
+ $("#user-create").validate({
+ rules: {
+ confirmPassword: {
+ equalTo: "#password"
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #user-create",validator,errorMap,errorMap);
+ }
+
+ });
+ // desactivate roles pill when adding user
+ $("#edit_user_details_pills_headers").hide();
+
+ } else {
+ window.sammyArchivaApplication.setLocation("#search");
+ }
+
+ }
+ });
+ }
+
+ /**
+ * open a modal box for login
+ */
+ loginBox=function(){
+
+ if (window.modalLoginWindow!=null){
+ window.modalLoginWindow=null;
+ }
+ if (window.modalLoginWindow==null) {
+ window.modalLoginWindow = $("#modal-login").modal();
+ window.modalLoginWindow.on('hidden', function () {
+ $("#modal-login-err-message").hide();
+ removeValidationErrorMessages("#user-login-form");
+ });
+ // focus on user name
+ window.modalLoginWindow.on('shown', function (e) {
+ $("#user-login-form-username" ).focus();
+ });
+ window.modalLoginWindow.keypress( function (event) {
+ if (event.which==13){
+ $("#modal-login-ok" ).trigger("click");
+ }
+ });
+ }
+
+ var user=getUserFromLoginCookie();
+ if(user){
+ $.log("found user in cookie rememberme:"+(user.rememberme()));
+ if(user.rememberme()){
+ $("#user-login-form-username" ).val(user.username());
+ $("#user-login-form-password" ).val(user.password());
+ $("#user-login-form-rememberme" ).attr("checked","true");
+ }
+ } else {
+ $.log("user not in cookie");
+ }
+
+ var rememberMe=window.redbackRuntimeConfiguration.findPropertyValue('security.rememberme.enabled');
+ $.log("rememberMe:"+rememberMe);
+ if (rememberMe=='false'){
+ $("#user-login-form-rememberme-label" ).hide();
+ $("#user-login-form-rememberme" ).attr("disabled","true");
+ if($("#user-login-form-rememberme" ).get(0 ).checked){
+ $("#user-login-form-rememberme" ).get(0 ).checked=false;
+ }
+ $("#user-login-form-username" ).val("");
+ $("#user-login-form-password" ).val("");
+ }
+
+ var userLoginForm = $("#user-login-form");
+
+ userLoginForm.validate({
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#user-login-form",validator,errorMap,errorMap);
+ }
+ });
+ $("#modal-login-ok").on("click", function(e) {
+ e.preventDefault();
+ login();
+ });
+
+ $("#modal-login-password-reset").on("click", function(e) {
+ e.preventDefault();
+ $.log("password reset");
+ passwordReset();
+ });
+
+ }
+
+
+ /**
+ * callback success function on rest login call.
+ * modal close and hide/show some links (login,logout,register...)
+ * @param result
+ */
+ var successLoginCallbackFn=function(result){
+
+ var logged = false;
+ if (result == null) {
+ logged = false;
+ } else {
+ if (result.username) {
+ logged = true;
+ }
+ }
+ if (logged == true) {
+ var user = mapUser(result);
+
+ if (user.passwordChangeRequired()==true){
+ changePasswordBox(true,false,user);
+ return;
+ }
+ // not really needed as an exception is returned but "ceintures et bretelles" as we say in French :-)
+ if (user.locked()==true){
+ $.log("user locked");
+ displayErrorMessage($.i18n.prop("account.locked"));
+ return;
+ }
+
+ // FIXME check validated
+ user.rememberme(window.redbackModel.rememberme);
+ if(user.rememberme()){
+ user.password(window.redbackModel.password);
+ }
+ $.log("user.rememberme:"+(user.rememberme()));
+ reccordLoginCookie(user);
+ window.user=user;
+ $("#login-link").hide();
+ $("#logout-link").show();
+ $("#register-link").hide();
+ $("#change-password-link").show();
+ if (window.modalLoginWindow){
+ window.modalLoginWindow.modal('hide');
+ }
+ clearForm("#user-login-form");
+ decorateMenuWithKarma(user);
+
+ return;
+ }
+ var modalLoginErrMsg=$("#modal-login-err-message");
+ modalLoginErrMsg.html($.i18n.prop("incorrect.username.password"));
+ modalLoginErrMsg.show();
+ }
+
+ /**
+ * callback error function on rest login call. display error message
+ * @param result
+ */
+ var errorLoginCallbackFn= function(result) {
+ var obj = jQuery.parseJSON(result.responseText);
+ displayRedbackError(obj,"modal-login-err-message");
+ $("#modal-login-err-message").show();
+ }
+
+ /**
+ * callback complate function on rest login call. remove spinner from modal login box
+ * @param result
+ */
+ var completeLoginCallbackFn=function(){
+ $("#modal-login-ok").button("reset");
+ $("#small-spinner").remove();
+ // force current screen reload to consider user karma
+ window.sammyArchivaApplication.refresh();
+ }
+
+ resetPasswordForm=function(key){
+ $.log("resetPasswordForm:"+key);
+ changePasswordBox(null,false,null,function(){
+ $.log("ok chgt pwd")
+ $.log("user.js#changePassword");
+ var valid = $("#password-change-form").valid();
+ if (valid==false) {
+ return;
+ }
+ var url = 'restServices/redbackServices/passwordService/changePasswordWithKey?';
+ url += "password="+$("#passwordChangeFormNewPassword").val();
+ url += "&passwordConfirmation="+$("#passwordChangeFormNewPasswordConfirm").val();
+ url += "&key="+key;
+ $.log("url:"+url);
+
+ $.ajax({
+ url: url,
+ success: function(result){
+ $.log("changePassword#success result:"+result);
+ var user = mapUser(result);
+ if (user) {
+ window.modalChangePasswordBox.modal('hide');
+ displaySuccessMessage($.i18n.prop('change.password.success.section.title'));
+ } else {
+ displayErrorMessage("issue appended");
+ }
+ window.modalChangePasswordBox.modal('hide');
+ var curHash = getUrlHash();
+ var url = $.url(window.location);
+ var newLocation=url.attr("path");
+ var requestLang=url.param("request_lang");
+ if(requestLang){
+ newLocation+="?request_lang="+requestLang;
+ }
+ if(curHash){
+ newLocation+="#"+curHash;
+ }else{
+ newLocation+="#search";
+ }
+ window.location=newLocation;
+ },
+ statusCode: {
+ 500: function(data){
+ $("#modal-password-change-err-message" ).empty();
+ displayRestError($.parseJSON(data.responseText),"modal-password-change-err-message");
+ $("#modal-password-change-err-message" ).show();
+ }
+ }
+ });
+
+ }
+ );
+ }
+
+ ResetPasswordRequest=function(username,applicationUrl){
+ this.username=username;
+ this.applicationUrl=applicationUrl;
+ }
+
+ passwordReset=function(){
+ var userLoginFormUsername=$("#user-login-form-username" );
+ var username = userLoginFormUsername.val();
+ if(username.trim().length<1){
+ var errorList=[{
+ message: $.i18n.prop("username.cannot.be.empty"),
+ element: userLoginFormUsername.get(0)
+ }];
+ customShowError("#user-login-form", null, null, errorList);
+ return;
+ }
+
+ if (window.modalLoginWindow){
+ window.modalLoginWindow.modal('hide');
+ }
+ $("#user-messages" ).html(mediumSpinnerImg());
+
+ $.ajax({
+ url: "restServices/archivaServices/archivaAdministrationService/applicationUrl",
+ type: "GET",
+ dataType: 'text',
+ success: function(data){
+
+ $.ajax("restServices/redbackServices/userService/resetPassword", {
+ type: "POST",
+ data: JSON.stringify(new ResetPasswordRequest(username,data)),
+ contentType: "application/json",
+ success: function(result) {
+ clearUserMessages();
+ displayInfoMessage($.i18n.prop("password.reset.success"));
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * validate login box before ajax call
+ */
+ login=function(){
+ $.log("user.js#login");
+
+ $("#modal-login-err-message").empty();
+
+ var valid = $("#user-login-form").valid();
+ if (!valid) {
+ return;
+ }
+ $("#modal-login-ok").button("loading");
+
+ $('#modal-login-footer').append(smallSpinnerImg());
+
+ var rememberme=($("#user-login-form-rememberme" ).attr('checked')=='checked');
+ window.redbackModel.rememberme=rememberme;
+ window.redbackModel.password=$("#user-login-form-password").val();
+
+ loginCall($("#user-login-form-username").val(),window.redbackModel.password,rememberme
+ ,successLoginCallbackFn,errorLoginCallbackFn,completeLoginCallbackFn);
+
+ }
+
+ /**
+ * call REST method for login
+ * @param username
+ * @param password
+ * @param rememberme
+ * @param successCallbackFn
+ * @param errorCallbackFn
+ * @param completeCallbackFn
+ */
+ loginCall=function(username,password,rememberme,successCallbackFn, errorCallbackFn, completeCallbackFn) {
+ var url = 'restServices/redbackServices/loginService/logIn';
+
+ $.ajax({
+ url: url,
+ type: 'POST',
+ contentType: 'application/json',
+ data: JSON.stringify({username:username,password:password}),
+ success: successCallbackFn,
+ error: errorCallbackFn,
+ complete: completeCallbackFn
+ });
+
+ }
+
+ /**
+ *
+ * @param previousPassword display and validate previous password text field
+ * @param registration are we in registration mode ?
+ */
+ changePasswordBox=function(previousPassword,registration,user,okFn){
+ $.log("changePasswordBox");
+ screenChange();
+ $.log("changePasswordBox previousPassword:"+previousPassword+",registration:"+registration+",user:"+user);
+ if (previousPassword==true){
+ $("#password-change-form-current-password-div").show();
+ $("#password-change-form-current-password").addClass("required");
+ }else{
+ $("#password-change-form-current-password-div").hide();
+ $("#password-change-form-current-password").removeClass("required");
+ }
+ if (window.modalChangePasswordBox == null) {
+ window.modalChangePasswordBox = $("#modal-password-change").modal({backdrop:'static',show:false});
+ window.modalChangePasswordBox.bind('hidden', function () {
+ $("#modal-password-change-err-message").hide();
+ })
+ $("#modal-password-change").delegate("#modal-change-password-ok", "click keydown keypress", function(e) {
+ e.preventDefault();
+ if ( $.isFunction(okFn)){
+ okFn();
+ } else {
+ changePassword(previousPassword,registration,user);
+ }
+ });
+ }
+ window.modalChangePasswordBox.modal('show');
+ $("#password-change-form").validate({
+ rules: {
+ passwordChangeFormNewPasswordConfirm : {
+ equalTo: "#passwordChangeFormNewPassword"
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#password-change-form",validator,errorMap,errorMap);
+ }
+ });
+
+
+ $("#modal-password-change").focus();
+ }
+
+ EditUserDetailViewModel=function(user){
+ this.user=user;
+ }
+
+ /**
+ * display modal box for updating current user details
+ */
+ editUserDetailsBox=function(){
+ clearUserMessages();
+ $("#modal-user-edit-err-message").hide();
+ $("#modal-user-edit-err-message").empty();
+ if (window.modalEditUserBox == null) {
+ window.modalEditUserBox = $("#modal-user-edit").modal({backdrop:'static',show:false});
+ window.modalEditUserBox.bind('hidden', function () {
+ $("#modal-user-edit-err-message").hide();
+ })
+ $("#modal-user-edit").find("#modal-user-edit-ok").on( "click keydown keypress", function(e) {
+ e.preventDefault();
+ $.log("user.js#editUserDetailsBox");
+ var valid = $("#user-edit-form").valid();
+ if (!valid) {
+ return;
+ }
+ var user = {
+ username:currentUser.username,
+ fullName:$("#modal-user-edit").find("#fullname").val(),
+ email:$("#modal-user-edit").find("#email").val(),
+ previousPassword:$("#modal-user-edit").find("#userEditFormCurrentPassword").val(),
+ password:$("#modal-user-edit").find("#userEditFormNewPassword").val(),
+ confirmPassword:$("#modal-user-edit").find("#userEditFormNewPasswordConfirm").val()
+ };
+ editUserDetails(user);
+ });
+ }
+ var currentUser = getUserFromLoginCookie();
+ /*$("#modal-user-edit").find("#username").html(currentUser.username);
+ $("#modal-user-edit").find("#fullname").val(currentUser.fullName);
+ $("#modal-user-edit").find("#email").val(currentUser.email);*/
+
+ $("#modal-user-edit-content" ).attr("data-bind",'template: {name:"modal-user-edit-tmpl"}');
+
+ var editUserDetailViewModel=new EditUserDetailViewModel(currentUser);
+ ko.applyBindings(editUserDetailViewModel,$("#modal-user-edit-content").get(0));
+
+ if(currentUser.readOnly){
+ $("#modal-user-edit-footer" ).hide();
+ }
+
+ window.modalEditUserBox.modal('show');
+ $("#user-edit-form").validate({
+ rules: {
+ userEditFormNewPasswordConfirm : {
+ equalTo: "#userEditFormNewPassword"
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#user-edit-form",validator,errorMap,errorMap);
+ }
+ });
+
+
+ $("#modal-user-edit").focus();
+ }
+
+ /**
+ * REST call to update current user
+ * @param user
+ */
+ editUserDetails=function(user){
+ $("#modal-user-edit-err-message").empty();
+ $.ajax("restServices/redbackServices/userService/updateMe", {
+ data: ko.toJSON(user),
+ contentType: 'application/json',
+ type: "POST",
+ dataType: 'json',
+ success: function(result) {
+ var created = result;
+ if (created == true) {
+ displaySuccessMessage( $.i18n.prop("user.details.updated"));
+ window.modalEditUserBox.modal('hide');
+ reccordLoginCookie(user);
+ clearForm("#user-edit-form");
+ return this;
+ } else {
+ displayErrorMessage("details cannot be updated","modal-user-edit-err-message");
+ }
+ },
+ error: function(result) {
+ var obj = jQuery.parseJSON(result.responseText);
+ $("#modal-user-edit-err-message").show();
+ displayRedbackError(obj,"modal-user-edit-err-message");
+ }
+ });
+
+ }
+
+
+ /**
+ *
+ * @param previousPassword display and validate previous password text field
+ * @param registration are we in registration mode ? if yes the user will be logged
+ */
+ changePassword=function(previousPassword,registration,user){
+ $.log("user.js#changePassword");
+ var valid = $("#password-change-form").valid();
+ if (valid==false) {
+ return;
+ }
+ $('#modal-password-change-footer').append(smallSpinnerImg());
+
+ if (registration==true) {
+ var url = 'restServices/redbackServices/passwordService/changePasswordWithKey?';
+ url += "password="+$("#passwordChangeFormNewPassword").val();
+ url += "&passwordConfirmation="+$("#passwordChangeFormNewPasswordConfirm").val();
+ url += "&key="+window.redbackModel.key;
+ } else {
+ var url = 'restServices/redbackServices/passwordService/changePassword?';
+ url += "password="+$("#passwordChangeFormNewPassword").val();
+ url += "&passwordConfirmation="+$("#passwordChangeFormNewPasswordConfirm").val();
+ url += "&previousPassword="+$("#password-change-form-current-password").val();
+ url += "&userName="+user.username();
+ }
+
+ $.ajax({
+ url: url,
+ success: function(result){
+ $.log("changePassword#success result:"+result);
+ var user = mapUser(result);
+ if (user) {
+ window.modalChangePasswordBox.modal('hide');
+ if (registration==true) {
+ $.log("changePassword#sucess,registration:"+registration);
+ displaySuccessMessage($.i18n.prop('change.password.success.section.title'))
+ loginCall(user.username(), $("#passwordChangeFormNewPassword").val(),true,successLoginCallbackFn,
+ function(data){
+ displayRestError(data,"modal-password-change-content");
+ }
+ ,function(){
+ window.modalChangePasswordBox.modal('hide');
+ window.location=window.location.toString().substringBeforeFirst("?");
+ window.sammyArchivaApplication.setLocation("#search");
+ });
+ } else {
+ displaySuccessMessage($.i18n.prop('change.password.success.section.title'));
+ }
+ } else {
+ displayErrorMessage("issue appended");
+ }
+ window.modalChangePasswordBox.modal('hide');
+ }
+ });
+
+ //$.urlParam('validateMe')
+ // for success i18n key change.password.success.section.title
+ }
+
+ /**
+ * @param data User response from redback rest api
+ */
+ mapUser=function(data) {
+ return new User(data.username, data.password, null,data.fullName,data.email,data.permanent,data.validated,
+ data.timestampAccountCreation,data.timestampLastLogin,data.timestampLastPasswordChange,
+ data.locked,data.passwordChangeRequired,self,data.readOnly,data.userManagerId);
+ }
+
+
+});
+
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/users.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/users.js
new file mode 100644
index 000000000..4409b0435
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/redback/users.js
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+define("redback.users",["jquery","utils","i18n","jquery.validate","knockout","knockout.simpleGrid"],
+function(jquery,utils,i18n,jqueryValidate,ko,koSimpleGrid) {
+
+ /**
+ * view model used for users grid
+ */
+ UsersViewModel=function() {
+ this.users = ko.observableArray([]);
+ var self = this;
+
+ this.gridViewModel = new ko.simpleGrid.viewModel({
+ data: this.users,
+ viewModel: this,
+ columns: [
+ {
+ headerText: "User Name",
+ rowText: "username"},
+ {
+ headerText: "Full Name",
+ rowText: "fullName"},
+ {
+ headerText: "Email",
+ rowText: "email"}
+ ],
+ pageSize: 10
+ });
+
+ this.addUser=function() {
+ clearUserMessages();
+ var mainContent = $("#main-content");
+ mainContent.find("#createUserForm").empty();
+ mainContent.find("#user-edit").remove();
+ mainContent.find("#user-create").show();
+ var viewModel = new UserViewModel(new User(),false,self);
+ $.log("UsersViewModel#addUser");
+ var createUserForm = mainContent.find("#createUserForm");
+ createUserForm.html(smallSpinnerImg());
+ createUserForm.attr("data-bind",'template: {name:"redback/user-edit-tmpl",data: user}');
+ ko.applyBindings(viewModel,createUserForm.get(0));
+ mainContent.find("#createUserForm #user-create-form-cancel-button").on( "click", function(e) {
+ e.preventDefault();
+ activateUsersGridTab();
+ });
+ mainContent.find("#user-create").validate({
+ rules: {
+ confirmPassword: {
+ equalTo: "#password"
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #user-create",validator,errorMap,errorMap);
+ }
+ });
+
+ // desactivate roles pill when adding user
+ mainContent.find("#edit_user_details_pills_headers").hide();
+
+ };
+
+ lock = function(user){
+ clearUserMessages();
+ user.lock();
+ }
+
+ unlock = function(user){
+ clearUserMessages();
+ user.unlock();
+ }
+
+ passwordChangeRequire = function(user,forceChangedPassword){
+ clearUserMessages();
+ user.changePasswordChangeRequired(forceChangedPassword);
+ }
+
+ this.sortByName = function() {
+ this.users.sort(function(a, b) {
+ return a.username < b.username ? -1 : 1;
+ });
+ };
+
+ deleteUser=function(user){
+ clearUserMessages();
+
+ var currentUser = user;
+ openDialogConfirm(function(){
+ $.ajax("restServices/redbackServices/userService/deleteUser/"+encodeURIComponent(currentUser.username()), {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ // FIXME i18n
+ displaySuccessMessage( $.i18n.prop("user.deleted", currentUser.username()));
+ self.users.remove(currentUser);
+ },
+ complete: function() {
+ closeDialogConfirm();
+ }
+ }
+ );
+ }
+ ,"Ok", $.i18n.prop("cancel"), $.i18n.prop("user.delete.message", currentUser.username()),
+ $("#user-delete-warning-tmpl" ).tmpl(currentUser));
+
+ }
+
+ editUserBox=function(user) {
+ $.log("editUserBox");
+ clearUserMessages();
+ activateUsersEditTab();
+ var mainContent = $("#main-content");
+ var viewModel = new UserViewModel(user,true,self);
+
+ mainContent.find("#user-edit-roles-view" ).append(smallSpinnerImg());
+ $.ajax("restServices/redbackServices/roleManagementService/getEffectivelyAssignedRoles/"+encodeURIComponent(user.username()), {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedRoles = $.map(data, function(item) {
+ return item.name;
+ });
+ user.assignedRoles = ko.observableArray(mappedRoles);
+
+ // user form binding
+ var createUserForm = mainContent.find("#createUserForm");
+ createUserForm.html(smallSpinnerImg());
+ createUserForm.attr("data-bind",'template: {name:"redback/user-edit-tmpl",data: user}');
+ ko.applyBindings(viewModel,createUserForm.get(0));
+
+ mainContent.find("#users-view-tabs-li-user-edit a").html($.i18n.prop("edit"));
+
+ mainContent.find("#user-create" ).find("#user-create-form-cancel-button").on("click", function(e) {
+ e.preventDefault();
+ activateUsersGridTab();
+ });
+
+ mainContent.find("#user-create").validate({
+ rules: {
+ confirmPassword: {
+ equalTo: "#password"
+ }
+ },
+ showErrors: function(validator, errorMap, errorList) {
+ customShowError("#main-content #user-create",validator,errorMap,errorMap);
+ }
+ });
+ mainContent.find("#createUserForm #user-create #user-create-form-register-button").on("click", function(e) {
+ e.preventDefault();
+ });
+
+ // user roles binding
+ mainContent.find("#user-edit-roles-view").attr("data-bind",'template: {name:"user_view_roles_list_tmpl"}');
+ ko.applyBindings(viewModel,mainContent.find("#user-edit-roles-view").get(0));
+ mainContent.find("#edit_user_details_pills_headers a:first").tab('show');
+
+ mainContent.find("#edit_user_details_pills_headers").bind('click', function (e) {
+ if ($(e.target).attr("href")=="#user-edit-roles-edit") {
+ editUserRoles(user);
+ }
+ })
+
+ }
+ }
+ );
+
+ }
+
+ }
+
+ editUserRoles=function(user){
+ var viewModel = new UserViewModel(user);
+ var mainContent = $("#main-content");
+ mainContent.find("#user-edit-roles-edit").html(smallSpinnerImg());
+ $.ajax("restServices/redbackServices/roleManagementService/getApplicationRoles/"+encodeURIComponent(user.username()), {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedApplicationRoles = $.map(data, function(item) {
+ return mapApplicationRoles(item);
+ });
+ viewModel.applicationRoles=ko.observableArray(mappedApplicationRoles);
+ mainContent.find("#user-edit-roles-edit").attr("data-bind",'template: {name:"user_edit_roles_tmpl"}');
+ ko.applyBindings(viewModel,mainContent.find("#user-edit-roles-edit").get(0));
+ $.log("assignedRoles:"+user.assignedRoles().length);
+ }
+ }
+ );
+ }
+
+ UserViewModel=function(user,updateMode,usersViewModel) {
+ this.user=user;
+ this.applicationRoles = ko.observableArray(new Array());
+ this.usersViewModel=usersViewModel;
+ this.updateMode=updateMode;
+ var self=this;
+ updateUserRoles=function(){
+ this.user.updateAssignedRoles();
+ }
+
+ saveUser=function(){
+ var valid = $("#main-content").find("#user-create").valid();
+ if (valid==false) {
+ return;
+ }
+ if (self.updateMode==false){
+ return user.create(function(){self.usersViewModel.users.push(user)});
+ } else {
+ return user.update();
+ }
+ }
+
+ }
+
+ /**
+ * called from the menu to display tabs with users grid
+ */
+ displayUsersGrid=function() {
+ screenChange();
+ var mainContent = $("#main-content");
+ mainContent.html(mediumSpinnerImg());
+ mainContent.attr("data-bind",'template: {name:"usersGrid"}');
+
+ $.ajax("restServices/redbackServices/userService/getUsers", {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ var mappedUsers = $.map(data, function(item) {
+ return mapUser(item);
+ });
+ var usersViewModel = new UsersViewModel();
+ usersViewModel.users(mappedUsers);
+ ko.applyBindings(usersViewModel,jQuery("#main-content").get(0));
+ mainContent.find("#users-view-tabs a:first").tab('show');
+ mainContent.find("#users-view-tabs a[data-toggle='tab']").on('show', function (e) {
+ //$.log( $(e.target).attr("href") ); // activated tab
+ //e.relatedTarget // previous tab
+ $.log("tabs shown");
+ if ($(e.target).attr("href")=="#createUserForm") {
+ usersViewModel.addUser();
+ }
+ if ($(e.target).attr("href")=="#users-view") {
+ mainContent.find("#users-view-tabs-li-user-edit a").html($.i18n.prop("add"));
+ }
+
+ })
+ mainContent.find("#users-view-tabs-content #users-view").addClass("active");
+ }
+ }
+ );
+
+ }
+
+ activateUsersGridTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#users-view-tabs li").removeClass("active");
+ mainContent.find("#users-view-tabs-content div").removeClass("active");
+ // activate users grid tab
+ mainContent.find("#users-view-tabs-content #users-view").addClass("active");
+ mainContent.find("#users-view-tabs-li-users-grid").addClass("active");
+ mainContent.find("#users-view-tabs-li-user-edit a").html($.i18n.prop("add"));
+ }
+
+ activateUsersEditTab=function(){
+ var mainContent = $("#main-content");
+ mainContent.find("#users-view-tabs li").removeClass("active");
+ mainContent.find("#users-view-tabs-content div").removeClass("active");
+ // activate users edit tab
+ mainContent.find("#users-view-tabs-content #createUserForm").addClass("active");
+ mainContent.find("#users-view-tabs-li-user-edit").addClass("active");
+ }
+
+});
+
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/require.2.1.2.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/require.2.1.2.js
new file mode 100644
index 000000000..8de013dc9
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/require.2.1.2.js
@@ -0,0 +1,35 @@
+/*
+ RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+ Available via the MIT or new BSD license.
+ see: http://github.com/jrburke/requirejs for details
+*/
+var requirejs,require,define;
+(function(Y){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function x(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function r(b,c){return da.call(b,c)}function i(b,c){return r(b,c)&&b[c]}function E(b,c){for(var d in b)if(r(b,d)&&c(b[d],d))break}function Q(b,c,d,i){c&&E(c,function(c,h){if(d||!r(b,h))i&&"string"!==typeof c?(b[h]||(b[h]={}),Q(b[h],
+c,d,i)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function Z(b){if(!b)return b;var c=Y;x(b.split("."),function(b){c=c[b]});return c}function J(b,c,d,i){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=i;d&&(c.originalError=d);return c}function ea(b){function c(a,g,v){var e,n,b,c,d,j,f,h=g&&g.split("/");e=h;var l=m.map,k=l&&l["*"];if(a&&"."===a.charAt(0))if(g){e=i(m.pkgs,g)?h=[g]:h.slice(0,h.length-1);g=a=e.concat(a.split("/"));
+for(e=0;g[e];e+=1)if(n=g[e],"."===n)g.splice(e,1),e-=1;else if(".."===n)if(1===e&&(".."===g[2]||".."===g[0]))break;else 0<e&&(g.splice(e-1,2),e-=2);e=i(m.pkgs,g=a[0]);a=a.join("/");e&&a===g+"/"+e.main&&(a=g)}else 0===a.indexOf("./")&&(a=a.substring(2));if(v&&(h||k)&&l){g=a.split("/");for(e=g.length;0<e;e-=1){b=g.slice(0,e).join("/");if(h)for(n=h.length;0<n;n-=1)if(v=i(l,h.slice(0,n).join("/")))if(v=i(v,b)){c=v;d=e;break}if(c)break;!j&&(k&&i(k,b))&&(j=i(k,b),f=e)}!c&&j&&(c=j,d=f);c&&(g.splice(0,d,
+c),a=g.join("/"))}return a}function d(a){z&&x(document.getElementsByTagName("script"),function(g){if(g.getAttribute("data-requiremodule")===a&&g.getAttribute("data-requirecontext")===j.contextName)return g.parentNode.removeChild(g),!0})}function y(a){var g=i(m.paths,a);if(g&&I(g)&&1<g.length)return d(a),g.shift(),j.require.undef(a),j.require([a]),!0}function f(a){var g,b=a?a.indexOf("!"):-1;-1<b&&(g=a.substring(0,b),a=a.substring(b+1,a.length));return[g,a]}function h(a,g,b,e){var n,u,d=null,h=g?g.name:
+null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(L+=1));a=f(a);d=a[0];a=a[1];d&&(d=c(d,h,e),u=i(p,d));a&&(d?k=u&&u.normalize?u.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(k=c(a,h,e),a=f(k),d=a[0],k=a[1],b=!0,n=j.nameToUrl(k)));b=d&&!u&&!b?"_unnormalized"+(M+=1):"";return{prefix:d,name:k,parentMap:g,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(d?d+"!"+k:k)+b}}function q(a){var g=a.id,b=i(k,g);b||(b=k[g]=new j.Module(a));return b}function s(a,g,b){var e=a.id,n=i(k,e);if(r(p,e)&&(!n||n.defineEmitComplete))"defined"===
+g&&b(p[e]);else q(a).on(g,b)}function C(a,g){var b=a.requireModules,e=!1;if(g)g(a);else if(x(b,function(g){if(g=i(k,g))g.error=a,g.events.error&&(e=!0,g.emit("error",a))}),!e)l.onError(a)}function w(){R.length&&(fa.apply(F,[F.length-1,0].concat(R)),R=[])}function A(a,g,b){var e=a.map.id;a.error?a.emit("error",a.error):(g[e]=!0,x(a.depMaps,function(e,c){var d=e.id,h=i(k,d);h&&(!a.depMatched[c]&&!b[d])&&(i(g,d)?(a.defineDep(c,p[d]),a.check()):A(h,g,b))}),b[e]=!0)}function B(){var a,g,b,e,n=(b=1E3*m.waitSeconds)&&
+j.startTime+b<(new Date).getTime(),c=[],h=[],f=!1,l=!0;if(!T){T=!0;E(k,function(b){a=b.map;g=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&n)y(g)?f=e=!0:(c.push(g),d(g));else if(!b.inited&&(b.fetched&&a.isDefine)&&(f=!0,!a.prefix))return l=!1});if(n&&c.length)return b=J("timeout","Load timeout for modules: "+c,null,c),b.contextName=j.contextName,C(b);l&&x(h,function(a){A(a,{},{})});if((!n||e)&&f)if((z||$)&&!U)U=setTimeout(function(){U=0;B()},50);T=!1}}function D(a){r(p,a[0])||
+q(h(a[0],null,!0)).init(a[1],a[2])}function G(a){var a=a.currentTarget||a.srcElement,b=j.onScriptLoad;a.detachEvent&&!V?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=j.onScriptError;(!a.detachEvent||V)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function K(){var a;for(w();F.length;){a=F.shift();if(null===a[0])return C(J("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));D(a)}}var T,W,j,N,U,m={waitSeconds:7,
+baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},k={},X={},F=[],p={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=j.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&i(m.config,a.map.id)||{}},exports:p[a.map.id]}}};W=function(a){this.events=i(X,a.id)||{};this.map=a;this.shim=
+i(m.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};W.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=
+b)},fetch:function(){if(!this.fetched){this.fetched=!0;j.startTime=(new Date).getTime();var a=this.map;if(this.shim)j.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;S[a]||(S[a]=!0,j.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,n=this.factory;
+if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(n)){if(this.events.error)try{e=j.execCb(c,n,b,e)}catch(d){a=d}else e=j.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",C(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&&
+!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(j,this.map,this.depMaps);delete k[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,"defined",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,f=j.makeRequire(a.parentMap,{enableBuildCallback:!0,
+skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||""),e=h(a.prefix+"!"+d,this.map.parentMap),s(e,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(k,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",t(this,function(a){this.emit("error",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error=
+a;a.requireModules=[b];E(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&delete k[a.map.id]});C(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(k){throw Error("fromText eval for "+d+" failed: "+k);}v&&(O=!0);this.depMaps.push(u);j.completeLoad(d);f([d],n)}),e.load(a.name,f,n,m)}));j.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a,
+b){var c,e;if("string"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,"error",this.errback)}c=a.id;e=k[c];!r(N,c)&&(e&&!e.enabled)&&j.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(k,a.id);b&&!b.enabled&&j.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=
+this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};j={config:m,contextName:b,registry:k,defined:p,urlFetched:S,defQueue:F,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?"map"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a,
+b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=j.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ga,"").replace(aa,"")}}),m.pkgs=b);E(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)j.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments));
+return b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function f(e,c,u){var i,m;d.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return C(J("requireargs","Invalid require call"),u);if(a&&r(N,e))return N[e](k[a.id]);if(l.get)return l.get(j,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?C(J("notloaded",'Module name "'+i+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[i]}K();j.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap;
+m.init(e,c,u,{enabled:!0});B()});return f}d=d||{};Q(f,{isBrowser:z,toUrl:function(b){var d=b.lastIndexOf("."),g=null;-1!==d&&(g=b.substring(d,b.length),b=b.substring(0,d));return j.nameToUrl(c(b,a&&a.id,!0),g)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(k,b)}});a||(f.undef=function(b){w();var c=h(b,a,!0),d=i(k,b);delete p[b];delete S[c.url];delete X[b];d&&(d.events.defined&&(X[b]=d.events),delete k[b])});return f},enable:function(a){i(k,
+a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();F.length;){c=F.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(k,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:C(J("nodefine","No define call for "+a,null,[a]));D([a,d.deps||[],d.exportsFn])}B()},nameToUrl:function(a,b){var c,d,h,f,j,k;if(l.jsExtRegExp.test(a))f=a+(b||"");else{c=m.paths;d=m.pkgs;f=a.split("/");for(j=f.length;0<j;j-=1)if(k=
+f.slice(0,j).join("/"),h=i(d,k),k=i(c,k)){I(k)&&(k=k[0]);f.splice(0,j,k);break}else if(h){c=a===h.name?h.location+"/"+h.main:h.location;f.splice(0,j,c);break}f=f.join("/");f+=b||(/\?/.test(f)?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":m.baseUrl)+f}return m.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+m.urlArgs):f},load:function(a,b){l.load(j,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ha.test((a.currentTarget||a.srcElement).readyState))P=
+null,a=G(a),j.completeLoad(a.id)},onScriptError:function(a){var b=G(a);if(!y(b.id))return C(J("scripterror","Script error",a,[b.id]))}};j.require=j.makeRequire();return j}var l,w,A,D,s,G,P,K,ba,ca,ia=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ja=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,aa=/\.js$/,ga=/^\.\//;w=Object.prototype;var L=w.toString,da=w.hasOwnProperty,fa=Array.prototype.splice,z=!!("undefined"!==typeof window&&navigator&&document),$=!z&&"undefined"!==typeof importScripts,ha=z&&
+"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,V="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),B={},q={},R=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(H(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!H(require)&&(q=require,require=void 0);l=requirejs=function(b,c,d,y){var f,h="_";!I(b)&&"string"!==typeof b&&(f=b,I(c)?(b=c,c=d,d=y):b=[]);f&&f.context&&(h=f.context);(y=i(B,h))||(y=B[h]=l.s.newContext(h));
+f&&y.configure(f);return y.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version="2.1.2";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=z;w=l.s={contexts:B,newContext:ea};l({});x(["toUrl","undef","defined","specified"],function(b){l[b]=function(){var c=B._;return c.require[b].apply(c,arguments)}});if(z&&(A=w.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))A=
+w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var i=b&&b.config||{},f;if(z)return f=i.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),f.type=i.scriptType||"text/javascript",f.charset="utf-8",f.async=!0,f.setAttribute("data-requirecontext",b.contextName),f.setAttribute("data-requiremodule",c),f.attachEvent&&!(f.attachEvent.toString&&0>f.attachEvent.toString().indexOf("[native code"))&&!V?(O=!0,f.attachEvent("onreadystatechange",
+b.onScriptLoad)):(f.addEventListener("load",b.onScriptLoad,!1),f.addEventListener("error",b.onScriptError,!1)),f.src=d,K=f,D?A.insertBefore(f,D):A.appendChild(f),K=null,f;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName("script"),function(b){A||(A=b.parentNode);if(s=b.getAttribute("data-main"))return q.baseUrl||(G=s.split("/"),ba=G.pop(),ca=G.length?G.join("/")+"/":"./",q.baseUrl=ca,s=ba),s=s.replace(aa,""),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var i,
+f;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=[]);!c.length&&H(d)&&d.length&&(d.toString().replace(ia,"").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(i=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute("data-requiremodule")),f=B[i.getAttribute("data-requirecontext")])}(f?f.defQueue:R).push([b,c,d])};define.amd=
+{jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/sammy.0.7.1.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/sammy.0.7.1.js
new file mode 100644
index 000000000..c756e225e
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/sammy.0.7.1.js
@@ -0,0 +1,2003 @@
+// name: sammy
+// version: 0.7.1
+
+// Sammy.js / http://sammyjs.org
+
+(function($, window) {
+ (function(factory){
+ // Support module loading scenarios
+ if (typeof define === 'function' && define.amd){
+ // AMD Anonymous Module
+ define(['jquery'], factory);
+ } else {
+ // No module loader (plain <script> tag) - put directly in global namespace
+ $.sammy = window.Sammy = factory($);
+ }
+ })(function($){
+ var Sammy,
+ PATH_REPLACER = "([^\/]+)",
+ PATH_NAME_MATCHER = /:([\w\d]+)/g,
+ QUERY_STRING_MATCHER = /\?([^#]*)?$/,
+ // mainly for making `arguments` an Array
+ _makeArray = function(nonarray) { return Array.prototype.slice.call(nonarray); },
+ // borrowed from jQuery
+ _isFunction = function( obj ) { return Object.prototype.toString.call(obj) === "[object Function]"; },
+ _isArray = function( obj ) { return Object.prototype.toString.call(obj) === "[object Array]"; },
+ _isRegExp = function( obj ) { return Object.prototype.toString.call(obj) === "[object RegExp]"; },
+ _decode = function( str ) { return decodeURIComponent((str || '').replace(/\+/g, ' ')); },
+ _encode = encodeURIComponent,
+ _escapeHTML = function(s) {
+ return String(s).replace(/&(?!\w+;)/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
+ },
+ _routeWrapper = function(verb) {
+ return function(path, callback) { return this.route.apply(this, [verb, path, callback]); };
+ },
+ _template_cache = {},
+ _has_history = !!(window.history && history.pushState),
+ loggers = [];
+
+
+ // `Sammy` (also aliased as $.sammy) is not only the namespace for a
+ // number of prototypes, its also a top level method that allows for easy
+ // creation/management of `Sammy.Application` instances. There are a
+ // number of different forms for `Sammy()` but each returns an instance
+ // of `Sammy.Application`. When a new instance is created using
+ // `Sammy` it is added to an Object called `Sammy.apps`. This
+ // provides for an easy way to get at existing Sammy applications. Only one
+ // instance is allowed per `element_selector` so when calling
+ // `Sammy('selector')` multiple times, the first time will create
+ // the application and the following times will extend the application
+ // already added to that selector.
+ //
+ // ### Example
+ //
+ // // returns the app at #main or a new app
+ // Sammy('#main')
+ //
+ // // equivalent to "new Sammy.Application", except appends to apps
+ // Sammy();
+ // Sammy(function() { ... });
+ //
+ // // extends the app at '#main' with function.
+ // Sammy('#main', function() { ... });
+ //
+ Sammy = function() {
+ var args = _makeArray(arguments),
+ app, selector;
+ Sammy.apps = Sammy.apps || {};
+ if (args.length === 0 || args[0] && _isFunction(args[0])) { // Sammy()
+ return Sammy.apply(Sammy, ['body'].concat(args));
+ } else if (typeof (selector = args.shift()) == 'string') { // Sammy('#main')
+ app = Sammy.apps[selector] || new Sammy.Application();
+ app.element_selector = selector;
+ if (args.length > 0) {
+ $.each(args, function(i, plugin) {
+ app.use(plugin);
+ });
+ }
+ // if the selector changes make sure the reference in Sammy.apps changes
+ if (app.element_selector != selector) {
+ delete Sammy.apps[selector];
+ }
+ Sammy.apps[app.element_selector] = app;
+ return app;
+ }
+ };
+
+ Sammy.VERSION = '0.7.1';
+
+ // Add to the global logger pool. Takes a function that accepts an
+ // unknown number of arguments and should print them or send them somewhere
+ // The first argument is always a timestamp.
+ Sammy.addLogger = function(logger) {
+ loggers.push(logger);
+ };
+
+ // Sends a log message to each logger listed in the global
+ // loggers pool. Can take any number of arguments.
+ // Also prefixes the arguments with a timestamp.
+ Sammy.log = function() {
+ var args = _makeArray(arguments);
+ args.unshift("[" + Date() + "]");
+ $.each(loggers, function(i, logger) {
+ logger.apply(Sammy, args);
+ });
+ };
+
+ if (typeof window.console != 'undefined') {
+ if (_isFunction(window.console.log.apply)) {
+ Sammy.addLogger(function() {
+ window.console.log.apply(window.console, arguments);
+ });
+ } else {
+ Sammy.addLogger(function() {
+ window.console.log(arguments);
+ });
+ }
+ } else if (typeof console != 'undefined') {
+ Sammy.addLogger(function() {
+ console.log.apply(console, arguments);
+ });
+ }
+
+ $.extend(Sammy, {
+ makeArray: _makeArray,
+ isFunction: _isFunction,
+ isArray: _isArray
+ });
+
+ // Sammy.Object is the base for all other Sammy classes. It provides some useful
+ // functionality, including cloning, iterating, etc.
+ Sammy.Object = function(obj) { // constructor
+ return $.extend(this, obj || {});
+ };
+
+ $.extend(Sammy.Object.prototype, {
+
+ // Escape HTML in string, use in templates to prevent script injection.
+ // Also aliased as `h()`
+ escapeHTML: _escapeHTML,
+ h: _escapeHTML,
+
+ // Returns a copy of the object with Functions removed.
+ toHash: function() {
+ var json = {};
+ $.each(this, function(k,v) {
+ if (!_isFunction(v)) {
+ json[k] = v;
+ }
+ });
+ return json;
+ },
+
+ // Renders a simple HTML version of this Objects attributes.
+ // Does not render functions.
+ // For example. Given this Sammy.Object:
+ //
+ // var s = new Sammy.Object({first_name: 'Sammy', last_name: 'Davis Jr.'});
+ // s.toHTML()
+ // //=> '<strong>first_name</strong> Sammy<br /><strong>last_name</strong> Davis Jr.<br />'
+ //
+ toHTML: function() {
+ var display = "";
+ $.each(this, function(k, v) {
+ if (!_isFunction(v)) {
+ display += "<strong>" + k + "</strong> " + v + "<br />";
+ }
+ });
+ return display;
+ },
+
+ // Returns an array of keys for this object. If `attributes_only`
+ // is true will not return keys that map to a `function()`
+ keys: function(attributes_only) {
+ var keys = [];
+ for (var property in this) {
+ if (!_isFunction(this[property]) || !attributes_only) {
+ keys.push(property);
+ }
+ }
+ return keys;
+ },
+
+ // Checks if the object has a value at `key` and that the value is not empty
+ has: function(key) {
+ return this[key] && $.trim(this[key].toString()) !== '';
+ },
+
+ // convenience method to join as many arguments as you want
+ // by the first argument - useful for making paths
+ join: function() {
+ var args = _makeArray(arguments);
+ var delimiter = args.shift();
+ return args.join(delimiter);
+ },
+
+ // Shortcut to Sammy.log
+ log: function() {
+ Sammy.log.apply(Sammy, arguments);
+ },
+
+ // Returns a string representation of this object.
+ // if `include_functions` is true, it will also toString() the
+ // methods of this object. By default only prints the attributes.
+ toString: function(include_functions) {
+ var s = [];
+ $.each(this, function(k, v) {
+ if (!_isFunction(v) || include_functions) {
+ s.push('"' + k + '": ' + v.toString());
+ }
+ });
+ return "Sammy.Object: {" + s.join(',') + "}";
+ }
+ });
+
+ // The DefaultLocationProxy is the default location proxy for all Sammy applications.
+ // A location proxy is a prototype that conforms to a simple interface. The purpose
+ // of a location proxy is to notify the Sammy.Application its bound to when the location
+ // or 'external state' changes.
+ //
+ // The `DefaultLocationProxy` watches for changes to the path of the current window and
+ // is also able to set the path based on changes in the application. It does this by
+ // using different methods depending on what is available in the current browser. In
+ // the latest and greatest browsers it used the HTML5 History API and the `pushState`
+ // `popState` events/methods. This allows you to use Sammy to serve a site behind normal
+ // URI paths as opposed to the older default of hash (#) based routing. Because the server
+ // can interpret the changed path on a refresh or re-entry, though, it requires additional
+ // support on the server side. If you'd like to force disable HTML5 history support, please
+ // use the `disable_push_state` setting on `Sammy.Application`. If pushState support
+ // is enabled, `DefaultLocationProxy` also binds to all links on the page. If a link is clicked
+ // that matches the current set of routes, the URL is changed using pushState instead of
+ // fully setting the location and the app is notified of the change.
+ //
+ // If the browser does not have support for HTML5 History, `DefaultLocationProxy` automatically
+ // falls back to the older hash based routing. The newest browsers (IE, Safari > 4, FF >= 3.6)
+ // support a 'onhashchange' DOM event, thats fired whenever the location.hash changes.
+ // In this situation the DefaultLocationProxy just binds to this event and delegates it to
+ // the application. In the case of older browsers a poller is set up to track changes to the
+ // hash.
+ Sammy.DefaultLocationProxy = function(app, run_interval_every) {
+ this.app = app;
+ // set is native to false and start the poller immediately
+ this.is_native = false;
+ this.has_history = _has_history;
+ this._startPolling(run_interval_every);
+ };
+
+ Sammy.DefaultLocationProxy.fullPath = function(location_obj) {
+ // Bypass the `window.location.hash` attribute. If a question mark
+ // appears in the hash IE6 will strip it and all of the following
+ // characters from `window.location.hash`.
+ var matches = location_obj.toString().match(/^[^#]*(#.+)$/);
+ var hash = matches ? matches[1] : '';
+ return [location_obj.pathname, location_obj.search, hash].join('');
+ };
+$.extend(Sammy.DefaultLocationProxy.prototype , {
+ // bind the proxy events to the current app.
+ bind: function() {
+ var proxy = this, app = this.app, lp = Sammy.DefaultLocationProxy;
+ $(window).bind('hashchange.' + this.app.eventNamespace(), function(e, non_native) {
+ // if we receive a native hash change event, set the proxy accordingly
+ // and stop polling
+ if (proxy.is_native === false && !non_native) {
+ proxy.is_native = true;
+ window.clearInterval(lp._interval);
+ }
+ app.trigger('location-changed');
+ });
+ if (_has_history && !app.disable_push_state) {
+ // bind to popstate
+ $(window).bind('popstate.' + this.app.eventNamespace(), function(e) {
+ app.trigger('location-changed');
+ });
+ // bind to link clicks that have routes
+ $('a').live('click.history-' + this.app.eventNamespace(), function(e) {
+ if (e.isDefaultPrevented() || e.metaKey || e.ctrlKey) {
+ return;
+ }
+ var full_path = lp.fullPath(this);
+ if (this.hostname == window.location.hostname &&
+ app.lookupRoute('get', full_path) &&
+ this.target !== '_blank') {
+ e.preventDefault();
+ proxy.setLocation(full_path);
+ return false;
+ }
+ });
+ }
+ if (!lp._bindings) {
+ lp._bindings = 0;
+ }
+ lp._bindings++;
+ },
+
+ // unbind the proxy events from the current app
+ unbind: function() {
+ $(window).unbind('hashchange.' + this.app.eventNamespace());
+ $(window).unbind('popstate.' + this.app.eventNamespace());
+ $('a').die('click.history-' + this.app.eventNamespace());
+ Sammy.DefaultLocationProxy._bindings--;
+ if (Sammy.DefaultLocationProxy._bindings <= 0) {
+ window.clearInterval(Sammy.DefaultLocationProxy._interval);
+ }
+ },
+
+ // get the current location from the hash.
+ getLocation: function() {
+ return Sammy.DefaultLocationProxy.fullPath(window.location);
+ },
+
+ // set the current location to `new_location`
+ setLocation: function(new_location) {
+ if (/^([^#\/]|$)/.test(new_location)) { // non-prefixed url
+ if (_has_history && !this.app.disable_push_state) {
+ new_location = '/' + new_location;
+ } else {
+ new_location = '#!/' + new_location;
+ }
+ }
+ if (new_location != this.getLocation()) {
+ // HTML5 History exists and new_location is a full path
+ if (_has_history && !this.app.disable_push_state && /^\//.test(new_location)) {
+ history.pushState({ path: new_location }, window.title, new_location);
+ this.app.trigger('location-changed');
+ } else {
+ return (window.location = new_location);
+ }
+ }
+ },
+
+ _startPolling: function(every) {
+ // set up interval
+ var proxy = this;
+ if (!Sammy.DefaultLocationProxy._interval) {
+ if (!every) { every = 10; }
+ var hashCheck = function() {
+ var current_location = proxy.getLocation();
+ if (typeof Sammy.DefaultLocationProxy._last_location == 'undefined' ||
+ current_location != Sammy.DefaultLocationProxy._last_location) {
+ window.setTimeout(function() {
+ $(window).trigger('hashchange', [true]);
+ }, 0);
+ }
+ Sammy.DefaultLocationProxy._last_location = current_location;
+ };
+ hashCheck();
+ Sammy.DefaultLocationProxy._interval = window.setInterval(hashCheck, every);
+ }
+ }
+ });
+
+
+ // Sammy.Application is the Base prototype for defining 'applications'.
+ // An 'application' is a collection of 'routes' and bound events that is
+ // attached to an element when `run()` is called.
+ // The only argument an 'app_function' is evaluated within the context of the application.
+ Sammy.Application = function(app_function) {
+ var app = this;
+ this.routes = {};
+ this.listeners = new Sammy.Object({});
+ this.arounds = [];
+ this.befores = [];
+ // generate a unique namespace
+ this.namespace = (new Date()).getTime() + '-' + parseInt(Math.random() * 1000, 10);
+ this.context_prototype = function() { Sammy.EventContext.apply(this, arguments); };
+ this.context_prototype.prototype = new Sammy.EventContext();
+
+ if (_isFunction(app_function)) {
+ app_function.apply(this, [this]);
+ }
+ // set the location proxy if not defined to the default (DefaultLocationProxy)
+ if (!this._location_proxy) {
+ this.setLocationProxy(new Sammy.DefaultLocationProxy(this, this.run_interval_every));
+ }
+ if (this.debug) {
+ this.bindToAllEvents(function(e, data) {
+ app.log(app.toString(), e.cleaned_type, data || {});
+ });
+ }
+ };
+
+ Sammy.Application.prototype = $.extend({}, Sammy.Object.prototype, {
+
+ // the four route verbs
+ ROUTE_VERBS: ['get','post','put','delete'],
+
+ // An array of the default events triggered by the
+ // application during its lifecycle
+ APP_EVENTS: ['run', 'unload', 'lookup-route', 'run-route', 'route-found', 'event-context-before', 'event-context-after', 'changed', 'error', 'check-form-submission', 'redirect', 'location-changed'],
+
+ _last_route: null,
+ _location_proxy: null,
+ _running: false,
+
+ // Defines what element the application is bound to. Provide a selector
+ // (parseable by `jQuery()`) and this will be used by `$element()`
+ element_selector: 'body',
+
+ // When set to true, logs all of the default events using `log()`
+ debug: false,
+
+ // When set to true, and the error() handler is not overridden, will actually
+ // raise JS errors in routes (500) and when routes can't be found (404)
+ raise_errors: false,
+
+ // The time in milliseconds that the URL is queried for changes
+ run_interval_every: 50,
+
+ // if using the `DefaultLocationProxy` setting this to true will force the app to use
+ // traditional hash based routing as opposed to the new HTML5 PushState support
+ disable_push_state: false,
+
+ // The default template engine to use when using `partial()` in an
+ // `EventContext`. `template_engine` can either be a string that
+ // corresponds to the name of a method/helper on EventContext or it can be a function
+ // that takes two arguments, the content of the unrendered partial and an optional
+ // JS object that contains interpolation data. Template engine is only called/referred
+ // to if the extension of the partial is null or unknown. See `partial()`
+ // for more information
+ template_engine: null,
+
+ // //=> Sammy.Application: body
+ toString: function() {
+ return 'Sammy.Application:' + this.element_selector;
+ },
+
+ // returns a jQuery object of the Applications bound element.
+ $element: function(selector) {
+ return selector ? $(this.element_selector).find(selector) : $(this.element_selector);
+ },
+
+ // `use()` is the entry point for including Sammy plugins.
+ // The first argument to use should be a function() that is evaluated
+ // in the context of the current application, just like the `app_function`
+ // argument to the `Sammy.Application` constructor.
+ //
+ // Any additional arguments are passed to the app function sequentially.
+ //
+ // For much more detail about plugins, check out:
+ // [http://sammyjs.org/docs/plugins](http://sammyjs.org/docs/plugins)
+ //
+ // ### Example
+ //
+ // var MyPlugin = function(app, prepend) {
+ //
+ // this.helpers({
+ // myhelper: function(text) {
+ // alert(prepend + " " + text);
+ // }
+ // });
+ //
+ // };
+ //
+ // var app = $.sammy(function() {
+ //
+ // this.use(MyPlugin, 'This is my plugin');
+ //
+ // this.get('#/', function() {
+ // this.myhelper('and dont you forget it!');
+ // //=> Alerts: This is my plugin and dont you forget it!
+ // });
+ //
+ // });
+ //
+ // If plugin is passed as a string it assumes your are trying to load
+ // Sammy."Plugin". This is the preferred way of loading core Sammy plugins
+ // as it allows for better error-messaging.
+ //
+ // ### Example
+ //
+ // $.sammy(function() {
+ // this.use('Mustache'); //=> Sammy.Mustache
+ // this.use('Storage'); //=> Sammy.Storage
+ // });
+ //
+ use: function() {
+ // flatten the arguments
+ var args = _makeArray(arguments),
+ plugin = args.shift(),
+ plugin_name = plugin || '';
+ try {
+ args.unshift(this);
+ if (typeof plugin == 'string') {
+ plugin_name = 'Sammy.' + plugin;
+ plugin = Sammy[plugin];
+ }
+ plugin.apply(this, args);
+ } catch(e) {
+ if (typeof plugin === 'undefined') {
+ this.error("Plugin Error: called use() but plugin (" + plugin_name.toString() + ") is not defined", e);
+ } else if (!_isFunction(plugin)) {
+ this.error("Plugin Error: called use() but '" + plugin_name.toString() + "' is not a function", e);
+ } else {
+ this.error("Plugin Error", e);
+ }
+ }
+ return this;
+ },
+
+ // Sets the location proxy for the current app. By default this is set to
+ // a new `Sammy.DefaultLocationProxy` on initialization. However, you can set
+ // the location_proxy inside you're app function to give your app a custom
+ // location mechanism. See `Sammy.DefaultLocationProxy` and `Sammy.DataLocationProxy`
+ // for examples.
+ //
+ // `setLocationProxy()` takes an initialized location proxy.
+ //
+ // ### Example
+ //
+ // // to bind to data instead of the default hash;
+ // var app = $.sammy(function() {
+ // this.setLocationProxy(new Sammy.DataLocationProxy(this));
+ // });
+ //
+ setLocationProxy: function(new_proxy) {
+ var original_proxy = this._location_proxy;
+ this._location_proxy = new_proxy;
+ if (this.isRunning()) {
+ if (original_proxy) {
+ // if there is already a location proxy, unbind it.
+ original_proxy.unbind();
+ }
+ this._location_proxy.bind();
+ }
+ },
+
+ // provide log() override for inside an app that includes the relevant application element_selector
+ log: function() {
+ Sammy.log.apply(Sammy, Array.prototype.concat.apply([this.element_selector],arguments));
+ },
+
+
+ // `route()` is the main method for defining routes within an application.
+ // For great detail on routes, check out:
+ // [http://sammyjs.org/docs/routes](http://sammyjs.org/docs/routes)
+ //
+ // This method also has aliases for each of the different verbs (eg. `get()`, `post()`, etc.)
+ //
+ // ### Arguments
+ //
+ // * `verb` A String in the set of ROUTE_VERBS or 'any'. 'any' will add routes for each
+ // of the ROUTE_VERBS. If only two arguments are passed,
+ // the first argument is the path, the second is the callback and the verb
+ // is assumed to be 'any'.
+ // * `path` A Regexp or a String representing the path to match to invoke this verb.
+ // * `callback` A Function that is called/evaluated when the route is run see: `runRoute()`.
+ // It is also possible to pass a string as the callback, which is looked up as the name
+ // of a method on the application.
+ //
+ route: function(verb, path, callback) {
+ var app = this, param_names = [], add_route, path_match;
+
+ // if the method signature is just (path, callback)
+ // assume the verb is 'any'
+ if (!callback && _isFunction(path)) {
+ path = verb;
+ callback = path;
+ verb = 'any';
+ }
+
+ verb = verb.toLowerCase(); // ensure verb is lower case
+
+ // if path is a string turn it into a regex
+ if (path.constructor == String) {
+
+ // Needs to be explicitly set because IE will maintain the index unless NULL is returned,
+ // which means that with two consecutive routes that contain params, the second set of params will not be found and end up in splat instead of params
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/lastIndex
+ PATH_NAME_MATCHER.lastIndex = 0;
+
+ // find the names
+ while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) {
+ param_names.push(path_match[1]);
+ }
+ // replace with the path replacement
+ path = new RegExp(path.replace(PATH_NAME_MATCHER, PATH_REPLACER) + "$");
+ }
+ // lookup callback
+ if (typeof callback == 'string') {
+ callback = app[callback];
+ }
+
+ add_route = function(with_verb) {
+ var r = {verb: with_verb, path: path, callback: callback, param_names: param_names};
+ // add route to routes array
+ app.routes[with_verb] = app.routes[with_verb] || [];
+ // place routes in order of definition
+ app.routes[with_verb].push(r);
+ };
+
+ if (verb === 'any') {
+ $.each(this.ROUTE_VERBS, function(i, v) { add_route(v); });
+ } else {
+ add_route(verb);
+ }
+
+ // return the app
+ return this;
+ },
+
+ // Alias for route('get', ...)
+ get: _routeWrapper('get'),
+
+ // Alias for route('post', ...)
+ post: _routeWrapper('post'),
+
+ // Alias for route('put', ...)
+ put: _routeWrapper('put'),
+
+ // Alias for route('delete', ...)
+ del: _routeWrapper('delete'),
+
+ // Alias for route('any', ...)
+ any: _routeWrapper('any'),
+
+ // `mapRoutes` takes an array of arrays, each array being passed to route()
+ // as arguments, this allows for mass definition of routes. Another benefit is
+ // this makes it possible/easier to load routes via remote JSON.
+ //
+ // ### Example
+ //
+ // var app = $.sammy(function() {
+ //
+ // this.mapRoutes([
+ // ['get', '#/', function() { this.log('index'); }],
+ // // strings in callbacks are looked up as methods on the app
+ // ['post', '#/create', 'addUser'],
+ // // No verb assumes 'any' as the verb
+ // [/dowhatever/, function() { this.log(this.verb, this.path)}];
+ // ]);
+ // });
+ //
+ mapRoutes: function(route_array) {
+ var app = this;
+ $.each(route_array, function(i, route_args) {
+ app.route.apply(app, route_args);
+ });
+ return this;
+ },
+
+ // A unique event namespace defined per application.
+ // All events bound with `bind()` are automatically bound within this space.
+ eventNamespace: function() {
+ return ['sammy-app', this.namespace].join('-');
+ },
+
+ // Works just like `jQuery.fn.bind()` with a couple notable differences.
+ //
+ // * It binds all events to the application element
+ // * All events are bound within the `eventNamespace()`
+ // * Events are not actually bound until the application is started with `run()`
+ // * callbacks are evaluated within the context of a Sammy.EventContext
+ //
+ bind: function(name, data, callback) {
+ var app = this;
+ // build the callback
+ // if the arity is 2, callback is the second argument
+ if (typeof callback == 'undefined') { callback = data; }
+ var listener_callback = function() {
+ // pull off the context from the arguments to the callback
+ var e, context, data;
+ e = arguments[0];
+ data = arguments[1];
+ if (data && data.context) {
+ context = data.context;
+ delete data.context;
+ } else {
+ context = new app.context_prototype(app, 'bind', e.type, data, e.target);
+ }
+ e.cleaned_type = e.type.replace(app.eventNamespace(), '');
+ callback.apply(context, [e, data]);
+ };
+
+ // it could be that the app element doesnt exist yet
+ // so attach to the listeners array and then run()
+ // will actually bind the event.
+ if (!this.listeners[name]) { this.listeners[name] = []; }
+ this.listeners[name].push(listener_callback);
+ if (this.isRunning()) {
+ // if the app is running
+ // *actually* bind the event to the app element
+ this._listen(name, listener_callback);
+ }
+ return this;
+ },
+
+ // Triggers custom events defined with `bind()`
+ //
+ // ### Arguments
+ //
+ // * `name` The name of the event. Automatically prefixed with the `eventNamespace()`
+ // * `data` An optional Object that can be passed to the bound callback.
+ // * `context` An optional context/Object in which to execute the bound callback.
+ // If no context is supplied a the context is a new `Sammy.EventContext`
+ //
+ trigger: function(name, data) {
+ this.$element().trigger([name, this.eventNamespace()].join('.'), [data]);
+ return this;
+ },
+
+ // Reruns the current route
+ refresh: function() {
+ this.last_location = null;
+ this.trigger('location-changed');
+ return this;
+ },
+
+ // Takes a single callback that is pushed on to a stack.
+ // Before any route is run, the callbacks are evaluated in order within
+ // the current `Sammy.EventContext`
+ //
+ // If any of the callbacks explicitly return false, execution of any
+ // further callbacks and the route itself is halted.
+ //
+ // You can also provide a set of options that will define when to run this
+ // before based on the route it proceeds.
+ //
+ // ### Example
+ //
+ // var app = $.sammy(function() {
+ //
+ // // will run at #/route but not at #/
+ // this.before('#/route', function() {
+ // //...
+ // });
+ //
+ // // will run at #/ but not at #/route
+ // this.before({except: {path: '#/route'}}, function() {
+ // this.log('not before #/route');
+ // });
+ //
+ // this.get('#/', function() {});
+ //
+ // this.get('#/route', function() {});
+ //
+ // });
+ //
+ // See `contextMatchesOptions()` for a full list of supported options
+ //
+ before: function(options, callback) {
+ if (_isFunction(options)) {
+ callback = options;
+ options = {};
+ }
+ this.befores.push([options, callback]);
+ return this;
+ },
+
+ // A shortcut for binding a callback to be run after a route is executed.
+ // After callbacks have no guarunteed order.
+ after: function(callback) {
+ return this.bind('event-context-after', callback);
+ },
+
+
+ // Adds an around filter to the application. around filters are functions
+ // that take a single argument `callback` which is the entire route
+ // execution path wrapped up in a closure. This means you can decide whether
+ // or not to proceed with execution by not invoking `callback` or,
+ // more usefully wrapping callback inside the result of an asynchronous execution.
+ //
+ // ### Example
+ //
+ // The most common use case for around() is calling a _possibly_ async function
+ // and executing the route within the functions callback:
+ //
+ // var app = $.sammy(function() {
+ //
+ // var current_user = false;
+ //
+ // function checkLoggedIn(callback) {
+ // // /session returns a JSON representation of the logged in user
+ // // or an empty object
+ // if (!current_user) {
+ // $.getJSON('/session', function(json) {
+ // if (json.login) {
+ // // show the user as logged in
+ // current_user = json;
+ // // execute the route path
+ // callback();
+ // } else {
+ // // show the user as not logged in
+ // current_user = false;
+ // // the context of aroundFilters is an EventContext
+ // this.redirect('#/login');
+ // }
+ // });
+ // } else {
+ // // execute the route path
+ // callback();
+ // }
+ // };
+ //
+ // this.around(checkLoggedIn);
+ //
+ // });
+ //
+ around: function(callback) {
+ this.arounds.push(callback);
+ return this;
+ },
+
+ // Returns `true` if the current application is running.
+ isRunning: function() {
+ return this._running;
+ },
+
+ // Helpers extends the EventContext prototype specific to this app.
+ // This allows you to define app specific helper functions that can be used
+ // whenever you're inside of an event context (templates, routes, bind).
+ //
+ // ### Example
+ //
+ // var app = $.sammy(function() {
+ //
+ // helpers({
+ // upcase: function(text) {
+ // return text.toString().toUpperCase();
+ // }
+ // });
+ //
+ // get('#/', function() { with(this) {
+ // // inside of this context I can use the helpers
+ // $('#main').html(upcase($('#main').text());
+ // }});
+ //
+ // });
+ //
+ //
+ // ### Arguments
+ //
+ // * `extensions` An object collection of functions to extend the context.
+ //
+ helpers: function(extensions) {
+ $.extend(this.context_prototype.prototype, extensions);
+ return this;
+ },
+
+ // Helper extends the event context just like `helpers()` but does it
+ // a single method at a time. This is especially useful for dynamically named
+ // helpers
+ //
+ // ### Example
+ //
+ // // Trivial example that adds 3 helper methods to the context dynamically
+ // var app = $.sammy(function(app) {
+ //
+ // $.each([1,2,3], function(i, num) {
+ // app.helper('helper' + num, function() {
+ // this.log("I'm helper number " + num);
+ // });
+ // });
+ //
+ // this.get('#/', function() {
+ // this.helper2(); //=> I'm helper number 2
+ // });
+ // });
+ //
+ // ### Arguments
+ //
+ // * `name` The name of the method
+ // * `method` The function to be added to the prototype at `name`
+ //
+ helper: function(name, method) {
+ this.context_prototype.prototype[name] = method;
+ return this;
+ },
+
+ // Actually starts the application's lifecycle. `run()` should be invoked
+ // within a document.ready block to ensure the DOM exists before binding events, etc.
+ //
+ // ### Example
+ //
+ // var app = $.sammy(function() { ... }); // your application
+ // $(function() { // document.ready
+ // app.run();
+ // });
+ //
+ // ### Arguments
+ //
+ // * `start_url` Optionally, a String can be passed which the App will redirect to
+ // after the events/routes have been bound.
+ run: function(start_url) {
+ if (this.isRunning()) { return false; }
+ var app = this;
+
+ // actually bind all the listeners
+ $.each(this.listeners.toHash(), function(name, callbacks) {
+ $.each(callbacks, function(i, listener_callback) {
+ app._listen(name, listener_callback);
+ });
+ });
+
+ this.trigger('run', {start_url: start_url});
+ this._running = true;
+ // set last location
+ this.last_location = null;
+ if (!(/\#(.+)/.test(this.getLocation())) && typeof start_url != 'undefined') {
+ this.setLocation(start_url);
+ }
+ // check url
+ this._checkLocation();
+ this._location_proxy.bind();
+ this.bind('location-changed', function() {
+ app._checkLocation();
+ });
+
+ // bind to submit to capture post/put/delete routes
+ this.bind('submit', function(e) {
+ var returned = app._checkFormSubmission($(e.target).closest('form'));
+ return (returned === false) ? e.preventDefault() : false;
+ });
+
+ // bind unload to body unload
+ $(window).bind('unload', function() {
+ app.unload();
+ });
+
+ // trigger html changed
+ return this.trigger('changed');
+ },
+
+ // The opposite of `run()`, un-binds all event listeners and intervals
+ // `run()` Automatically binds a `onunload` event to run this when
+ // the document is closed.
+ unload: function() {
+ if (!this.isRunning()) { return false; }
+ var app = this;
+ this.trigger('unload');
+ // clear interval
+ this._location_proxy.unbind();
+ // unbind form submits
+ this.$element().unbind('submit').removeClass(app.eventNamespace());
+ // unbind all events
+ $.each(this.listeners.toHash() , function(name, listeners) {
+ $.each(listeners, function(i, listener_callback) {
+ app._unlisten(name, listener_callback);
+ });
+ });
+ this._running = false;
+ return this;
+ },
+
+ // Will bind a single callback function to every event that is already
+ // being listened to in the app. This includes all the `APP_EVENTS`
+ // as well as any custom events defined with `bind()`.
+ //
+ // Used internally for debug logging.
+ bindToAllEvents: function(callback) {
+ var app = this;
+ // bind to the APP_EVENTS first
+ $.each(this.APP_EVENTS, function(i, e) {
+ app.bind(e, callback);
+ });
+ // next, bind to listener names (only if they dont exist in APP_EVENTS)
+ $.each(this.listeners.keys(true), function(i, name) {
+ if ($.inArray(name, app.APP_EVENTS) == -1) {
+ app.bind(name, callback);
+ }
+ });
+ return this;
+ },
+
+ // Returns a copy of the given path with any query string after the hash
+ // removed.
+ routablePath: function(path) {
+ return path.replace(QUERY_STRING_MATCHER, '');
+ },
+
+ // Given a verb and a String path, will return either a route object or false
+ // if a matching route can be found within the current defined set.
+ lookupRoute: function(verb, path) {
+ var app = this, routed = false, i = 0, l, route;
+ if (typeof this.routes[verb] != 'undefined') {
+ l = this.routes[verb].length;
+ for (; i < l; i++) {
+ route = this.routes[verb][i];
+ if (app.routablePath(path).match(route.path)) {
+ routed = route;
+ break;
+ }
+ }
+ }
+ return routed;
+ },
+
+ // First, invokes `lookupRoute()` and if a route is found, parses the
+ // possible URL params and then invokes the route's callback within a new
+ // `Sammy.EventContext`. If the route can not be found, it calls
+ // `notFound()`. If `raise_errors` is set to `true` and
+ // the `error()` has not been overridden, it will throw an actual JS
+ // error.
+ //
+ // You probably will never have to call this directly.
+ //
+ // ### Arguments
+ //
+ // * `verb` A String for the verb.
+ // * `path` A String path to lookup.
+ // * `params` An Object of Params pulled from the URI or passed directly.
+ //
+ // ### Returns
+ //
+ // Either returns the value returned by the route callback or raises a 404 Not Found error.
+ //
+ runRoute: function(verb, path, params, target) {
+ var app = this,
+ route = this.lookupRoute(verb, path),
+ context,
+ wrapped_route,
+ arounds,
+ around,
+ befores,
+ before,
+ callback_args,
+ path_params,
+ final_returned;
+
+ this.log('runRoute', [verb, path].join(' '));
+ this.trigger('run-route', {verb: verb, path: path, params: params});
+ if (typeof params == 'undefined') { params = {}; }
+
+ $.extend(params, this._parseQueryString(path));
+
+ if (route) {
+ this.trigger('route-found', {route: route});
+ // pull out the params from the path
+ if ((path_params = route.path.exec(this.routablePath(path))) !== null) {
+ // first match is the full path
+ path_params.shift();
+ // for each of the matches
+ $.each(path_params, function(i, param) {
+ // if theres a matching param name
+ if (route.param_names[i]) {
+ // set the name to the match
+ params[route.param_names[i]] = _decode(param);
+ } else {
+ // initialize 'splat'
+ if (!params.splat) { params.splat = []; }
+ params.splat.push(_decode(param));
+ }
+ });
+ }
+
+ // set event context
+ context = new this.context_prototype(this, verb, path, params, target);
+ // ensure arrays
+ arounds = this.arounds.slice(0);
+ befores = this.befores.slice(0);
+ // set the callback args to the context + contents of the splat
+ callback_args = [context].concat(params.splat);
+ // wrap the route up with the before filters
+ wrapped_route = function() {
+ var returned;
+ while (befores.length > 0) {
+ before = befores.shift();
+ // check the options
+ if (app.contextMatchesOptions(context, before[0])) {
+ returned = before[1].apply(context, [context]);
+ if (returned === false) { return false; }
+ }
+ }
+ app.last_route = route;
+ context.trigger('event-context-before', {context: context});
+ returned = route.callback.apply(context, callback_args);
+ context.trigger('event-context-after', {context: context});
+ return returned;
+ };
+ $.each(arounds.reverse(), function(i, around) {
+ var last_wrapped_route = wrapped_route;
+ wrapped_route = function() { return around.apply(context, [last_wrapped_route]); };
+ });
+ try {
+ final_returned = wrapped_route();
+ } catch(e) {
+ this.error(['500 Error', verb, path].join(' '), e);
+ }
+ return final_returned;
+ } else {
+ return this.notFound(verb, path);
+ }
+ },
+
+ // Matches an object of options against an `EventContext` like object that
+ // contains `path` and `verb` attributes. Internally Sammy uses this
+ // for matching `before()` filters against specific options. You can set the
+ // object to _only_ match certain paths or verbs, or match all paths or verbs _except_
+ // those that match the options.
+ //
+ // ### Example
+ //
+ // var app = $.sammy(),
+ // context = {verb: 'get', path: '#/mypath'};
+ //
+ // // match against a path string
+ // app.contextMatchesOptions(context, '#/mypath'); //=> true
+ // app.contextMatchesOptions(context, '#/otherpath'); //=> false
+ // // equivalent to
+ // app.contextMatchesOptions(context, {only: {path:'#/mypath'}}); //=> true
+ // app.contextMatchesOptions(context, {only: {path:'#/otherpath'}}); //=> false
+ // // match against a path regexp
+ // app.contextMatchesOptions(context, /path/); //=> true
+ // app.contextMatchesOptions(context, /^path/); //=> false
+ // // match only a verb
+ // app.contextMatchesOptions(context, {only: {verb:'get'}}); //=> true
+ // app.contextMatchesOptions(context, {only: {verb:'post'}}); //=> false
+ // // match all except a verb
+ // app.contextMatchesOptions(context, {except: {verb:'post'}}); //=> true
+ // app.contextMatchesOptions(context, {except: {verb:'get'}}); //=> false
+ // // match all except a path
+ // app.contextMatchesOptions(context, {except: {path:'#/otherpath'}}); //=> true
+ // app.contextMatchesOptions(context, {except: {path:'#/mypath'}}); //=> false
+ // // match multiple paths
+ // app.contextMatchesOptions(context, {path: ['#/mypath', '#/otherpath']}); //=> true
+ // app.contextMatchesOptions(context, {path: ['#/otherpath', '#/thirdpath']}); //=> false
+ // // equivalent to
+ // app.contextMatchesOptions(context, {only: {path: ['#/mypath', '#/otherpath']}}); //=> true
+ // app.contextMatchesOptions(context, {only: {path: ['#/otherpath', '#/thirdpath']}}); //=> false
+ // // match all except multiple paths
+ // app.contextMatchesOptions(context, {except: {path: ['#/mypath', '#/otherpath']}}); //=> false
+ // app.contextMatchesOptions(context, {except: {path: ['#/otherpath', '#/thirdpath']}}); //=> true
+ //
+ contextMatchesOptions: function(context, match_options, positive) {
+ var options = match_options;
+ // normalize options
+ if (typeof options === 'string' || _isRegExp(options)) {
+ options = {path: options};
+ }
+ if (typeof positive === 'undefined') {
+ positive = true;
+ }
+ // empty options always match
+ if ($.isEmptyObject(options)) {
+ return true;
+ }
+ // Do we have to match against multiple paths?
+ if (_isArray(options.path)){
+ var results, numopt, opts;
+ results = [];
+ for (numopt in options.path){
+ opts = $.extend({}, options, {path: options.path[numopt]});
+ results.push(this.contextMatchesOptions(context, opts));
+ }
+ var matched = $.inArray(true, results) > -1 ? true : false;
+ return positive ? matched : !matched;
+ }
+ if (options.only) {
+ return this.contextMatchesOptions(context, options.only, true);
+ } else if (options.except) {
+ return this.contextMatchesOptions(context, options.except, false);
+ }
+ var path_matched = true, verb_matched = true;
+ if (options.path) {
+ if (!_isRegExp(options.path)) {
+ options.path = new RegExp(options.path.toString() + '$');
+ }
+ path_matched = options.path.test(context.path);
+ }
+ if (options.verb) {
+ if(typeof options.verb === 'string') {
+ verb_matched = options.verb === context.verb;
+ } else {
+ verb_matched = options.verb.indexOf(context.verb) > -1;
+ }
+ }
+ return positive ? (verb_matched && path_matched) : !(verb_matched && path_matched);
+ },
+
+
+ // Delegates to the `location_proxy` to get the current location.
+ // See `Sammy.DefaultLocationProxy` for more info on location proxies.
+ getLocation: function() {
+ return this._location_proxy.getLocation();
+ },
+
+ // Delegates to the `location_proxy` to set the current location.
+ // See `Sammy.DefaultLocationProxy` for more info on location proxies.
+ //
+ // ### Arguments
+ //
+ // * `new_location` A new location string (e.g. '#/')
+ //
+ setLocation: function(new_location) {
+ return this._location_proxy.setLocation(new_location);
+ },
+
+ // Swaps the content of `$element()` with `content`
+ // You can override this method to provide an alternate swap behavior
+ // for `EventContext.partial()`.
+ //
+ // ### Example
+ //
+ // var app = $.sammy(function() {
+ //
+ // // implements a 'fade out'/'fade in'
+ // this.swap = function(content, callback) {
+ // var context = this;
+ // context.$element().fadeOut('slow', function() {
+ // context.$element().html(content);
+ // context.$element().fadeIn('slow', function() {
+ // if (callback) {
+ // callback.apply();
+ // }
+ // });
+ // });
+ // };
+ //
+ // });
+ //
+ swap: function(content, callback) {
+ var $el = this.$element().html(content);
+ if (_isFunction(callback)) { callback(content); }
+ return $el;
+ },
+
+ // a simple global cache for templates. Uses the same semantics as
+ // `Sammy.Cache` and `Sammy.Storage` so can easily be replaced with
+ // a persistent storage that lasts beyond the current request.
+ templateCache: function(key, value) {
+ if (typeof value != 'undefined') {
+ return _template_cache[key] = value;
+ } else {
+ return _template_cache[key];
+ }
+ },
+
+ // clear the templateCache
+ clearTemplateCache: function() {
+ return _template_cache = {};
+ },
+
+ // This throws a '404 Not Found' error by invoking `error()`.
+ // Override this method or `error()` to provide custom
+ // 404 behavior (i.e redirecting to / or showing a warning)
+ notFound: function(verb, path) {
+ var ret = this.error(['404 Not Found', verb, path].join(' '));
+ return (verb === 'get') ? ret : true;
+ },
+
+ // The base error handler takes a string `message` and an `Error`
+ // object. If `raise_errors` is set to `true` on the app level,
+ // this will re-throw the error to the browser. Otherwise it will send the error
+ // to `log()`. Override this method to provide custom error handling
+ // e.g logging to a server side component or displaying some feedback to the
+ // user.
+ error: function(message, original_error) {
+ if (!original_error) { original_error = new Error(); }
+ original_error.message = [message, original_error.message].join(' ');
+ this.trigger('error', {message: original_error.message, error: original_error});
+ if (this.raise_errors) {
+ throw(original_error);
+ } else {
+ this.log(original_error.message, original_error);
+ }
+ },
+
+ _checkLocation: function() {
+ var location, returned;
+ // get current location
+ location = this.getLocation();
+ // compare to see if hash has changed
+ if (!this.last_location || this.last_location[0] != 'get' || this.last_location[1] != location) {
+ // reset last location
+ this.last_location = ['get', location];
+ // lookup route for current hash
+ returned = this.runRoute('get', location);
+ }
+ return returned;
+ },
+
+ _getFormVerb: function(form) {
+ var $form = $(form), verb, $_method;
+ $_method = $form.find('input[name="_method"]');
+ if ($_method.length > 0) { verb = $_method.val(); }
+ if (!verb) { verb = $form[0].getAttribute('method'); }
+ if (!verb || verb == '') { verb = 'get'; }
+ return $.trim(verb.toString().toLowerCase());
+ },
+
+ _checkFormSubmission: function(form) {
+ var $form, path, verb, params, returned;
+ this.trigger('check-form-submission', {form: form});
+ $form = $(form);
+ path = $form.attr('action') || '';
+ verb = this._getFormVerb($form);
+ this.log('_checkFormSubmission', $form, path, verb);
+ if (verb === 'get') {
+ params = this._serializeFormParams($form);
+ if (params !== '') { path += '?' + params; }
+ this.setLocation(path);
+ returned = false;
+ } else {
+ params = $.extend({}, this._parseFormParams($form));
+ returned = this.runRoute(verb, path, params, form.get(0));
+ }
+ return (typeof returned == 'undefined') ? false : returned;
+ },
+
+ _serializeFormParams: function($form) {
+ var queryString = "",
+ fields = $form.serializeArray(),
+ i;
+ if (fields.length > 0) {
+ queryString = this._encodeFormPair(fields[0].name, fields[0].value);
+ for (i = 1; i < fields.length; i++) {
+ queryString = queryString + "&" + this._encodeFormPair(fields[i].name, fields[i].value);
+ }
+ }
+ return queryString;
+ },
+
+ _encodeFormPair: function(name, value){
+ return _encode(name) + "=" + _encode(value);
+ },
+
+ _parseFormParams: function($form) {
+ var params = {},
+ form_fields = $form.serializeArray(),
+ i;
+ for (i = 0; i < form_fields.length; i++) {
+ params = this._parseParamPair(params, form_fields[i].name, form_fields[i].value);
+ }
+ return params;
+ },
+
+ _parseQueryString: function(path) {
+ var params = {}, parts, pairs, pair, i;
+
+ parts = path.match(QUERY_STRING_MATCHER);
+ if (parts && parts[1]) {
+ pairs = parts[1].split('&');
+ for (i = 0; i < pairs.length; i++) {
+ pair = pairs[i].split('=');
+ params = this._parseParamPair(params, _decode(pair[0]), _decode(pair[1] || ""));
+ }
+ }
+ return params;
+ },
+
+ _parseParamPair: function(params, key, value) {
+ if (typeof params[key] !== 'undefined') {
+ if (_isArray(params[key])) {
+ params[key].push(value);
+ } else {
+ params[key] = [params[key], value];
+ }
+ } else {
+ params[key] = value;
+ }
+ return params;
+ },
+
+ _listen: function(name, callback) {
+ return this.$element().bind([name, this.eventNamespace()].join('.'), callback);
+ },
+
+ _unlisten: function(name, callback) {
+ return this.$element().unbind([name, this.eventNamespace()].join('.'), callback);
+ }
+
+ });
+
+ // `Sammy.RenderContext` is an object that makes sequential template loading,
+ // rendering and interpolation seamless even when dealing with asynchronous
+ // operations.
+ //
+ // `RenderContext` objects are not usually created directly, rather they are
+ // instantiated from an `Sammy.EventContext` by using `render()`, `load()` or
+ // `partial()` which all return `RenderContext` objects.
+ //
+ // `RenderContext` methods always returns a modified `RenderContext`
+ // for chaining (like jQuery itself).
+ //
+ // The core magic is in the `then()` method which puts the callback passed as
+ // an argument into a queue to be executed once the previous callback is complete.
+ // All the methods of `RenderContext` are wrapped in `then()` which allows you
+ // to queue up methods by chaining, but maintaining a guaranteed execution order
+ // even with remote calls to fetch templates.
+ //
+ Sammy.RenderContext = function(event_context) {
+ this.event_context = event_context;
+ this.callbacks = [];
+ this.previous_content = null;
+ this.content = null;
+ this.next_engine = false;
+ this.waiting = false;
+ };
+
+ Sammy.RenderContext.prototype = $.extend({}, Sammy.Object.prototype, {
+
+ // The "core" of the `RenderContext` object, adds the `callback` to the
+ // queue. If the context is `waiting` (meaning an async operation is happening)
+ // then the callback will be executed in order, once the other operations are
+ // complete. If there is no currently executing operation, the `callback`
+ // is executed immediately.
+ //
+ // The value returned from the callback is stored in `content` for the
+ // subsequent operation. If you return `false`, the queue will pause, and
+ // the next callback in the queue will not be executed until `next()` is
+ // called. This allows for the guaranteed order of execution while working
+ // with async operations.
+ //
+ // If then() is passed a string instead of a function, the string is looked
+ // up as a helper method on the event context.
+ //
+ // ### Example
+ //
+ // this.get('#/', function() {
+ // // initialize the RenderContext
+ // // Even though `load()` executes async, the next `then()`
+ // // wont execute until the load finishes
+ // this.load('myfile.txt')
+ // .then(function(content) {
+ // // the first argument to then is the content of the
+ // // prev operation
+ // $('#main').html(content);
+ // });
+ // });
+ //
+ then: function(callback) {
+ if (!_isFunction(callback)) {
+ // if a string is passed to then, assume we want to call
+ // a helper on the event context in its context
+ if (typeof callback === 'string' && callback in this.event_context) {
+ var helper = this.event_context[callback];
+ callback = function(content) {
+ return helper.apply(this.event_context, [content]);
+ };
+ } else {
+ return this;
+ }
+ }
+ var context = this;
+ if (this.waiting) {
+ this.callbacks.push(callback);
+ } else {
+ this.wait();
+ window.setTimeout(function() {
+ var returned = callback.apply(context, [context.content, context.previous_content]);
+ if (returned !== false) {
+ context.next(returned);
+ }
+ }, 0);
+ }
+ return this;
+ },
+
+ // Pause the `RenderContext` queue. Combined with `next()` allows for async
+ // operations.
+ //
+ // ### Example
+ //
+ // this.get('#/', function() {
+ // this.load('mytext.json')
+ // .then(function(content) {
+ // var context = this,
+ // data = JSON.parse(content);
+ // // pause execution
+ // context.wait();
+ // // post to a url
+ // $.post(data.url, {}, function(response) {
+ // context.next(JSON.parse(response));
+ // });
+ // })
+ // .then(function(data) {
+ // // data is json from the previous post
+ // $('#message').text(data.status);
+ // });
+ // });
+ wait: function() {
+ this.waiting = true;
+ },
+
+ // Resume the queue, setting `content` to be used in the next operation.
+ // See `wait()` for an example.
+ next: function(content) {
+ this.waiting = false;
+ if (typeof content !== 'undefined') {
+ this.previous_content = this.content;
+ this.content = content;
+ }
+ if (this.callbacks.length > 0) {
+ this.then(this.callbacks.shift());
+ }
+ },
+
+ // Load a template into the context.
+ // The `location` can either be a string specifying the remote path to the
+ // file, a jQuery object, or a DOM element.
+ //
+ // No interpolation happens by default, the content is stored in
+ // `content`.
+ //
+ // In the case of a path, unless the option `{cache: false}` is passed the
+ // data is stored in the app's `templateCache()`.
+ //
+ // If a jQuery or DOM object is passed the `innerHTML` of the node is pulled in.
+ // This is useful for nesting templates as part of the initial page load wrapped
+ // in invisible elements or `<script>` tags. With template paths, the template
+ // engine is looked up by the extension. For DOM/jQuery embedded templates,
+ // this isnt possible, so there are a couple of options:
+ //
+ // * pass an `{engine:}` option.
+ // * define the engine in the `data-engine` attribute of the passed node.
+ // * just store the raw template data and use `interpolate()` manually
+ //
+ // If a `callback` is passed it is executed after the template load.
+ load: function(location, options, callback) {
+ var context = this;
+ return this.then(function() {
+ var should_cache, cached, is_json, location_array;
+ if (_isFunction(options)) {
+ callback = options;
+ options = {};
+ } else {
+ options = $.extend({}, options);
+ }
+ if (callback) { this.then(callback); }
+ if (typeof location === 'string') {
+ // it's a path
+ is_json = (location.match(/\.json$/) || options.json);
+ should_cache = is_json ? options.cache === true : options.cache !== false;
+ context.next_engine = context.event_context.engineFor(location);
+ delete options.cache;
+ delete options.json;
+ if (options.engine) {
+ context.next_engine = options.engine;
+ delete options.engine;
+ }
+ if (should_cache && (cached = this.event_context.app.templateCache(location))) {
+ return cached;
+ }
+ this.wait();
+ $.ajax($.extend({
+ url: location,
+ data: {},
+ dataType: is_json ? 'json' : 'text',
+ type: 'get',
+ success: function(data) {
+ if (should_cache) {
+ context.event_context.app.templateCache(location, data);
+ }
+ context.next(data);
+ }
+ }, options));
+ return false;
+ } else {
+ // it's a dom/jQuery
+ if (location.nodeType) {
+ return location.innerHTML;
+ }
+ if (location.selector) {
+ // it's a jQuery
+ context.next_engine = location.attr('data-engine');
+ if (options.clone === false) {
+ return location.remove()[0].innerHTML.toString();
+ } else {
+ return location[0].innerHTML.toString();
+ }
+ }
+ }
+ });
+ },
+
+ // Load partials
+ //
+ // ### Example
+ //
+ // this.loadPartials({mypartial: '/path/to/partial'});
+ //
+ loadPartials: function(partials) {
+ var name;
+ if(partials) {
+ this.partials = this.partials || {};
+ for(name in partials) {
+ (function(context, name) {
+ context.load(partials[name])
+ .then(function(template) {
+ this.partials[name] = template;
+ });
+ })(this, name);
+ }
+ }
+ return this;
+ },
+
+ // `load()` a template and then `interpolate()` it with data.
+ //
+ // can be called with multiple different signatures:
+ //
+ // this.render(callback);
+ // this.render('/location');
+ // this.render('/location', {some: data});
+ // this.render('/location', callback);
+ // this.render('/location', {some: data}, callback);
+ // this.render('/location', {some: data}, {my: partials});
+ // this.render('/location', callback, {my: partials});
+ // this.render('/location', {some: data}, callback, {my: partials});
+ //
+ // ### Example
+ //
+ // this.get('#/', function() {
+ // this.render('mytemplate.template', {name: 'test'});
+ // });
+ //
+ render: function(location, data, callback, partials) {
+ if (_isFunction(location) && !data) {
+ // invoked as render(callback)
+ return this.then(location);
+ } else {
+ if(_isFunction(data)) {
+ // invoked as render(location, callback, [partials])
+ partials = callback;
+ callback = data;
+ data = null;
+ } else if(callback && !_isFunction(callback)) {
+ // invoked as render(location, data, partials)
+ partials = callback;
+ callback = null;
+ }
+
+ return this.loadPartials(partials)
+ .load(location)
+ .interpolate(data, location)
+ .then(callback);
+ }
+ },
+
+ // `render()` the `location` with `data` and then `swap()` the
+ // app's `$element` with the rendered content.
+ partial: function(location, data, callback, partials) {
+ if (_isFunction(callback)) {
+ // invoked as partial(location, data, callback, [partials])
+ return this.render(location, data, partials).swap(callback);
+ } else if (_isFunction(data)) {
+ // invoked as partial(location, callback, [partials])
+ return this.render(location, {}, callback).swap(data);
+ } else {
+ // invoked as partial(location, data, [partials])
+ return this.render(location, data, callback).swap();
+ }
+ },
+
+ // defers the call of function to occur in order of the render queue.
+ // The function can accept any number of arguments as long as the last
+ // argument is a callback function. This is useful for putting arbitrary
+ // asynchronous functions into the queue. The content passed to the
+ // callback is passed as `content` to the next item in the queue.
+ //
+ // ### Example
+ //
+ // this.send($.getJSON, '/app.json')
+ // .then(function(json) {
+ // $('#message).text(json['message']);
+ // });
+ //
+ //
+ send: function() {
+ var context = this,
+ args = _makeArray(arguments),
+ fun = args.shift();
+
+ if (_isArray(args[0])) { args = args[0]; }
+
+ return this.then(function(content) {
+ args.push(function(response) { context.next(response); });
+ context.wait();
+ fun.apply(fun, args);
+ return false;
+ });
+ },
+
+ // iterates over an array, applying the callback for each item item. the
+ // callback takes the same style of arguments as `jQuery.each()` (index, item).
+ // The return value of each callback is collected as a single string and stored
+ // as `content` to be used in the next iteration of the `RenderContext`.
+ collect: function(array, callback, now) {
+ var context = this;
+ var coll = function() {
+ if (_isFunction(array)) {
+ callback = array;
+ array = this.content;
+ }
+ var contents = [], doms = false;
+ $.each(array, function(i, item) {
+ var returned = callback.apply(context, [i, item]);
+ if (returned.jquery && returned.length == 1) {
+ returned = returned[0];
+ doms = true;
+ }
+ contents.push(returned);
+ return returned;
+ });
+ return doms ? contents : contents.join('');
+ };
+ return now ? coll() : this.then(coll);
+ },
+
+ // loads a template, and then interpolates it for each item in the `data`
+ // array. If a callback is passed, it will call the callback with each
+ // item in the array _after_ interpolation
+ renderEach: function(location, name, data, callback) {
+ if (_isArray(name)) {
+ callback = data;
+ data = name;
+ name = null;
+ }
+ return this.load(location).then(function(content) {
+ var rctx = this;
+ if (!data) {
+ data = _isArray(this.previous_content) ? this.previous_content : [];
+ }
+ if (callback) {
+ $.each(data, function(i, value) {
+ var idata = {}, engine = this.next_engine || location;
+ name ? (idata[name] = value) : (idata = value);
+ callback(value, rctx.event_context.interpolate(content, idata, engine));
+ });
+ } else {
+ return this.collect(data, function(i, value) {
+ var idata = {}, engine = this.next_engine || location;
+ name ? (idata[name] = value) : (idata = value);
+ return this.event_context.interpolate(content, idata, engine);
+ }, true);
+ }
+ });
+ },
+
+ // uses the previous loaded `content` and the `data` object to interpolate
+ // a template. `engine` defines the templating/interpolation method/engine
+ // that should be used. If `engine` is not passed, the `next_engine` is
+ // used. If `retain` is `true`, the final interpolated data is appended to
+ // the `previous_content` instead of just replacing it.
+ interpolate: function(data, engine, retain) {
+ var context = this;
+ return this.then(function(content, prev) {
+ if (!data && prev) { data = prev; }
+ if (this.next_engine) {
+ engine = this.next_engine;
+ this.next_engine = false;
+ }
+ var rendered = context.event_context.interpolate(content, data, engine, this.partials);
+ return retain ? prev + rendered : rendered;
+ });
+ },
+
+ // Swap the return contents ensuring order. See `Application#swap`
+ swap: function(callback) {
+ return this.then(function(content) {
+ this.event_context.swap(content, callback);
+ return content;
+ }).trigger('changed', {});
+ },
+
+ // Same usage as `jQuery.fn.appendTo()` but uses `then()` to ensure order
+ appendTo: function(selector) {
+ return this.then(function(content) {
+ $(selector).append(content);
+ }).trigger('changed', {});
+ },
+
+ // Same usage as `jQuery.fn.prependTo()` but uses `then()` to ensure order
+ prependTo: function(selector) {
+ return this.then(function(content) {
+ $(selector).prepend(content);
+ }).trigger('changed', {});
+ },
+
+ // Replaces the `$(selector)` using `html()` with the previously loaded
+ // `content`
+ replace: function(selector) {
+ return this.then(function(content) {
+ $(selector).html(content);
+ }).trigger('changed', {});
+ },
+
+ // trigger the event in the order of the event context. Same semantics
+ // as `Sammy.EventContext#trigger()`. If data is omitted, `content`
+ // is sent as `{content: content}`
+ trigger: function(name, data) {
+ return this.then(function(content) {
+ if (typeof data == 'undefined') { data = {content: content}; }
+ this.event_context.trigger(name, data);
+ return content;
+ });
+ }
+
+ });
+
+ // `Sammy.EventContext` objects are created every time a route is run or a
+ // bound event is triggered. The callbacks for these events are evaluated within a `Sammy.EventContext`
+ // This within these callbacks the special methods of `EventContext` are available.
+ //
+ // ### Example
+ //
+ // $.sammy(function() {
+ // // The context here is this Sammy.Application
+ // this.get('#/:name', function() {
+ // // The context here is a new Sammy.EventContext
+ // if (this.params['name'] == 'sammy') {
+ // this.partial('name.html.erb', {name: 'Sammy'});
+ // } else {
+ // this.redirect('#/somewhere-else')
+ // }
+ // });
+ // });
+ //
+ // Initialize a new EventContext
+ //
+ // ### Arguments
+ //
+ // * `app` The `Sammy.Application` this event is called within.
+ // * `verb` The verb invoked to run this context/route.
+ // * `path` The string path invoked to run this context/route.
+ // * `params` An Object of optional params to pass to the context. Is converted
+ // to a `Sammy.Object`.
+ // * `target` a DOM element that the event that holds this context originates
+ // from. For post, put and del routes, this is the form element that triggered
+ // the route.
+ //
+ Sammy.EventContext = function(app, verb, path, params, target) {
+ this.app = app;
+ this.verb = verb;
+ this.path = path;
+ this.params = new Sammy.Object(params);
+ this.target = target;
+ };
+
+ Sammy.EventContext.prototype = $.extend({}, Sammy.Object.prototype, {
+
+ // A shortcut to the app's `$element()`
+ $element: function() {
+ return this.app.$element(_makeArray(arguments).shift());
+ },
+
+ // Look up a templating engine within the current app and context.
+ // `engine` can be one of the following:
+ //
+ // * a function: should conform to `function(content, data) { return interpolated; }`
+ // * a template path: 'template.ejs', looks up the extension to match to
+ // the `ejs()` helper
+ // * a string referring to the helper: "mustache" => `mustache()`
+ //
+ // If no engine is found, use the app's default `template_engine`
+ //
+ engineFor: function(engine) {
+ var context = this, engine_match;
+ // if path is actually an engine function just return it
+ if (_isFunction(engine)) { return engine; }
+ // lookup engine name by path extension
+ engine = (engine || context.app.template_engine).toString();
+ if ((engine_match = engine.match(/\.([^\.\?\#]+)$/))) {
+ engine = engine_match[1];
+ }
+ // set the engine to the default template engine if no match is found
+ if (engine && _isFunction(context[engine])) {
+ return context[engine];
+ }
+
+ if (context.app.template_engine) {
+ return this.engineFor(context.app.template_engine);
+ }
+ return function(content, data) { return content; };
+ },
+
+ // using the template `engine` found with `engineFor()`, interpolate the
+ // `data` into `content`
+ interpolate: function(content, data, engine, partials) {
+ return this.engineFor(engine).apply(this, [content, data, partials]);
+ },
+
+ // Create and return a `Sammy.RenderContext` calling `render()` on it.
+ // Loads the template and interpolate the data, however does not actual
+ // place it in the DOM.
+ //
+ // ### Example
+ //
+ // // mytemplate.mustache <div class="name">{{name}}</div>
+ // render('mytemplate.mustache', {name: 'quirkey'});
+ // // sets the `content` to <div class="name">quirkey</div>
+ // render('mytemplate.mustache', {name: 'quirkey'})
+ // .appendTo('ul');
+ // // appends the rendered content to $('ul')
+ //
+ render: function(location, data, callback, partials) {
+ return new Sammy.RenderContext(this).render(location, data, callback, partials);
+ },
+
+ // Create and return a `Sammy.RenderContext` calling `renderEach()` on it.
+ // Loads the template and interpolates the data for each item,
+ // however does not actual place it in the DOM.
+ //
+ // ### Example
+ //
+ // // mytemplate.mustache <div class="name">{{name}}</div>
+ // renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}])
+ // // sets the `content` to <div class="name">quirkey</div><div class="name">endor</div>
+ // renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}]).appendTo('ul');
+ // // appends the rendered content to $('ul')
+ //
+ renderEach: function(location, name, data, callback) {
+ return new Sammy.RenderContext(this).renderEach(location, name, data, callback);
+ },
+
+ // create a new `Sammy.RenderContext` calling `load()` with `location` and
+ // `options`. Called without interpolation or placement, this allows for
+ // preloading/caching the templates.
+ load: function(location, options, callback) {
+ return new Sammy.RenderContext(this).load(location, options, callback);
+ },
+
+ // `render()` the `location` with `data` and then `swap()` the
+ // app's `$element` with the rendered content.
+ partial: function(location, data, callback, partials) {
+ return new Sammy.RenderContext(this).partial(location, data, callback, partials);
+ },
+
+ // create a new `Sammy.RenderContext` calling `send()` with an arbitrary
+ // function
+ send: function() {
+ var rctx = new Sammy.RenderContext(this);
+ return rctx.send.apply(rctx, arguments);
+ },
+
+ // Changes the location of the current window. If `to` begins with
+ // '#' it only changes the document's hash. If passed more than 1 argument
+ // redirect will join them together with forward slashes.
+ //
+ // ### Example
+ //
+ // redirect('#/other/route');
+ // // equivalent to
+ // redirect('#', 'other', 'route');
+ //
+ redirect: function() {
+ var to, args = _makeArray(arguments),
+ current_location = this.app.getLocation(),
+ l = args.length;
+ if (l > 1) {
+ var i = 0, paths = [], pairs = [], params = {}, has_params = false;
+ for (; i < l; i++) {
+ if (typeof args[i] == 'string') {
+ paths.push(args[i]);
+ } else {
+ $.extend(params, args[i]);
+ has_params = true;
+ }
+ }
+ to = paths.join('/');
+ if (has_params) {
+ for (var k in params) {
+ pairs.push(this.app._encodeFormPair(k, params[k]));
+ }
+ to += '?' + pairs.join('&');
+ }
+ } else {
+ to = args[0];
+ }
+ this.trigger('redirect', {to: to});
+ this.app.last_location = [this.verb, this.path];
+ this.app.setLocation(to);
+ if (new RegExp(to).test(current_location)) {
+ this.app.trigger('location-changed');
+ }
+ },
+
+ // Triggers events on `app` within the current context.
+ trigger: function(name, data) {
+ if (typeof data == 'undefined') { data = {}; }
+ if (!data.context) { data.context = this; }
+ return this.app.trigger(name, data);
+ },
+
+ // A shortcut to app's `eventNamespace()`
+ eventNamespace: function() {
+ return this.app.eventNamespace();
+ },
+
+ // A shortcut to app's `swap()`
+ swap: function(contents, callback) {
+ return this.app.swap(contents, callback);
+ },
+
+ // Raises a possible `notFound()` error for the current path.
+ notFound: function() {
+ return this.app.notFound(this.verb, this.path);
+ },
+
+ // Default JSON parsing uses jQuery's `parseJSON()`. Include `Sammy.JSON`
+ // plugin for the more conformant "crockford special".
+ json: function(string) {
+ return $.parseJSON(string);
+ },
+
+ // //=> Sammy.EventContext: get #/ {}
+ toString: function() {
+ return "Sammy.EventContext: " + [this.verb, this.path, this.params].join(' ');
+ }
+
+ });
+
+ return Sammy;
+});
+})(jQuery, window);
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/select2.min-3.2.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/select2.min-3.2.js
new file mode 100755
index 000000000..152373565
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/select2.min-3.2.js
@@ -0,0 +1,82 @@
+/*
+Copyright 2012 Igor Vaynberg
+
+Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in
+compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License is
+distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and limitations under the License.
+*/
+(function(e){"undefined"==typeof e.fn.each2&&e.fn.extend({each2:function(g){for(var i=e([0]),m=-1,s=this.length;++m<s&&(i.context=i[0]=this[m])&&!1!==g.call(i[0],m,i););return this}})})(jQuery);
+(function(e,g){function i(a,b){var c=0,d=b.length,j;if("undefined"===typeof a)return-1;if(a.constructor===String)for(;c<d;c+=1){if(0===a.localeCompare(b[c]))return c}else for(;c<d;c+=1)if(j=b[c],j.constructor===String){if(0===j.localeCompare(a))return c}else if(j===a)return c;return-1}function m(a,b){return a===b?!0:a===g||b===g||null===a||null===b?!1:a.constructor===String?0===a.localeCompare(b):b.constructor===String?0===b.localeCompare(a):!1}function s(a,b){var c,d,j;if(null===a||1>a.length)return[];
+c=a.split(b);d=0;for(j=c.length;d<j;d+=1)c[d]=e.trim(c[d]);return c}function A(a,b,c){var c=c||g,d;return function(){var j=arguments;window.clearTimeout(d);d=window.setTimeout(function(){b.apply(c,j)},a)}}function l(a){a.preventDefault();a.stopPropagation()}function B(a,b,c){var d=a.toUpperCase().indexOf(b.toUpperCase()),b=b.length;0>d?c.push(a):(c.push(a.substring(0,d)),c.push("<span class='select2-match'>"),c.push(a.substring(d,d+b)),c.push("</span>"),c.push(a.substring(d+b,a.length)))}function C(a){var b,
+c=0,d=null,j=a.quietMillis||100;return function(h){window.clearTimeout(b);b=window.setTimeout(function(){var b=c+=1,j=a.data,n=a.transport||e.ajax,f=a.traditional||!1,g=a.type||"GET",j=j.call(this,h.term,h.page,h.context);null!==d&&d.abort();d=n.call(null,{url:a.url,dataType:a.dataType,data:j,type:g,traditional:f,success:function(d){b<c||(d=a.results(d,h.page),h.callback(d))}})},j)}}function D(a){var b=a,c,d=function(a){return""+a.text};e.isArray(b)||(d=b.text,e.isFunction(d)||(c=b.text,d=function(a){return a[c]}),
+b=b.results);return function(a){var c=a.term,f={results:[]},k;if(c==="")a.callback({results:b});else{k=function(b,f){var g,t,b=b[0];if(b.children){g={};for(t in b)b.hasOwnProperty(t)&&(g[t]=b[t]);g.children=[];e(b.children).each2(function(a,b){k(b,g.children)});g.children.length&&f.push(g)}else a.matcher(c,d(b))&&f.push(b)};e(b).each2(function(a,b){k(b,f.results)});a.callback(f)}}}function E(a){return e.isFunction(a)?a:function(b){var c=b.term,d={results:[]};e(a).each(function(){var a=this.text!==
+g,e=a?this.text:this;if(""===c||b.matcher(c,e))d.results.push(a?this:{id:this,text:this})});b.callback(d)}}function u(a){if(e.isFunction(a))return!0;if(!a)return!1;throw Error("formatterName must be a function or a falsy value");}function v(a){return e.isFunction(a)?a():a}function F(a){var b=0;e.each(a,function(a,d){d.children?b+=F(d.children):b++});return b}function H(a,b,c,d){var e=a,h=!1,f,k,n,o;if(!d.createSearchChoice||!d.tokenSeparators||1>d.tokenSeparators.length)return g;for(;;){h=-1;k=0;
+for(n=d.tokenSeparators.length;k<n&&!(o=d.tokenSeparators[k],h=a.indexOf(o),0<=h);k++);if(0>h)break;f=a.substring(0,h);a=a.substring(h+o.length);if(0<f.length&&(f=d.createSearchChoice(f,b),f!==g&&null!==f&&d.id(f)!==g&&null!==d.id(f))){h=!1;k=0;for(n=b.length;k<n;k++)if(m(d.id(f),d.id(b[k]))){h=!0;break}h||c(f)}}if(0!=e.localeCompare(a))return a}function x(a,b){var c=function(){};c.prototype=new a;c.prototype.constructor=c;c.prototype.parent=a.prototype;c.prototype=e.extend(c.prototype,b);return c}
+if(window.Select2===g){var f,w,y,z,G,q;f={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){a=a.which?a.which:a;switch(a){case f.LEFT:case f.RIGHT:case f.UP:case f.DOWN:return!0}return!1},isControl:function(a){switch(a.which){case f.SHIFT:case f.CTRL:case f.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){a=a.which?a.which:a;return 112<=a&&123>=a}};var I=1;G=function(){return I++};
+e(document).delegate("body","mousemove",function(a){e.data(document,"select2-lastpos",{x:a.pageX,y:a.pageY})});e(document).ready(function(){e(document).delegate("body","mousedown touchend",function(a){var b=e(a.target).closest("div.select2-container").get(0),c;b?e(document).find("div.select2-container-active").each(function(){this!==b&&e(this).data("select2").blur()}):(b=e(a.target).closest("div.select2-drop").get(0),e(document).find("div.select2-drop-active").each(function(){this!==b&&e(this).data("select2").blur()}));
+b=e(a.target);c=b.attr("for");"LABEL"===a.target.tagName&&(c&&0<c.length)&&(b=e("#"+c),b=b.data("select2"),b!==g&&(b.focus(),a.preventDefault()))})});w=x(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(a){var b,c;this.opts=a=this.prepareOpts(a);this.id=a.id;a.element.data("select2")!==g&&null!==a.element.data("select2")&&this.destroy();this.enabled=!0;this.container=this.createContainer();this.containerId="s2id_"+(a.element.attr("id")||"autogen"+G());this.containerSelector=
+"#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1");this.container.attr("id",this.containerId);var d=!1,j;this.body=function(){!1===d&&(j=a.element.closest("body"),d=!0);return j};a.element.attr("class")!==g&&this.container.addClass(a.element.attr("class").replace(/validate\[[\S ]+] ?/,""));this.container.css(v(a.containerCss));this.container.addClass(v(a.containerCssClass));this.opts.element.data("select2",this).hide().before(this.container);this.container.data("select2",
+this);this.dropdown=this.container.find(".select2-drop");this.dropdown.addClass(v(a.dropdownCssClass));this.dropdown.data("select2",this);this.results=b=this.container.find(".select2-results");this.search=c=this.container.find("input.select2-input");c.attr("tabIndex",this.opts.element.attr("tabIndex"));this.resultsPage=0;this.context=null;this.initContainer();this.initContainerWidth();this.results.bind("mousemove",function(a){var b=e.data(document,"select2-lastpos");(b===g||b.x!==a.pageX||b.y!==a.pageY)&&
+e(a.target).trigger("mousemove-filtered",a)});this.dropdown.delegate(".select2-results","mousemove-filtered",this.bind(this.highlightUnderEvent));var h=this.results,f=A(80,function(a){h.trigger("scroll-debounced",a)});h.bind("scroll",function(a){0<=i(a.target,h.get())&&f(a)});this.dropdown.delegate(".select2-results","scroll-debounced",this.bind(this.loadMoreIfNeeded));e.fn.mousewheel&&b.mousewheel(function(a,c,d,e){c=b.scrollTop();0<e&&0>=c-e?(b.scrollTop(0),l(a)):0>e&&b.get(0).scrollHeight-b.scrollTop()+
+e<=b.height()&&(b.scrollTop(b.get(0).scrollHeight-b.height()),l(a))});c.bind("keydown",function(){e.data(c,"keyup-change-value")===g&&e.data(c,"keyup-change-value",c.val())});c.bind("keyup",function(){var a=e.data(c,"keyup-change-value");a!==g&&c.val()!==a&&(e.removeData(c,"keyup-change-value"),c.trigger("keyup-change"))});c.bind("keyup-change",this.bind(this.updateResults));c.bind("focus",function(){c.addClass("select2-focused");" "===c.val()&&c.val("")});c.bind("blur",function(){c.removeClass("select2-focused")});
+this.dropdown.delegate(".select2-results","mouseup",this.bind(function(a){0<e(a.target).closest(".select2-result-selectable:not(.select2-disabled)").length?(this.highlightUnderEvent(a),this.selectHighlighted(a)):this.focusSearch();l(a)}));this.dropdown.bind("click mouseup mousedown",function(a){a.stopPropagation()});e.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource());(a.element.is(":disabled")||a.element.is("[readonly='readonly']"))&&this.disable()},destroy:function(){var a=
+this.opts.element.data("select2");a!==g&&(a.container.remove(),a.dropdown.remove(),a.opts.element.removeData("select2").unbind(".select2").show())},prepareOpts:function(a){var b,c,d;b=a.element;"select"===b.get(0).tagName.toLowerCase()&&(this.select=c=a.element);c&&e.each("id multiple ajax query createSearchChoice initSelection data tags".split(" "),function(){if(this in a)throw Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.");});a=e.extend({},{populateResults:function(b,
+c,d){var f,n=this.opts.id,o=this;f=function(b,c,j){var h,l,i,m,r,p,q;h=0;for(l=b.length;h<l;h=h+1){i=b[h];m=n(i)!==g;r=i.children&&i.children.length>0;p=e("<li></li>");p.addClass("select2-results-dept-"+j);p.addClass("select2-result");p.addClass(m?"select2-result-selectable":"select2-result-unselectable");r&&p.addClass("select2-result-with-children");p.addClass(o.opts.formatResultCssClass(i));m=e("<div></div>");m.addClass("select2-result-label");q=a.formatResult(i,m,d);q!==g&&m.html(o.opts.escapeMarkup(q));
+p.append(m);if(r){r=e("<ul></ul>");r.addClass("select2-result-sub");f(i.children,r,j+1);p.append(r)}p.data("select2-data",i);c.append(p)}};f(c,b,0)}},e.fn.select2.defaults,a);"function"!==typeof a.id&&(d=a.id,a.id=function(a){return a[d]});if(c)a.query=this.bind(function(a){var c={results:[],more:false},d=a.term,f,n,o;o=function(b,c){var e;if(b.is("option"))a.matcher(d,b.text(),b)&&c.push({id:b.attr("value"),text:b.text(),element:b.get(),css:b.attr("class")});else if(b.is("optgroup")){e={text:b.attr("label"),
+children:[],element:b.get(),css:b.attr("class")};b.children().each2(function(a,b){o(b,e.children)});e.children.length>0&&c.push(e)}};f=b.children();if(this.getPlaceholder()!==g&&f.length>0){n=f[0];e(n).text()===""&&(f=f.not(n))}f.each2(function(a,b){o(b,c.results)});a.callback(c)}),a.id=function(a){return a.id},a.formatResultCssClass=function(a){return a.css};else if(!("query"in a))if("ajax"in a){if((c=a.element.data("ajax-url"))&&0<c.length)a.ajax.url=c;a.query=C(a.ajax)}else"data"in a?a.query=D(a.data):
+"tags"in a&&(a.query=E(a.tags),a.createSearchChoice=function(a){return{id:a,text:a}},a.initSelection=function(b,c){var d=[];e(s(b.val(),a.separator)).each(function(){var b=this,c=this,j=a.tags;e.isFunction(j)&&(j=j());e(j).each(function(){if(m(this.id,b)){c=this.text;return false}});d.push({id:b,text:c})});c(d)});if("function"!==typeof a.query)throw"query function not defined for Select2 "+a.element.attr("id");return a},monitorSource:function(){this.opts.element.bind("change.select2",this.bind(function(){!0!==
+this.opts.element.data("select2-change-triggered")&&this.initSelection()}))},triggerChange:function(a){a=a||{};a=e.extend({},a,{type:"change",val:this.val()});this.opts.element.data("select2-change-triggered",!0);this.opts.element.trigger(a);this.opts.element.data("select2-change-triggered",!1);this.opts.element.click();this.opts.blurOnChange&&this.opts.element.blur()},enable:function(){this.enabled||(this.enabled=!0,this.container.removeClass("select2-container-disabled"))},disable:function(){this.enabled&&
+(this.close(),this.enabled=!1,this.container.addClass("select2-container-disabled"))},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var a=this.container.offset(),b=this.container.outerHeight(),c=this.container.outerWidth(),d=this.dropdown.outerHeight(),j=e(window).scrollTop()+document.documentElement.clientHeight,b=a.top+b,f=a.left,j=b+d<=j,g=a.top-d>=this.body().scrollTop(),k=this.dropdown.hasClass("select2-drop-above"),n;"static"!==this.body().css("position")&&
+(n=this.body().offset(),b-=n.top,f-=n.left);k?(k=!0,!g&&j&&(k=!1)):(k=!1,!j&&g&&(k=!0));k?(b=a.top-d,this.container.addClass("select2-drop-above"),this.dropdown.addClass("select2-drop-above")):(this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above"));a=e.extend({top:b,left:f,width:c},v(this.opts.dropdownCss));this.dropdown.css(a)},shouldOpen:function(){var a;if(this.opened())return!1;a=e.Event("open");this.opts.element.trigger(a);return!a.isDefaultPrevented()},
+clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above");this.dropdown.removeClass("select2-drop-above")},open:function(){if(!this.shouldOpen())return!1;window.setTimeout(this.bind(this.opening),1);return!0},opening:function(){var a=this.containerId,b=this.containerSelector,c="scroll."+a,d="resize."+a;this.container.parents().each(function(){e(this).bind(c,function(){var a=e(b);0==a.length&&e(this).unbind(c);a.select2("close")})});e(window).bind(d,function(){var a=
+e(b);0==a.length&&e(window).unbind(d);a.select2("close")});this.clearDropdownAlignmentPreference();" "===this.search.val()&&this.search.val("");this.container.addClass("select2-dropdown-open").addClass("select2-container-active");this.updateResults(!0);this.dropdown[0]!==this.body().children().last()[0]&&this.dropdown.detach().appendTo(this.body());this.dropdown.show();this.positionDropdown();this.dropdown.addClass("select2-drop-active");this.ensureHighlightVisible();this.focusSearch()},close:function(){if(this.opened()){var a=
+this;this.container.parents().each(function(){e(this).unbind("scroll."+a.containerId)});e(window).unbind("resize."+this.containerId);this.clearDropdownAlignmentPreference();this.dropdown.hide();this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");this.results.empty();this.clearSearch();this.opts.element.trigger(e.Event("close"))}},clearSearch:function(){},ensureHighlightVisible:function(){var a=this.results,b,c,d,f;c=this.highlight();0>c||(0==c?a.scrollTop(0):
+(b=a.find(".select2-result-selectable"),d=e(b[c]),f=d.offset().top+d.outerHeight(),c===b.length-1&&(b=a.find("li.select2-more-results"),0<b.length&&(f=b.offset().top+b.outerHeight())),b=a.offset().top+a.outerHeight(),f>b&&a.scrollTop(a.scrollTop()+(f-b)),d=d.offset().top-a.offset().top,0>d&&a.scrollTop(a.scrollTop()+d)))},moveHighlight:function(a){for(var b=this.results.find(".select2-result-selectable"),c=this.highlight();-1<c&&c<b.length;){var c=c+a,d=e(b[c]);if(d.hasClass("select2-result-selectable")&&
+!d.hasClass("select2-disabled")){this.highlight(c);break}}},highlight:function(a){var b=this.results.find(".select2-result-selectable").not(".select2-disabled");if(0===arguments.length)return i(b.filter(".select2-highlighted")[0],b.get());a>=b.length&&(a=b.length-1);0>a&&(a=0);b.removeClass("select2-highlighted");e(b[a]).addClass("select2-highlighted");this.ensureHighlightVisible()},countSelectableResults:function(){return this.results.find(".select2-result-selectable").not(".select2-disabled").length},
+highlightUnderEvent:function(a){a=e(a.target).closest(".select2-result-selectable");if(0<a.length&&!a.is(".select2-highlighted")){var b=this.results.find(".select2-result-selectable");this.highlight(b.index(a))}else 0==a.length&&this.results.find(".select2-highlighted").removeClass("select2-highlighted")},loadMoreIfNeeded:function(){var a=this.results,b=a.find("li.select2-more-results"),c,d=this.resultsPage+1,e=this,f=this.search.val(),g=this.context;0!==b.length&&(c=b.offset().top-a.offset().top-
+a.height(),0>=c&&(b.addClass("select2-active"),this.opts.query({term:f,page:d,context:g,matcher:this.opts.matcher,callback:this.bind(function(c){e.opened()&&(e.opts.populateResults.call(this,a,c.results,{term:f,page:d,context:g}),!0===c.more?(b.detach().appendTo(a).text(e.opts.formatLoadMore(d+1)),window.setTimeout(function(){e.loadMoreIfNeeded()},10)):b.remove(),e.positionDropdown(),e.resultsPage=d)})})))},tokenize:function(){},updateResults:function(a){function b(){f.scrollTop(0);d.removeClass("select2-active");
+k.positionDropdown()}function c(a){f.html(k.opts.escapeMarkup(a));b()}var d=this.search,f=this.results,h=this.opts,i,k=this;if(!(!0!==a&&(!1===this.showSearchInput||!this.opened()))){d.addClass("select2-active");if(1<=h.maximumSelectionSize&&(i=this.data(),e.isArray(i)&&i.length>=h.maximumSelectionSize&&u(h.formatSelectionTooBig,"formatSelectionTooBig"))){c("<li class='select2-selection-limit'>"+h.formatSelectionTooBig(h.maximumSelectionSize)+"</li>");return}d.val().length<h.minimumInputLength&&u(h.formatInputTooShort,
+"formatInputTooShort")?c("<li class='select2-no-results'>"+h.formatInputTooShort(d.val(),h.minimumInputLength)+"</li>"):(c("<li class='select2-searching'>"+h.formatSearching()+"</li>"),i=this.tokenize(),i!=g&&null!=i&&d.val(i),this.resultsPage=1,h.query({term:d.val(),page:this.resultsPage,context:null,matcher:h.matcher,callback:this.bind(function(i){var l;this.opened()&&((this.context=i.context===g?null:i.context,this.opts.createSearchChoice&&""!==d.val()&&(l=this.opts.createSearchChoice.call(null,
+d.val(),i.results),l!==g&&null!==l&&k.id(l)!==g&&null!==k.id(l)&&0===e(i.results).filter(function(){return m(k.id(this),k.id(l))}).length&&i.results.unshift(l)),0===i.results.length&&u(h.formatNoMatches,"formatNoMatches"))?c("<li class='select2-no-results'>"+h.formatNoMatches(d.val())+"</li>"):(f.empty(),k.opts.populateResults.call(this,f,i.results,{term:d.val(),page:this.resultsPage,context:null}),!0===i.more&&u(h.formatLoadMore,"formatLoadMore")&&(f.append("<li class='select2-more-results'>"+k.opts.escapeMarkup(h.formatLoadMore(this.resultsPage))+
+"</li>"),window.setTimeout(function(){k.loadMoreIfNeeded()},10)),this.postprocessResults(i,a),b()))})}))}},cancel:function(){this.close()},blur:function(){this.close();this.container.removeClass("select2-container-active");this.dropdown.removeClass("select2-drop-active");this.search[0]===document.activeElement&&this.search.blur();this.clearSearch();this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){this.search.show();this.search.focus();
+window.setTimeout(this.bind(function(){this.search.show();this.search.focus();this.search.val(this.search.val())}),10)},selectHighlighted:function(){var a=this.highlight(),b=this.results.find(".select2-highlighted").not(".select2-disabled"),c=b.closest(".select2-result-selectable").data("select2-data");c&&(b.addClass("select2-disabled"),this.highlight(a),this.onSelect(c))},getPlaceholder:function(){return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")||
+this.opts.placeholder},initContainerWidth:function(){var a=function(){var a,c,d,f;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth()?"auto":this.opts.element.outerWidth()+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){a=this.opts.element.attr("style");if(a!==g){a=a.split(";");d=0;for(f=a.length;d<f;d+=1)if(c=a[d].replace(/\s/g,"").match(/width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/),null!==c&&1<=c.length)return c[1]}return"resolve"===
+this.opts.width?(a=this.opts.element.css("width"),0<a.indexOf("%")?a:0===this.opts.element.outerWidth()?"auto":this.opts.element.outerWidth()+"px"):null}return e.isFunction(this.opts.width)?this.opts.width():this.opts.width}.call(this);null!==a&&this.container.attr("style","width: "+a)}});y=x(w,{createContainer:function(){return e("<div></div>",{"class":"select2-container"}).html(" <a href='#' onclick='return false;' class='select2-choice'> <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr> <div><b></b></div></a> <div class='select2-drop select2-offscreen'> <div class='select2-search'> <input type='text' autocomplete='off' class='select2-input'/> </div> <ul class='select2-results'> </ul></div>")},
+opening:function(){this.search.show();this.parent.opening.apply(this,arguments);this.dropdown.removeClass("select2-offscreen")},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show())},focus:function(){this.close();this.selection.focus()},isFocused:function(){return this.selection[0]===document.activeElement},cancel:function(){this.parent.cancel.apply(this,arguments);this.selection.focus()},
+initContainer:function(){var a,b=this.dropdown;this.selection=a=this.container.find(".select2-choice");this.search.bind("keydown",this.bind(function(a){if(this.enabled)if(a.which===f.PAGE_UP||a.which===f.PAGE_DOWN)l(a);else if(this.opened())switch(a.which){case f.UP:case f.DOWN:this.moveHighlight(a.which===f.UP?-1:1);l(a);break;case f.TAB:case f.ENTER:this.selectHighlighted();l(a);break;case f.ESC:this.cancel(a),l(a)}else a.which===f.TAB||f.isControl(a)||f.isFunctionKey(a)||a.which===f.ESC||!1===
+this.opts.openOnEnter&&a.which===f.ENTER||this.open()}));this.search.bind("focus",this.bind(function(){this.selection.attr("tabIndex","-1")}));this.search.bind("blur",this.bind(function(){this.opened()||this.container.removeClass("select2-container-active");window.setTimeout(this.bind(function(){this.selection.attr("tabIndex",this.opts.element.attr("tabIndex"))}),10)}));a.bind("mousedown",this.bind(function(){this.opened()?(this.close(),this.selection.focus()):this.enabled&&this.open()}));b.bind("mousedown",
+this.bind(function(){this.search.focus()}));a.bind("focus",this.bind(function(){this.container.addClass("select2-container-active");this.search.attr("tabIndex","-1")}));a.bind("blur",this.bind(function(){this.opened()||this.container.removeClass("select2-container-active");window.setTimeout(this.bind(function(){this.search.attr("tabIndex",this.opts.element.attr("tabIndex"))}),10)}));a.bind("keydown",this.bind(function(a){if(this.enabled)if(a.which===f.PAGE_UP||a.which===f.PAGE_DOWN)l(a);else if(!(a.which===
+f.TAB||f.isControl(a)||f.isFunctionKey(a)||a.which===f.ESC)&&!(!1===this.opts.openOnEnter&&a.which===f.ENTER))if(a.which==f.DELETE)this.opts.allowClear&&this.clear();else{this.open();if(a.which!==f.ENTER&&!(48>a.which)){var b=String.fromCharCode(a.which).toLowerCase();a.shiftKey&&(b=b.toUpperCase());this.search.focus();this.search.val(b)}l(a)}}));a.delegate("abbr","mousedown",this.bind(function(a){this.enabled&&(this.clear(),l(a),this.close(),this.triggerChange(),this.selection.focus())}));this.setPlaceholder();
+this.search.bind("focus",this.bind(function(){this.container.addClass("select2-container-active")}))},clear:function(){this.opts.element.val("");this.selection.find("span").empty();this.selection.removeData("select2-data");this.setPlaceholder()},initSelection:function(){if(""===this.opts.element.val())this.close(),this.setPlaceholder();else{var a=this;this.opts.initSelection.call(null,this.opts.element,function(b){b!==g&&null!==b&&(a.updateSelection(b),a.close(),a.setPlaceholder())})}},prepareOpts:function(){var a=
+this.parent.prepareOpts.apply(this,arguments);"select"===a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a,c){var d=a.find(":selected");e.isFunction(c)&&c({id:d.attr("value"),text:d.text()})});return a},setPlaceholder:function(){var a=this.getPlaceholder();""===this.opts.element.val()&&a!==g&&!(this.select&&""!==this.select.find("option:first").text())&&(this.selection.find("span").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.selection.find("abbr").hide())},
+postprocessResults:function(a,b){var c=0,d=this,f=!0;this.results.find(".select2-result-selectable").each2(function(a,b){if(m(d.id(b.data("select2-data")),d.opts.element.val()))return c=a,!1});this.highlight(c);!0===b&&(f=this.showSearchInput=F(a.results)>=this.opts.minimumResultsForSearch,this.dropdown.find(".select2-search")[f?"removeClass":"addClass"]("select2-search-hidden"),e(this.dropdown,this.container)[f?"addClass":"removeClass"]("select2-with-searchbox"))},onSelect:function(a){var b=this.opts.element.val();
+this.opts.element.val(this.id(a));this.updateSelection(a);this.close();this.selection.focus();m(b,this.id(a))||this.triggerChange()},updateSelection:function(a){var b=this.selection.find("span");this.selection.data("select2-data",a);b.empty();a=this.opts.formatSelection(a,b);a!==g&&b.append(this.opts.escapeMarkup(a));this.selection.removeClass("select2-default");this.opts.allowClear&&this.getPlaceholder()!==g&&this.selection.find("abbr").show()},val:function(){var a,b=null,c=this;if(0===arguments.length)return this.opts.element.val();
+a=arguments[0];if(this.select)this.select.val(a).find(":selected").each2(function(a,c){b={id:c.attr("value"),text:c.text()};return!1}),this.updateSelection(b),this.setPlaceholder();else{if(this.opts.initSelection===g)throw Error("cannot call val() if initSelection() is not defined");a?(this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){c.opts.element.val(!a?"":c.id(a));c.updateSelection(a);c.setPlaceholder()})):this.clear()}},clearSearch:function(){this.search.val("")},
+data:function(a){var b;if(0===arguments.length)return b=this.selection.data("select2-data"),b==g&&(b=null),b;!a||""===a?this.clear():(this.opts.element.val(!a?"":this.id(a)),this.updateSelection(a))}});z=x(w,{createContainer:function(){return e("<div></div>",{"class":"select2-container select2-container-multi"}).html(" <ul class='select2-choices'> <li class='select2-search-field'> <input type='text' autocomplete='off' class='select2-input'> </li></ul><div class='select2-drop select2-drop-multi' style='display:none;'> <ul class='select2-results'> </ul></div>")},
+prepareOpts:function(){var a=this.parent.prepareOpts.apply(this,arguments);"select"===a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a,c){var d=[];a.find(":selected").each2(function(a,b){d.push({id:b.attr("value"),text:b.text()})});e.isFunction(c)&&c(d)});return a},initContainer:function(){var a;this.searchContainer=this.container.find(".select2-search-field");this.selection=a=this.container.find(".select2-choices");this.search.bind("keydown",this.bind(function(b){if(this.enabled){if(b.which===
+f.BACKSPACE&&""===this.search.val()){this.close();var c;c=a.find(".select2-search-choice-focus");if(0<c.length){this.unselect(c.first());this.search.width(10);l(b);return}c=a.find(".select2-search-choice");0<c.length&&c.last().addClass("select2-search-choice-focus")}else a.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");if(this.opened())switch(b.which){case f.UP:case f.DOWN:this.moveHighlight(b.which===f.UP?-1:1);l(b);return;case f.ENTER:case f.TAB:this.selectHighlighted();
+l(b);return;case f.ESC:this.cancel(b);l(b);return}if(!(b.which===f.TAB||f.isControl(b)||f.isFunctionKey(b)||b.which===f.BACKSPACE||b.which===f.ESC)&&!(!1===this.opts.openOnEnter&&b.which===f.ENTER))this.open(),(b.which===f.PAGE_UP||b.which===f.PAGE_DOWN)&&l(b)}}));this.search.bind("keyup",this.bind(this.resizeSearch));this.search.bind("blur",this.bind(function(a){this.container.removeClass("select2-container-active");this.search.removeClass("select2-focused");this.clearSearch();a.stopImmediatePropagation()}));
+this.container.delegate(".select2-choices","mousedown",this.bind(function(a){this.enabled&&!(0<e(a.target).closest(".select2-search-choice").length)&&(this.clearPlaceholder(),this.open(),this.focusSearch(),a.preventDefault())}));this.container.delegate(".select2-choices","focus",this.bind(function(){this.enabled&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())}));this.clearSearch()},enable:function(){this.enabled||(this.parent.enable.apply(this,
+arguments),this.search.removeAttr("disabled"))},disable:function(){this.enabled&&(this.parent.disable.apply(this,arguments),this.search.attr("disabled",!0))},initSelection:function(){""===this.opts.element.val()&&(this.updateSelection([]),this.close(),this.clearSearch());if(this.select||""!==this.opts.element.val()){var a=this;this.opts.initSelection.call(null,this.opts.element,function(b){if(b!==g&&b!==null){a.updateSelection(b);a.close();a.clearSearch()}})}},clearSearch:function(){var a=this.getPlaceholder();
+a!==g&&0===this.getVal().length&&!1===this.search.hasClass("select2-focused")?(this.search.val(a).addClass("select2-default"),this.resizeSearch()):this.search.val(" ").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")?this.search.val("").removeClass("select2-default"):" "===this.search.val()&&this.search.val("")},opening:function(){this.parent.opening.apply(this,arguments);this.clearPlaceholder();this.resizeSearch();this.focusSearch()},close:function(){this.opened()&&
+this.parent.close.apply(this,arguments)},focus:function(){this.close();this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(a){var b=[],c=[],d=this;e(a).each(function(){0>i(d.id(this),b)&&(b.push(d.id(this)),c.push(this))});a=c;this.selection.find(".select2-search-choice").remove();e(a).each(function(){d.addSelectedChoice(this)});d.postprocessResults()},tokenize:function(){var a=this.search.val(),a=this.opts.tokenizer(a,this.data(),this.bind(this.onSelect),
+this.opts);null!=a&&a!=g&&(this.search.val(a),0<a.length&&this.open())},onSelect:function(a){this.addSelectedChoice(a);this.select&&this.postprocessResults();this.opts.closeOnSelect?(this.close(),this.search.width(10)):0<this.countSelectableResults()?(this.search.width(10),this.resizeSearch(),this.positionDropdown()):this.close();this.triggerChange({added:a});this.focusSearch()},cancel:function(){this.close();this.focusSearch()},addSelectedChoice:function(a){var b=e("<li class='select2-search-choice'> <div></div> <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a></li>"),
+c=this.id(a),d=this.getVal(),f;f=this.opts.formatSelection(a,b);b.find("div").replaceWith("<div>"+this.opts.escapeMarkup(f)+"</div>");b.find(".select2-search-choice-close").bind("mousedown",l).bind("click dblclick",this.bind(function(a){this.enabled&&(e(a.target).closest(".select2-search-choice").fadeOut("fast",this.bind(function(){this.unselect(e(a.target));this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");this.close();this.focusSearch()})).dequeue(),
+l(a))})).bind("focus",this.bind(function(){this.enabled&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))}));b.data("select2-data",a);b.insertBefore(this.searchContainer);d.push(c);this.setVal(d)},unselect:function(a){var b=this.getVal(),c,d,a=a.closest(".select2-search-choice");if(0===a.length)throw"Invalid argument: "+a+". Must be .select2-search-choice";c=a.data("select2-data");d=i(this.id(c),b);0<=d&&(b.splice(d,1),this.setVal(b),this.select&&
+this.postprocessResults());a.remove();this.triggerChange({removed:c})},postprocessResults:function(){var a=this.getVal(),b=this.results.find(".select2-result-selectable"),c=this.results.find(".select2-result-with-children"),d=this;b.each2(function(b,c){var e=d.id(c.data("select2-data"));0<=i(e,a)?c.addClass("select2-disabled").removeClass("select2-result-selectable"):c.removeClass("select2-disabled").addClass("select2-result-selectable")});c.each2(function(a,b){0==b.find(".select2-result-selectable").length?
+b.addClass("select2-disabled"):b.removeClass("select2-disabled")});b.each2(function(a,b){if(!b.hasClass("select2-disabled")&&b.hasClass("select2-result-selectable"))return d.highlight(0),!1})},resizeSearch:function(){var a,b,c,d,f=this.search.outerWidth()-this.search.width();a=this.search;q||(c=a[0].currentStyle||window.getComputedStyle(a[0],null),q=e("<div></div>").css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,
+fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),e("body").append(q));q.text(a.val());a=q.width()+10;b=this.search.offset().left;c=this.selection.width();d=this.selection.offset().left;b=c-(b-d)-f;b<a&&(b=c-f);40>b&&(b=c-f);this.search.width(b)},getVal:function(){var a;if(this.select)return a=this.select.val(),null===a?[]:a;a=this.opts.element.val();return s(a,this.opts.separator)},setVal:function(a){var b;this.select?this.select.val(a):(b=
+[],e(a).each(function(){0>i(this,b)&&b.push(this)}),this.opts.element.val(0===b.length?"":b.join(this.opts.separator)))},val:function(){var a,b=[],c=this;if(0===arguments.length)return this.getVal();if(a=arguments[0])if(this.setVal(a),this.select)this.select.find(":selected").each(function(){b.push({id:e(this).attr("value"),text:e(this).text()})}),this.updateSelection(b);else{if(this.opts.initSelection===g)throw Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,
+function(a){var b=e(a).map(c.id);c.setVal(b);c.updateSelection(a);c.clearSearch()})}else this.opts.element.val(""),this.updateSelection([]);this.clearSearch()},onSortStart:function(){if(this.select)throw Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");this.search.width(0);this.searchContainer.hide()},onSortEnd:function(){var a=[],b=this;this.searchContainer.show();this.searchContainer.appendTo(this.searchContainer.parent());this.resizeSearch();
+this.selection.find(".select2-search-choice").each(function(){a.push(b.opts.id(e(this).data("select2-data")))});this.setVal(a);this.triggerChange()},data:function(a){var b=this,c;if(0===arguments.length)return this.selection.find(".select2-search-choice").map(function(){return e(this).data("select2-data")}).get();a||(a=[]);c=e.map(a,function(a){return b.opts.id(a)});this.setVal(c);this.updateSelection(a);this.clearSearch()}});e.fn.select2=function(){var a=Array.prototype.slice.call(arguments,0),b,
+c,d,f,h="val destroy opened open close focus isFocused container onSortStart onSortEnd enable disable positionDropdown data".split(" ");this.each(function(){if(0===a.length||"object"===typeof a[0])b=0===a.length?{}:e.extend({},a[0]),b.element=e(this),"select"===b.element.get(0).tagName.toLowerCase()?f=b.element.attr("multiple"):(f=b.multiple||!1,"tags"in b&&(b.multiple=f=!0)),c=f?new z:new y,c.init(b);else if("string"===typeof a[0]){if(0>i(a[0],h))throw"Unknown method: "+a[0];d=g;c=e(this).data("select2");
+if(c!==g&&(d="container"===a[0]?c.container:c[a[0]].apply(c,a.slice(1)),d!==g))return!1}else throw"Invalid arguments to select2 plugin: "+a;});return d===g?this:d};e.fn.select2.defaults={width:"copy",closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c){b=[];B(a.text,c.term,b);return b.join("")},formatSelection:function(a){return a?a.text:g},formatResultCssClass:function(){return g},formatNoMatches:function(){return"No matches found"},
+formatInputTooShort:function(a,b){return"Please enter "+(b-a.length)+" more characters"},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results..."},formatSearching:function(){return"Searching..."},minimumResultsForSearch:0,minimumInputLength:0,maximumSelectionSize:0,id:function(a){return a.id},matcher:function(a,b){return 0<=b.toUpperCase().indexOf(a.toUpperCase())},separator:",",tokenSeparators:[],tokenizer:H,
+escapeMarkup:function(a){return a&&"string"===typeof a?a.replace(/&/g,"&amp;"):a},blurOnChange:!1};window.Select2={query:{ajax:C,local:D,tags:E},util:{debounce:A,markMatch:B},"class":{"abstract":w,single:y,multi:z}}}})(jQuery);
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/docs.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/docs.html
new file mode 100644
index 000000000..c02950247
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/docs.html
@@ -0,0 +1,38 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+
+<script id="rest_docs" type="text/html">
+ <div id="rest-doc-header">
+ <div class="page-header">
+ <h3><b>${$.i18n.prop('docs.rest.header')}</b></h3>
+ </div>
+ <div id="docs_rest_choice">
+ <ul>
+ <li><a class="cursor-hand" onclick="displayArchivaRestDocs();">Archiva Rest Api Docs</a></li>
+ <li><a class="cursor-hand" onclick="displayArchivaRestUIDocs();">Archiva Rest Api UI Docs</a></li>
+ <li><a class="cursor-hand" onclick="displayRedbackRestDocs();">Redback Rest Api UI Docs</a></li>
+ </ul>
+ </div>
+ </div>
+ <div id="rest_docs_content">
+ </div>
+</script>
+
+<script id="users_docs" type="text/html">
+</script> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/general-admin.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/general-admin.html
new file mode 100644
index 000000000..d7eb7bef2
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/general-admin.html
@@ -0,0 +1,1100 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<script id="legacy-artifact-path-main" type="text/html">
+ <div id="legacy-artifact-path-screen">
+ <div class="page-header">
+ <h2>${$.i18n.prop('legacy-artifact-paths.list')}</h2>
+ </div>
+
+ <ul id="legacy-artifact-paths-view-tabs" class="nav nav-tabs">
+ <li id="legacy-artifact-paths-view-tabs-li-grid">
+ <a data-toggle="tab" href="#legacy-artifact-paths-view" id="legacy-artifact-paths-view-tabs-a-grid">${$.i18n.prop('legacy-artifact-paths.grid.tab.title')}</a>
+ </li>
+ <li id="legacy-artifact-paths-view-tabs-li-edit">
+ <a data-toggle="tab" href="#legacy-artifact-paths-edit">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="legacy-artifact-paths-view-tabs-content" class="tab-content">
+ <div id="legacy-artifact-paths-view" class="tab-pane">
+ <table class="table table-striped table-bordered" id="legacy-artifact-paths-table"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko-legacy-artifact-paths-grid',pageLinksId:'legacy-artifact-pathsPagination'">
+ </table>
+ <div id="legacy-artifact-pathsPagination"></div>
+ </div>
+ <div id="legacy-artifact-paths-edit" class="tab-pane" data-bind='template: {name:"legacy-artifact-paths-edit-tmpl"}'></div>
+ </div>
+ </div>
+</script>
+
+<script id='ko-legacy-artifact-paths-grid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th>${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>${$.i18n.prop('delete')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ {{each(j, columnDefinition) columns}}
+ {{var val = (typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText])}}
+ <td>
+ ${val}
+ </td>
+ {{/each}}
+ <td>
+ <a href="#" data-bind="click: function(){ removeLegacyArtifactPath(row) }">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+<script id="legacy-artifact-paths-edit-tmpl" type="text/html">
+ <form id="legacy-artifact-paths-edit-form" class="well form-horizontal">
+ <fieldset id="legacy-artifact-paths-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="groupId">${$.i18n.prop('legacy-artifact-paths.groupId')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" id="groupId" name="groupId" size="8"
+ data-bind="value: legacyArtifactPath.groupId"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="artifactId">${$.i18n.prop('legacy-artifact-paths.artifactId')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" id="artifactId" name="artifactId" size="8"
+ data-bind="value: legacyArtifactPath.artifactId"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="version">${$.i18n.prop('legacy-artifact-paths.version')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" id="version" name="version" size="8"
+ data-bind="value: legacyArtifactPath.version"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="classifier">${$.i18n.prop('legacy-artifact-paths.classifier')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge" id="classifier" name="classifier" size="8"
+ data-bind="value: legacyArtifactPath.classifier"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="type">${$.i18n.prop('legacy-artifact-paths.type')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" id="type" name="type" size="8"
+ data-bind="value: legacyArtifactPath.type"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="path">${$.i18n.prop('legacy-artifact-paths.path')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" id="path" name="path" size="8"
+ data-bind="value: legacyArtifactPath.path"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="artifact">${$.i18n.prop('legacy-artifact-paths.artifact')}</label>
+ <div class="controls">
+ <span title="calculated from values" class="uneditable-input"
+ id="artifact" data-bind="text: legacyArtifactPath.artifact"></span>
+ </div>
+ </div>
+
+ </fieldset>
+ <button id="network-proxy-btn-save" data-bind="click: save" class="btn">${$.i18n.prop('save')}</button>
+ <button id="network-proxy-btn-cancel" data-bind="click: displayGrid" class="btn">${$.i18n.prop('cancel')}</button>
+ <button id="network-proxy-btn-calculate-path" data-bind="click: calculatePath" class="btn btn-success">${$.i18n.prop('legacy-artifact-paths.calculatePath')}</button>
+ </form>
+</script>
+
+<script id="legacy-artifact-path-delete-warning-tmpl" type="text/html">
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+<script id="repository-scanning-main" type="text/html">
+ <div id="repository-scanning-screen">
+ <div class="page-header">
+ <h2>${$.i18n.prop('repository-scanning.head')}</h2>
+ </div>
+ </div>
+
+ <ul id="repositories-tabs" class="nav nav-tabs">
+ <li class="active">
+ <a data-toggle="tab" href="#file-types-content">${$.i18n.prop('repository-scanning.file-types.head')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" href="#consumers-content">${$.i18n.prop('repository-scanning.consumers.head')}</a>
+ </li>
+ </ul>
+
+ <div class="tab-content">
+ <div id="file-types-content" class="tab-pane active" data-bind='template: {name:"file-types-tmpl"}'>
+ </div>
+ <div id="consumers-content" class="tab-pane">
+ <div id="consumers-known-content" data-bind='template: {name:"consumers-known-content-tmpl"}'></div>
+ <div id="consumers-invalid-content" data-bind='template: {name:"consumers-invalid-content-tmpl"}'></div>
+ </div>
+ </div>
+
+</script>
+
+<script id="file-types-tmpl" type="text/html">
+<div class="accordion" id="accordion-file-types">
+ <div class="span4">
+ {{each(i, fileType) fileTypes}}
+ <div class="accordion-group">
+ <div class="accordion-heading">
+ <a class="accordion-toggle" href="#collapse-pattern-${fileType.id}"
+ data-parent="#accordion-file-types" data-toggle="collapse">${fileType.id}&nbsp;<i class="icon-resize-vertical"/></a>
+ </div>
+ <div id="collapse-pattern-${fileType.id}" class="accordion-body collapse">
+ <table class="table table-condensed">
+ {{each(j,pattern) fileType.patterns}}
+ <tr>
+ <td>${pattern}</td>
+ <td>
+ <a href="#" data-bind="click: function(){ removeFileTypePattern(fileType.id(),pattern) }">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ </tr>
+ {{/each}}
+ <tr>
+ <td><input type="text" id="pattern-${fileType.id}"/></td>
+ <td>
+ <a href="#" data-bind="click: function(){addFileTypePattern(fileType.id())}">
+ <span class="btn btn-success">
+ <i class="icon-plus-sign icon-white"/>
+ </span>
+ </a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ {{/each}}
+ </div>
+</div>
+</script>
+
+<script id="consumers-known-content-tmpl" type="text/html">
+ <div class="page-header">
+ <h4>${$.i18n.prop('repository-scanning.consumers.know-content.head')}</h4>
+ </div>
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.enabled')}</th>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.id')}</th>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.description')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i,knownAdminRepositoryConsumer) knownAdminRepositoryConsumers}}
+ <tr>
+ {{if knownAdminRepositoryConsumer.enabled()==true}}
+ <td>
+ <a class="cursor-hand" data-bind="click: function(){ disableKnowContentConsumer(knownAdminRepositoryConsumer) }">
+ <img src="images/weather-clear-22-22.png"/>
+ </a>
+ </td>
+ {{else}}
+ <td>
+ <a class="cursor-hand" data-bind="click: function(){ enableKnowContentConsumer(knownAdminRepositoryConsumer) }">
+ <img src="images/dialog-error-22-22.png"/>
+ </a>
+ </td>
+ {{/if}}
+
+ <td>${knownAdminRepositoryConsumer.id}</td>
+ <td>${knownAdminRepositoryConsumer.description}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</script>
+
+<script id="consumers-invalid-content-tmpl" type="text/html">
+ <div class="page-header">
+ <h4>${$.i18n.prop('repository-scanning.consumers.invalid-content.head')}</h4>
+ </div>
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.enabled')}</th>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.id')}</th>
+ <th>${$.i18n.prop('repository-scanning.consumers.grid.description')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i,invalidAdminRepositoryConsumer) invalidAdminRepositoryConsumers}}
+ <tr>
+ {{if invalidAdminRepositoryConsumer.enabled()==true}}
+ <td>
+ <a href="#" data-bind="click: function(){ disableInvalidContentConsumer(invalidAdminRepositoryConsumer) }">
+ <img src="images/weather-clear-22-22.png"/>
+ </a>
+ </td>
+ {{else}}
+ <td>
+ <a href="#" data-bind="click: function(){ enableInvalidContentConsumer(invalidAdminRepositoryConsumer) }">
+ <img src="images/dialog-error-22-22.png"/>
+ </a>
+ </td>
+ {{/if}}
+ <td>${invalidAdminRepositoryConsumer.id}</td>
+ <td>${invalidAdminRepositoryConsumer.description}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</script>
+
+<script id="network-configuration-screen" type="text/html">
+ <div class="page-header">
+ <h4>${$.i18n.prop('network-configuration.header')}</h4>
+ </div>
+ <div id="network-configuration-form" data-bind='template: {name:"network-configuration-form-tmpl"}'></div>
+</script>
+
+<script id="network-configuration-form-tmpl" type="text/html">
+ <form id="network-configuration-edit-form" class="well form-horizontal">
+ <fieldset id="network-configuration-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="maxTotal">${$.i18n.prop('network-configuration.maxTotal')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required digits" id="maxTotal" name="maxTotal" size="8"
+ data-bind="value: networkConfiguration().maxTotal"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="maxTotal">${$.i18n.prop('network-configuration.maxTotalPerHost')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required digits" id="maxTotalPerHost" name="maxTotalPerHost" size="8"
+ data-bind="value: networkConfiguration().maxTotalPerHost"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="usePooling">${$.i18n.prop('network-configuration.usePooling')}</label>
+ <div class="controls">
+ <input type="checkbox" id="usePooling" name="usePooling" data-bind="checked: networkConfiguration().usePooling"/>
+ </div>
+ </div>
+ </fieldset>
+ <button id="network-configuration-btn-save" data-loading-text="${$.i18n.prop('common.loading')}"
+ data-bind="click: save" class="btn">${$.i18n.prop('save')}</button>
+ </form>
+</script>
+
+<script id="ui-configuration-screen" type="text/html">
+ <div class="page-header">
+ <h4>${$.i18n.prop('ui-configuration.header')}</h4>
+ </div>
+ <div id="ui-configuration-form" data-bind='template: {name:"ui-configuration-form-tmpl"}'></div>
+</script>
+
+<script id="ui-configuration-form-tmpl" type="text/html">
+ <form id="ui-configuration-edit-form" class="well form-horizontal">
+ <fieldset id="ui-configuration-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="maxTotal">${$.i18n.prop('ui-configuration.applicationUrl')}</label>
+ <div class="controls">
+ <input type="text" class="input-xxlarge required digits" id="applicationUrl" name="applicationUrl" size="8"
+ data-bind="value: uiConfiguration().applicationUrl"/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="disableRegistration">${$.i18n.prop('ui-configuration.disableRegistration')}</label>
+ <div class="controls">
+ <input type="checkbox" id="disableRegistration" name="disableRegistration" data-bind="checked: uiConfiguration().disableRegistration"/>
+ </div>
+ </div>
+
+ </fieldset>
+ <button id="ui-configuration-btn-save" data-bind="click: save" class="btn" data-loading-text="${$.i18n.prop('common.loading')}">${$.i18n.prop('save')}</button>
+ </form>
+</script>
+
+<script id="system-status-main" type="text/html">
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.version.info')}</h4>
+ </div>
+ <div id="status_version_info">
+ <img src="images/small-spinner.gif"/>
+ </div>
+ <div class="page-header">
+ <h3>${$.i18n.prop('system-status.header.main')}&nbsp;<a class="cursor-hand" onclick="refreshSystemStatus()"><img src="images/view-refresh-22-22.png"/></a></h3>
+ </div>
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.queues')}&nbsp;<a class="cursor-hand" onclick="displayQueueEntries()"><img src="images/view-refresh.png"/></a></h4>
+ </div>
+ <div id="status_queues">
+ <img src="images/small-spinner.gif"/>
+ </div>
+
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.scanning')}&nbsp;<a class="cursor-hand" onclick="displayScanningStats()"><img src="images/view-refresh.png"/></a></h4>
+ </div>
+ <div id="status_scanning">
+ <img src="images/small-spinner.gif"/>
+ </div>
+
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.caches')}&nbsp;<a class="cursor-hand" onclick="displayCacheEntries()"><img src="images/view-refresh.png"/></a></h4>
+ </div>
+ <div id="status_caches">
+ <img src="images/small-spinner.gif"/>
+ </div>
+
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.memory')}&nbsp;<a class="cursor-hand" onclick="displayMemoryUsage()"><img src="images/view-refresh.png"/></a></h4>
+ </div>
+ <div id="status_memory_info">
+ <img src="images/small-spinner.gif"/>
+ </div>
+
+ <div class="page-header">
+ <h4>${$.i18n.prop('system-status.header.current.time')}</h4>
+ </div>
+ <div id="status_current_time">
+ <img src="images/small-spinner.gif"/>
+ </div>
+
+</script>
+
+<script id="status_caches_tmpl" type="text/html">
+ <a class="btn btn-warning" onclick="flushAllCaches()">
+ ${$.i18n.prop('system-status.caches.flushAll')}
+ </a>
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('system-status.caches.grid.header.key')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.size')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.cacheHits')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.cacheMiss')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.cacheHitRate')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.inMemorySize')}</th>
+ <th>${$.i18n.prop('system-status.caches.grid.header.flush')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i,cacheEntry) cacheEntries}}
+ <tr>
+ <td>${cacheEntry.key}</td>
+ <td>${cacheEntry.size}</td>
+ <td>${cacheEntry.cacheHits}</td>
+ <td>${cacheEntry.cacheMiss}</td>
+ <td>${cacheEntry.cacheHitRate}</td>
+ <td>${cacheEntry.inMemorySize}</td>
+ <td>
+ <a onclick="flushCache('${cacheEntry.key}')">
+ {{if cacheEntry.size > 0 }}
+ <img src="images/user-trash-full.png"/>
+ {{else}}
+ <img src="images/user-trash.png"/>
+ {{/if}}
+ </a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</script>
+
+
+<script id="status_queues_tmpl" type="text/html">
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('system-status.queues.grid.header.key')}</th>
+ <th>${$.i18n.prop('system-status.queues.grid.header.size')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i,queueEntry) queueEntries}}
+ <tr>
+ <td>${queueEntry.key}</td>
+ <td>${queueEntry.entriesNumber}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</script>
+
+<script id="status_scanning_tmpl" type="text/html">
+ {{if repositoryScannerStatisticsList.length == 0}}
+ <h5>No scans in progress.</h5>
+ {{else}}
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('system-status.scanning.grid.header.repository')}</th>
+ <th>${$.i18n.prop('system-status.scanning.grid.header.files.processed')}</th>
+ <th>${$.i18n.prop('system-status.scanning.grid.header.files.new')}</th>
+ <th>${$.i18n.prop('system-status.scanning.grid.header.stats')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i,repositoryScannerStatistics) repositoryScannerStatisticsList}}
+ <tr>
+ <td>${repositoryScannerStatistics.managedRepository.name()}</td>
+ <td>${repositoryScannerStatistics.totalFileCount}</td>
+ <td>${repositoryScannerStatistics.newFileCount}</td>
+ <td>
+ <blockquote>
+ <table>
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('system-status.scanning.consumers.grid.header.name')}</th>
+ <th>${$.i18n.prop('system-status.scanning.consumers.grid.header.total')}</th>
+ <th>${$.i18n.prop('system-status.scanning.consumers.grid.header.average')} ms</th>
+ <th>${$.i18n.prop('system-status.scanning.consumers.grid.header.invocations.time')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(j,consumerScanningStatistics) repositoryScannerStatistics.consumerScanningStatisticsList}}
+ <tr>
+ <td>${consumerScanningStatistics.consumerKey}</td>
+ <td>${consumerScanningStatistics.count}</td>
+ <td>${consumerScanningStatistics.average}ms</td>
+ <td>${consumerScanningStatistics.time}ms</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ </blockquote>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ {{/if}}
+</script>
+
+<script id="changeAppearance" type="text/html">
+ <div class="page-header">
+ <h2>${$.i18n.prop('appearance-configuration.title-page')}</h2>
+ </div>
+
+ <h2>${$.i18n.prop('appearance-configuration.organisation-details')}</h2>
+
+ <p>
+ ${$.i18n.prop('apperance-configuration.details-description')}
+ </p>
+
+ <form id="appearance-configuration-form-id" class="well form-horizontal">
+ <fieldset id="appearance-configuration-fielset-id">
+ <div class="control-group">
+ <label class="control-label" for="name">${$.i18n.prop('appearance-configuration.name-label')}</label>
+ <div class="controls">
+ <input type="text" class="input-xlarge required" id="name" name="name" size="50"
+ data-bind="value: organisationInformation().name"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="name">${$.i18n.prop('appearance-configuration.url-label')}</label>
+ <div class="controls">
+ <input type="text" class="input-xlarge required" id="url" name="url" size="50"
+ data-bind="value: organisationInformation().url"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label"
+ for="name">${$.i18n.prop('appearance-configuration.logoLocation-label')}</label>
+ <div class="controls">
+ <input type="text" class="input-xxlarge" id="logoLocation" name="logoLocation" size="50"
+ data-bind="value: organisationInformation().logoLocation"/>
+ </div>
+ </div>
+ </fieldset>
+ <button id="appearance-configuration-btn-save" data-loading-text="${$.i18n.prop('common.loading')}" data-bind="click: save" class="btn">${$.i18n.prop('save')}</button>
+ </form>
+</script>
+
+
+<script id="file-upload-screen" type="text/html">
+ <div id="file-upload-main" data-bind='template:{name:"file-upload-tmpl"}'></div>
+</script>
+
+<script id="file-upload-tmpl" type="text/html">
+ <div class="page-header">
+ <h3>${$.i18n.prop('fileupload.header')}</h3>
+ </div>
+ <form id="fileupload" action="restServices/archivaUiServices/fileUploadService" method="POST"
+ enctype="multipart/form-data" class="well form-horizontal">
+
+ <fieldset id="network-proxy-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="repositoryId">${$.i18n.prop('fileupload.repositoryId')}</label>
+ <div class="controls">
+ <select id="repositoryId"
+ data-bind="options: managedRepositories, optionsText: 'name',optionsValue:'id',
+ value: repositoryId"></select>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="groupId">${$.i18n.prop('fileupload.groupId')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" data-bind="value: groupId" id="groupId" name="groupId" size="10" />
+ </div>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="artifactId">${$.i18n.prop('fileupload.artifactId')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" data-bind="value: artifactId" id="artifactId" name="artifactId" size="10" />
+ </div>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="version">${$.i18n.prop('fileupload.version')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" data-bind="value: version" id="version" name="version" size="10" />
+ </div>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="packaging">${$.i18n.prop('fileupload.packaging')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required" data-bind="value: packaging" id="packaging" name="packaging" size="10" />
+ </div>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="generatePom">${$.i18n.prop('fileupload.generatePom')}</label>
+ <div class="controls">
+ <input type="checkbox" class="xlarge" data-bind="value: generatePom" id="generatePom" name="generatePom" />
+ </div>
+ </div>
+ </div>
+ </fieldset>
+
+ <div class="row-fluid fileupload-buttonbar">
+ <div class="span7">
+ <span class="btn btn-success fileinput-button">
+ <i class="icon-plus icon-white"></i>
+ <span>${$.i18n.prop('fileupload.file.choose')}</span>
+ <input type="file" name="files[]" multiple="">
+ </span>
+ <button type="submit" class="btn btn-primary start">
+ <i class="icon-upload icon-white"></i>
+ <span>${$.i18n.prop('fileupload.start')}</span>
+ </button>
+ <button type="reset" class="btn btn-warning cancel">
+ <i class="icon-ban-circle icon-white"></i>
+ <span>${$.i18n.prop('fileupload.cancel')}</span>
+ </button>
+ <button type="button" class="btn btn-danger delete">
+ <i class="icon-trash icon-white"></i>
+ <span>${$.i18n.prop('fileupload.delete')}</span>
+ </button>
+ <input type="checkbox" class="toggle">
+ </div>
+ <div class="span5">
+ <div class="progress progress-success progress-striped active">
+ <div class="bar" style="width:0%;"></div>
+ </div>
+ </div>
+ </div>
+ <div>
+ <a href="#" id="fileupload-save-files">
+ <span class="btn btn-info" data-bind='click: saveArtifacts'>
+ <i class="icon-file icon-white"></i>
+ <span>${$.i18n.prop('fileupload.save')}</span>
+ </span>
+ </a>
+ </div>
+ <div class="fileupload-loading"></div>
+ <br>
+ <table class="table table-striped">
+ <tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery" id="uploaded-files-list"></tbody>
+ </table>
+</form>
+
+</script>
+
+
+<script id="template-upload" type="text/html">
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
+ <tr class="template-upload">
+ <td class="name"><span>{%=file.name%}</span></td>
+ <td><input type="text" id="classifier" name="classifier" placeholder="classifier" value=""/></td>
+ <td><span>pomFile:</span><input type="checkbox" id="pomFile" name="pomFile"/></td>
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
+ {% if (file.error) { %}
+ <td class="error" colspan="2">
+ <span class="label label-important">{%=$.i18n.prop('fileupload.error')%}</span>
+ {%=$.i18n.prop('fileupload.errors.'+[file.error]) || file.error%}
+ </td>
+ {% } else if (o.files.valid && !i) { %}
+ <td>
+ <div class="progress progress-success progress-striped active">
+ <div class="bar" style="width:0%;"></div>
+ </div>
+ </td>
+ <td class="start">
+ {% if (!o.options.autoUpload) { %}
+ <button class="btn btn-primary">
+ <i class="icon-upload icon-white"></i>
+ <span>{%=$.i18n.prop('fileupload.start')%}</span>
+ </button>
+ {% } %}
+ </td>
+ {% } else { %}
+ <td colspan="2"></td>
+ {% } %}
+ <td class="cancel">
+ {% if (!i) { %}
+ <button class="btn btn-warning">
+ <i class="icon-ban-circle icon-white"></i>
+ <span>{%=$.i18n.prop('fileupload.cancel')%}</span>
+ </button>
+ {% } %}
+ </td>
+ </tr>
+ {% } %}
+</script>
+
+<script id="template-download" type="text/html">
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
+ <tr class="template-download">
+ <td class="name"><span>{%=file.name%}</span></td>
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
+ {% if (file.error) { %}
+ <td class="error" colspan="2">
+ <span class="label label-important">{%=$.i18n.prop('fileupload.error')%}</span>
+ {%=$.i18n.prop('fileupload.errors.'+[file.error]) || file.error%}
+ </td>
+ {% } else { %}
+ <td colspan="2"></td>
+ {% } %}
+ <td class="delete">
+ <button class="btn btn-danger" data-type="{%=file.deleteType%}"
+ data-url="restServices/archivaUiServices/fileUploadService/{%=file.deleteUrl%}">
+ <i class="icon-trash icon-white"></i>
+ <span>{%=$.i18n.prop('fileupload.destroy')%}</span>
+ </button>
+ <input type="checkbox" name="delete" value="1">
+ </td>
+ </tr>
+{% } %}
+</script>
+
+<script id="report-base" type="text/html">
+ <div class="page-header">
+ <h2>${$.i18n.prop('report.title')}</h2>
+ </div>
+
+ <ul class="nav nav-tabs">
+ <li class="active" id="report-stat-tab-li"><a href="#report-stat-tab-content" data-toggle="tab">${$.i18n.prop('report.statistics.title')}</a></li>
+ <li id="report-health-tab-li"><a href="#report-health-tab-content" data-toggle="tab">${$.i18n.prop('report.health.title')}</a></li>
+ <li id="report-result-tab-li" class="hide"><a href="#report-result" data-toggle="tab">${$.i18n.prop('report.result.title')}</a></li>
+ </ul>
+
+ <div class="tab-content">
+ <div class="tab-pane active" id="report-stat-tab-content">
+ <form class="form-horizontal" id="report-statistics-form-id">
+ <fieldset id="form-statistics-report">
+ <div class="row-fluid">
+ <div class="span6 row-fluid">
+ <div class="row-fluid" id="repositoriesErrorMessage"></div>
+ <div class="row-fluid">
+ <div class="span6 dotted">
+ <h5>${$.i18n.prop('report.statistics.selected-repositories.label')}</h5>
+ <hr/>
+ <div style="min-height: 40px"
+ data-bind="sortable: { template: 'statistics-repositories-order-tmpl', data:statisticsReport().repositories}">
+ </div>
+ </div>
+ <div class="span6 dotted">
+ <h5>${$.i18n.prop('repository.groups.available-repositories.label')}</h5>
+ <hr/>
+ <div style="min-height: 40px"
+ data-bind="sortable: {template: 'statistics-repositories-order-tmpl',data:availableRepositories}">
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="span6 well">
+ <div class="control-group">
+ <label for="rowCountStatistics" class="control-label">
+ ${$.i18n.prop('report.statistics.row-count.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="rowCountStatistics" name="rowCountStatistics" class="input-small"
+ data-bind="value: statisticsReport().rowCount"/>
+
+ <a class="btn btn-warning btn-mini" id="rowcount-info-button"
+ data-original-title="${$.i18n.prop('report.statistics.rowCount.explanations-title')}"
+ data-content="${$.i18n.prop('report.statistics.rowCount.explanations')}"
+ data-placement="left" data-toggle="button">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="startDate" class="control-label">
+ ${$.i18n.prop('report.statistics.start-date.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="startDate" name="startDate" class="input-small"
+ data-bind="value: statisticsReport().startDate"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="endDate" class="control-label">
+ ${$.i18n.prop('report.statistics.end-date.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="endDate" name="endDate" class="input-small"
+ data-bind="value: statisticsReport().endDate"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="form-actions">
+ <button class="btn btn-primary" data-bind="click: showStatistics">
+ ${$.i18n.prop('report.statistics.btn-view')}
+ </button>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+
+ <div class="tab-pane" id="report-health-tab-content">
+ <form class="form-horizontal" id="report-health-form-id">
+ <fieldset id="form-health-report">
+ <div class="control-group">
+ <label for="rowCountHealth" class="control-label">
+ ${$.i18n.prop('report.statistics.row-count.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="rowCountHealth" name="rowCountHealth" class="input-small required"
+ data-bind="value: healthReport().rowCount"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="groupId" class="control-label">
+ ${$.i18n.prop('report.health.groupId.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="groupId" name="groupId" data-bind="value: healthReport().groupId"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="repositoryId" class="control-label">
+ ${$.i18n.prop('report.health.repositoryId.label')}
+ </label>
+ <div class="controls">
+ <select id="repositoryId" name="repositoryId" data-bind="value: healthReport().repositoryId"
+ class="required">
+ <option value="all">${$.i18n.prop('report.select.all-repositories')}</option>
+ {{each(i, repoId) repositoriesList}}
+ <option value="${repoId}">${repoId}</option>
+ {{/each}}
+ </select>
+ </div>
+ </div>
+ <div class="form-actions">
+ <a href="#" class="btn btn-primary" data-bind="click: showHealth">
+ ${$.i18n.prop('report.health.btn-view')}
+ </a>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+
+ <div class="tab-pane" id="report-result">
+ </div>
+ </div>
+</script>
+
+<script id="statistics-repositories-order-tmpl" type="text/html">
+ <div class="well draggable-item">
+ ${$data}
+ </div>
+</script>
+
+<script id="report-health" type="text/html">
+ <div class="page-header">
+ <h3>${$.i18n.prop('report.health.title')}</h3>
+ </div>
+ <table class="table table-bordered table-striped"
+ data-bind="simpleGrid: tableReportViewModel,simpleGridTemplate:'table-report-tmpl',pageLinksId:'reportHealthPageLinkId'">
+ </table>
+ <div id="reportHealthPageLinkId"></div>
+</script>
+
+<script id="report-statistics" type="text/html">
+ <div class="page-header">
+ <h3>${$.i18n.prop('report.statistics.title')}</h3>
+ </div>
+ <table class="table table-bordered table-striped"
+ data-bind="simpleGrid: tableReportViewModel,simpleGridTemplate:'table-report-tmpl',pageLinksId:'reportStatisticsPageLinkId'">
+ </table>
+ <div id="reportStatisticsPageLinkId"></div>
+</script>
+<script id="table-report-tmpl" type="text/html">
+ <thead>
+ {{each(i, columnDefinition) columns}}
+ <th>${ columnDefinition.headerText }</th>
+ {{/each}}
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ {{var val = (typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText])}}
+ <td>
+ ${val}
+ </td>
+ {{/each}}
+ </tr>
+ {{/each}}
+ </tbody>
+</script>
+
+<script type="text/html" id="redback-runtime-configuration-main">
+ <div class="page-header">
+ <h2>${$.i18n.prop('redback-runtime-configuration.title')}</h2>
+ </div>
+ <div id="redback-runtime-configuration-content" data-bind='template: {name:"redback-runtime-configuration-content-tmpl"}'>
+ </div>
+</script>
+
+<script type="text/html" id="redback-runtime-configuration-content-tmpl">
+ <ul class="nav nav-tabs">
+ <li class="active" id="redback-runtime-general-li"><a href="#redback-runtime-general-content" data-toggle="tab">${$.i18n.prop('redback.runtime.general.title')}</a></li>
+ <li id="redback-runtime-ldap-li"><a href="#redback-runtime-ldap-content" data-toggle="tab">${$.i18n.prop('redback.runtime.ldap.title')}</a></li>
+ <li id="redback-runtime-properties-li"><a href="#redback-runtime-properties-content" data-toggle="tab">${$.i18n.prop('redback.runtime.properties.title')}</a></li>
+ <li id="redback-runtime-users-cache-li"><a href="#redback-runtime-users-cache-content" data-toggle="tab">${$.i18n.prop('redback.runtime.users.cache.title')}</a></li>
+ </ul>
+
+ <div class="tab-content">
+ <div class="tab-pane active" id="redback-runtime-general-content">
+ <div class="well">
+ <div class="row-fluid">
+ <div class="span4 dotted">
+ <h5>${$.i18n.prop('redback.runtime.user-managers.impls.choosed')}</h5>
+ <div style="min-height: 40px" id="user-mananagers-sortables-choosed"
+ data-bind="sortable: { template: 'redback-runtime-general-content-usermanagers', data:usedUserManagerImpls,afterMove: userManagerImplMoved}">
+ </div>
+ </div>
+
+ <div class="span4 dotted">
+ <h5>${$.i18n.prop('redback.runtime.user-managers.impls.available')}</h5>
+ <div style="min-height: 40px"id="user-mananagers-sortables-availables"
+ data-bind="sortable: {template: 'redback-runtime-general-content-usermanagers',data:availableUserManagerImpls,afterMove: userManagerImplMoved}">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-pane" id="redback-runtime-ldap-content">
+ <div class="well">
+ <form class="form-horizontal" id="redback-runtime-ldap-form-id">
+
+ <div class="control-group">
+ <label for="ldapHost" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.host.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldapHost" name="ldapHost" class="input-xlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().hostName"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldapPort" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.port.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldapPort" name="ldapPort" class="input-large"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().port"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldapBaseDn" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.baseDn.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldapBaseDn" name="ldapBaseDn" class="input-xxlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().baseDn"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldapBindDn" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.bindDn.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldapBindDn" name="ldapBindDn" class="input-xxlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().bindDn"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldap-ssl" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.ssl.label')}
+ </label>
+ <div class="controls">
+ <input type="checkbox" id="ldap-ssl" name="ldap-ssl"
+ data-bind="checked: redbackRuntimeConfiguration().ldapConfiguration().ssl"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldapPassword" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.password.label')}
+ </label>
+ <div class="controls">
+ <input type="password" id="ldapPassword" name="ldapPassword" class="input-xlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().password"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldap-context-factory" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.contextFactory.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldap-context-factory" name="ldap-context-factory" class="input-xlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().contextFactory"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label for="ldap-authenticationMethod" class="control-label">
+ ${$.i18n.prop('redback.runtime.ldap.authenticationMethod.label')}
+ </label>
+ <div class="controls">
+ <input type="text" id="ldap-authenticationMethod" name="ldap-authenticationMethod" class="input-xlarge"
+ data-bind="value: redbackRuntimeConfiguration().ldapConfiguration().authenticationMethod"/>
+ </div>
+ </div>
+ <!-- TODO extraPropertiesEntries -->
+
+ </form>
+
+ <button data-bind="click: checkChangedLdapConfiguration,css:{ 'btn-warning': redbackRuntimeConfiguration().ldapConfiguration().modified() },
+ enabled: redbackRuntimeConfiguration().ldapConfiguration().modified()"
+ id="ldap-configuration-check-modification"class="btn">${$.i18n.prop('redback.runtime.ldap.checkModification')}</button>
+
+ <button data-bind="click: checkLdapServerConfiguration"
+ id="ldap-configuration-check-server"class="btn">${$.i18n.prop('redback.runtime.ldap.checkServer')}</button>
+
+ </div>
+ </div>
+
+ <div class="tab-pane" id="redback-runtime-properties-content">
+
+ <div class="well">
+ <table id="proxyConnectorsTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'properties-grid',pageLinksId:'properties-grid-pagination'">
+ </table>
+ <div id="properties-grid-pagination"></div>
+ </div>
+ </div>
+
+ <div class="tab-pane" id="redback-runtime-users-cache-content">
+
+ <div class="well">
+
+
+ <form class="form-horizontal" id="redback-runtime-general-form-id">
+ <div class="control-group">
+ <label for="redback-runtime-useUsersCache" class="control-label">${$.i18n.prop('redback.runtime.useUsersCache.label')}</label>
+ <div class="controls">
+ <input type="checkbox" id="redback-runtime-useUsersCache" name="redback-runtime-useUsersCache"
+ data-bind="checked: redbackRuntimeConfiguration().useUsersCache"/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="usersCacheTimeToLiveSeconds">${$.i18n.prop('redback.runtime.usersCacheTimeToLiveSeconds.label')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required numeric" data-bind="value: redbackRuntimeConfiguration().usersCacheConfiguration().timeToLiveSeconds"
+ id="usersCacheTimeToLiveSeconds" name="usersCacheTimeToLiveSeconds" />
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="usersCacheTimeToIdleSeconds">${$.i18n.prop('redback.runtime.usersCacheTimeToIdleSeconds.label')}</label>
+ <div class="controls">
+ <input type="text" class="xlarge required numeric" data-bind="value: redbackRuntimeConfiguration().usersCacheConfiguration().timeToIdleSeconds"
+ id="usersCacheTimeToIdleSeconds" name="usersCacheTimeToIdleSeconds" />
+ </div>
+ </div>
+
+ </form>
+
+
+ </div>
+ </div>
+
+ <div>
+ <button data-bind="click: saveRedbackRuntimeConfiguration,css:{ 'btn-warning': redbackRuntimeConfiguration().modified() | redbackRuntimeConfiguration().ldapConfiguration().modified() }"
+ id="redback-runtime-configuration-save"class="btn">${$.i18n.prop('save')}</button>
+ </div>
+
+</script>
+
+<script id='properties-grid' type='text/html'>
+ <thead>
+ <tr>
+ <th></th>
+ <th>${$.i18n.prop('redback.runtime.properties.key.label')}</th>
+ <th>${$.i18n.prop('redback.runtime.properties.value.label')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr>
+ <td>
+ {{var key = row.key}}
+ <a class="popover-doc"
+ data-original-title="${$.i18n.prop('redback.runtime.properties.help.title')}"
+ data-content="${$.i18n.prop(key+'.help.content')}">
+ <span class="btn btn-info"><i class="icon-question-sign icon-white"></i></span>
+ </a>
+ </td>
+ <td>${row.key}</td>
+ <td><input type="text" class="input-xxlarge" data-bind="value: row.value"></td>
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+<script id="redback-runtime-general-content-usermanagers" type="text/html">
+ <div class="well draggable-item">
+ ${$data.description}
+ </div>
+</script>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/generics.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/generics.html
new file mode 100644
index 000000000..9fd3989c8
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/generics.html
@@ -0,0 +1,67 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<script id='alert-message-success' type='text/html'>
+ <div class="alert fade in alert-success" data-alert="alert">
+ <a class="close" data-dismiss="alert" href="#" id='alert-message-success-close-a'>&#215;</a>
+ ${message}
+ </div>
+</script>
+<script id='alert-message-error' type='text/html'>
+ <div class="alert fade in alert-error" data-alert="alert">
+ <a class="close" data-dismiss="alert" href="#" id='alert-message-error-close-a'>&#215;</a>
+ ${message}
+ </div>
+</script>
+<script id='alert-message-warning' type='text/html'>
+ <div class="alert fade in alert-heading" data-alert="alert">
+ <a class="close" data-dismiss="alert" href="#" id='alert-message-warning-close-a'>&#215;</a>
+ ${message}
+ </div>
+</script>
+<script id='alert-message-info' type='text/html'>
+ <div class="alert fade in alert-info" data-alert="alert">
+ <a class="close" data-dismiss="alert" href="#" id='alert-message-info-close-a'>&#215;</a>
+ ${message}
+ </div>
+</script>
+
+<script id='footer-tmpl' type='text/html'>
+ <div class="pull-left">
+ <a target="_blank" href="http://archiva.apache.org/">Apache Archiva&nbsp;-&nbsp;${version}</a>
+ </div>
+ <div class="pull-right">
+ Copyright &#169; ${copyrightRange} <a target="_blank" href="http://www.apache.org/">The Apache Software
+ Foundation</a>
+ </div>
+</script>
+
+<script id="ko_simpleGrid_pageLinks" type="text/html">
+ <div class="pagination">
+ <ul>
+ {{each(i) ko.utils.range(1, maxPageIndex)}}
+ <li data-bind="css: { active: i == currentPageIndex() }">
+ <a href="#" data-bind="click: function() { currentPageIndex(i) }">
+ ${ i + 1 }
+ </a>
+ </li>
+ {{/each}}
+ </ul>
+ </div>
+</script>
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/menu.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/menu.html
new file mode 100644
index 000000000..4be060d2f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/menu.html
@@ -0,0 +1,116 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<script type="text/html" id="main_menu_tmpl">
+ <div id="main-menu">
+
+ <ul class="nav nav-list" data-bind="foreach: artifactMenuItems">
+ <!-- ko ifnot: id -->
+ <li class="nav-header archiva-nav-header" data-bind="text: text"></li>
+ <!-- /ko -->
+ <!-- ko if: id -->
+ <li data-bind='redbackP: $data.redback, css: { active: $data.href == "#"+$root.activeMenuId() }'>
+ <a data-bind="text: text, attr: { id: id, href: href}"></a>
+ </li>
+ <!-- /ko -->
+ </ul>
+
+ <ul class="nav nav-list" redback-permissions="{permissions: ['archiva-manage-configuration']}"
+ data-bind="foreach: administrationMenuItems">
+ <!-- ko ifnot: id -->
+ <li class="nav-header archiva-nav-header" data-bind="text: text"></li>
+ <!-- /ko -->
+ <!-- ko if: id -->
+ <li data-bind='redbackP: $data.redback, css: { active: $data.href == "#"+$root.activeMenuId() }'>
+ <a data-bind="text: text, attr: { id: id, href: href}"></a>
+ </li>
+ <!-- /ko -->
+ </ul>
+
+ <ul class="nav nav-list" redback-permissions="{permissions: ['archiva-manage-users']}"
+ data-bind="foreach: usersMenuItems">
+ <!-- ko ifnot: id -->
+ <li class="nav-header archiva-nav-header" data-bind="text: text"></li>
+ <!-- /ko -->
+ <!-- ko if: id -->
+ <li data-bind='redbackP: $data.redback, css: { active: $data.href == "#"+$root.activeMenuId() }'>
+ <a data-bind="text: text, attr: { id: id, href: href}"></a>
+ </li>
+ <!-- /ko -->
+ </ul>
+
+ <ul class="nav nav-list" data-bind="foreach: docsMenuItems">
+ <!-- ko ifnot: id -->
+ <li class="nav-header archiva-nav-header" data-bind="text: text"></li>
+ <!-- /ko -->
+ <!-- ko if: id -->
+ <li data-bind='redbackP: $data.redback, css: { active: $data.href == "#"+$root.activeMenuId() }'>
+ <a data-bind="text: text, attr: { id: id, href: href, target: target}"></a>
+ </li>
+ <!-- /ko -->
+ </ul>
+
+ </div>
+</script>
+
+<script id="topbar_menu_tmpl" type="text/html">
+ <div id="topbar-menu">
+ <div class="navbar navbar-fixed-top"><!-- navbar-inverse for black topbar olamy: prefer non black :-) -->
+
+ <div style="max-height: 40px" class="navbar-inner">
+ <div class="container-fluid">
+ <div id="organisation-logo" style="max-height: 40px" class="pull-left"></div>
+ <ul class="nav pull-right">
+ <li id="create-admin-link" style="display: none">
+ <a href="#open-admin-create-box" onclick="adminCreateBox();" id="create-admin-link-a">
+ <span class="label label-important">${$.i18n.prop('create.admin.page.link')}</span>
+ </a>
+ </li>
+ <li id="login-link" style="display: none">
+ <a onclick="loginBox();" id="login-link-a">
+ <span class="btn btn-success label force-upper-case">${$.i18n.prop('login')}</span>
+ </a>
+ </li>
+ <li id="change-password-link">
+ <a onclick="editUserDetailsBox();">
+ <span class="btn btn-warning label force-upper-case">${$.i18n.prop('edit.details')}</span>
+ </a>
+ </li>
+ <li id="logout-link" style="display: none">
+ <a onclick="logout(false);" id="logout-link-a">
+ <span class="btn btn-danger label force-upper-case">${$.i18n.prop('logout')}</span>
+ </a>
+ </li>
+ <li id="register-link" style="display: none">
+ <a onclick="registerBox();" id="register-link-a">
+ <span class="btn btn-info label force-upper-case">${$.i18n.prop('register')}</span>
+ </a>
+ </li>
+ <li>
+ <div class="ui-widget navbar-search">
+ <input type="text" class="ui-autocomplete-input search-query" id="quick-search-autocomplete"
+ placeholder="${$.i18n.prop('menu.topbar.quicksearch')}"/>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ </div>
+ </div>
+</script> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/modal.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/modal.html
new file mode 100644
index 000000000..3ec4278ca
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/modal.html
@@ -0,0 +1,42 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<div id="dialog-confirm-modal" class="modal hide fade" style="display: block;">
+ <div class="modal-header">
+ <a class="close" href="#" data-dismiss="modal">&#215;</a>
+
+ <h3 id="dialog-confirm-modal-header-title"></h3>
+ </div>
+ <div class="modal-body">
+ <p id="dialog-confirm-modal-body-text"></p>
+ </div>
+ <div class="modal-footer">
+ <a class="btn btn-secondary" id="dialog-confirm-modal-cancel" data-loading-text="${$.i18n.prop('common.loading')}">${$.i18n.prop('cancel')}</a>
+ <a class="btn btn-primary" id="dialog-confirm-modal-ok" data-loading-text="${$.i18n.prop('common.loading')}">${$.i18n.prop('ok')}</a>
+ </div>
+</div>
+
+<div id="dialog-modal-merge-repo" class="modal hide fade" style="display: block;">
+ <div class="modal-header">
+ <a class="close" href="#" data-dismiss="modal">&#215;</a>
+
+ <h3 id="dialog-modal-merge-repo-header-title">${$.i18n.prop('managedrepository.repomerge.dialog.header')}</h3>
+ </div>
+ <div class="modal-body" id="dialog-modal-merge-repo-body-text">>
+ </div>
+</div>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
new file mode 100644
index 000000000..335a5afc4
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
@@ -0,0 +1,1686 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<script id="repositoriesMain" type="text/html">
+ <div class="page-header">
+ <h2><img src="images/system-file-manager-32-32.png"/>${$.i18n.prop('administration.repositories')}</h2>
+ </div>
+
+ <ul id="repositories-tabs" class="nav nav-tabs">
+ <li class="active">
+ <a data-toggle="tab" href="#managed-repositories-content">${$.i18n.prop('managedrepositories.grid.head')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" href="#remote-repositories-content">${$.i18n.prop('remoterepositories.grid.head')}</a>
+ </li>
+ </ul>
+ <div class="tab-content">
+ <div id="managed-repositories-content" class="tab-pane active">
+ <ul id="managed-repositories-pills" class="nav nav-pills">
+ <li class="active" id="managed-repositories-view-li">
+ <a data-toggle="tab" href="#managed-repositories-view" id="managed-repositories-view-a">${$.i18n.prop('managedrepositories.grid.tab.title')}</a>
+ </li>
+ <li id="managed-repository-edit-li">
+ <a data-toggle="tab" href="#managed-repository-edit">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="managed-repositories-tabs-content" class="pill-content">
+ <div id="managed-repositories-view" class="pill-pane active">
+ <div id="managed-repositories-bulk-save-btn"
+ data-bind='template:{name:"managed-repositories-bulk-save-tmpl"}'></div>
+ <table class="table table-striped table-bordered" id="managed-repositories-table"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko_managed-repositoriesGrid',pageLinksId:'managed-repositoriesPagination',data:'managedRepositories'">
+ </table>
+ <div id="managed-repositoriesPagination"></div>
+ <div id="managed-repositories-pom-snippet"></div>
+ </div>
+ <div id="managed-repository-edit" class="pill-pane" data-bind='template: {name:"managed-repository-edit-tmpl"}'>
+ </div>
+ </div>
+ </div>
+
+
+ <div id="remote-repositories-content" class="tab-pane">
+ <ul id="remote-repositories-pills" class="nav nav-pills">
+ <li class="active" id="remote-repositories-view-li">
+ <a data-toggle="tab" href="#remote-repositories-view" id="remote-repositories-view-a">${$.i18n.prop('remoterepositories.grid.tab.title')}</a>
+ </li>
+ <li id="remote-repository-edit-li">
+ <a data-toggle="tab" href="#remote-repository-edit">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="remote-repositories-tabs-content" class="pill-content">
+ <div id="remote-repositories-view" class="pill-pane active">
+ <div id="remote-repositories-bulk-save-btn"
+ data-bind='template:{name:"remote-repositories-bulk-save-tmpl"}'></div>
+ <table class="table table-striped table-bordered" id="remote-repositories-table"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko_remote-repositoriesGrid',pageLinksId:'remote-repositoriesPagination',data:'remoteRepositories'">
+ </table>
+ <div id="remote-repositoriesPagination"></div>
+ </div>
+ <div id="remote-repository-edit" class="pill-pane" data-bind='template:{name:"remote-repository-edit-tmpl"}'>
+ </div>
+ </div>
+ </div>
+ </div>
+</script>
+
+<script id='ko_managed-repositoriesGrid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th title="${ columnDefinition.title }">${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>Releases</th>
+ <th>Snapshots</th>
+ <th>${$.i18n.prop('managedrepository.actions')}</th>
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('modified')}</th>
+ <th>${$.i18n.prop('managed.repository.rss.header')}</th>
+ <th title="${$.i18n.prop('managedrepository.stats')}">${$.i18n.prop('managedrepository.stats.grid.header')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ {{each(j, columnDefinition) columns}}
+ <td>
+ ${ typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText] }
+ </td>
+ {{/each}}
+ <td>
+ {{if row.releases() == true}}
+ <img src="images/weather-clear-22-22.png" title="${$.i18n.prop('release.included')}"/>
+ {{else}}
+ <img src="images/dialog-error-22-22.png" title="${$.i18n.prop('release.notincluded')}"/>
+ {{/if}}
+ </td>
+
+ <td>
+ {{if row.snapshots() == true}}
+ <img src="images/weather-clear-22-22.png" title="${$.i18n.prop('snapshots.included')}"/>
+ {{else}}
+ <img src="images/dialog-error-22-22.png" title="${$.i18n.prop('snapshots.notincluded')}"/>
+ {{/if}}
+ </td>
+ <td>
+ <div class="btn-group">
+ <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">Actions<span class="caret"></span> </a>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="#" data-bind="click: function(){ scanNow(row) }">
+ <span class="btn btn-success">
+ <i class="icon-refresh icon-white"></i>
+ </span>
+ ${$.i18n.prop('managedrepository.scan.grid.header')}
+ </a>
+ </li>
+ <li>
+ <a href="#" data-bind="click: function(){directoriesScan(row)}">
+ <span class="btn btn-warning">
+ <i class="icon-wrench icon-white"></i>
+ </span>
+ ${$.i18n.prop('managedrepository.scan.directories.grid.header')}
+ </a>
+ </li>
+ <li>
+ <a href="#" data-bind="click: function(){ showPomSnippet(row) }">
+ <span class="btn btn-info">
+ <i class="icon-user icon-white"></i>
+ </span>
+ ${$.i18n.prop('managedrepository.pomsnippet')}
+ </a>
+ </li>
+ <li>
+ {{if row.stageRepoNeeded()}}
+ stage
+ {{/if}}
+ </li>
+ <li>
+ <!-- todo check archiva-merge-repository operation -->
+ <a href="#" data-bind="click: function(){ mergeRepo(row) }">
+ <span class="btn btn-info">
+ <i class="icon-share icon-white"></i>
+ </span>
+ ${$.i18n.prop('managedrepository.mergerepo')}
+ </a>
+ </li>
+ </ul>
+ </div>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ editManagedRepository(row) }">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ removeManagedRepository(row) }">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ {{if row.modified()}}
+ <td>
+ <a href="#" class="btn btn-warning" data-bind="click: function(){ updateManagedRepository(row) }">${$.i18n.prop('save')}</a>
+ </td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ <td>
+ <a href="${row.feedsUrl}"><img src="images/atom.gif" alt=""
+ title="${$.i18n.prop('managedrepository.feeds')} ${row.name()}"/></a>
+ </td>
+ <td id="managedrepository-stats-${row.id()}">
+ <img src="images/utilities-system-monitor-22-22.png"
+ data-original-title="${$.i18n.prop('managedrepository.stats')}"
+ data-bind="event: { mouseover: function(){ showStats(row) }, mouseout: function(){ hideStats(row) },}"
+ id="managedrepository-stats-img-${row.id()}"/>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+<script id="managed-repository-edit-tmpl" type='text/html'>
+ <form id="managed-repository-edit-form" class="well form-horizontal">
+ <fieldset id="managed-repository-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="id">${$.i18n.prop('id')}</label>
+
+ <div class="controls">
+ {{if update}}
+ <span class="uneditable-input">${$data.managedRepository.id}</span>
+ {{else}}
+ <input type="text" class="input-xlarge required" id="id" name="id" size="50"
+ data-bind="value: managedRepository.id,css:{'uneditable-input': update},readonly:update"/>
+ {{/if}}
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-id-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.id.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.id.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="name">${$.i18n.prop('name')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xlarge required" id="name" name="name" size="50"
+ data-bind="value: managedRepository.name"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-name-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.name.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.name.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="location">${$.i18n.prop('directory')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xxlarge required" id="location" name="location" size="50"
+ data-bind="value: managedRepository.location"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-location-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.location.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.location.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="indexDirectory">${$.i18n.prop('index.directory')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xxlarge" id="indexDirectory" name="indexDirectory" size="50"
+ data-bind="value: managedRepository.indexDirectory"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-indexDirectory-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.indexDirectory.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.indexDirectory.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="layout">${$.i18n.prop('type')}</label>
+
+ <div class="controls">
+ <select id="layout"
+ data-bind="options: availableLayouts,optionsText: 'label',optionsValue:'type',value: managedRepository.layout"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="cronExpression">${$.i18n.prop('cronExpression')}</label>
+
+ <div class="controls">
+ <input type="text" id="cronExpression" class="required" name="cronExpression" size="40"
+ data-bind="value: managedRepository.cronExpression"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="cronExpression-info-button"
+ data-original-title="${$.i18n.prop('cronExpression.help.title')}"
+ data-content="${$.i18n.prop('cronExpression.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="daysOlder">${$.i18n.prop('daysOlder')}</label>
+
+ <div class="controls">
+ <input type="text" id="daysOlder" class="digits" name="daysOlder" size="5"
+ data-bind="value: managedRepository.daysOlder"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-daysOlder-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.daysOlder.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.daysOlder.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="retentionCount">${$.i18n.prop('retentionCount')}</label>
+
+ <div class="controls">
+ <input type="text" id="retentionCount" name="retentionCount" size="5"
+ data-bind="value: managedRepository.retentionCount"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-retentionCount-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.retentionCount.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.retentionCount.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="description">${$.i18n.prop('description')}</label>
+
+ <div class="controls">
+ <textarea rows="3" id="description" name="description"
+ data-bind="value: managedRepository.description"></textarea>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-description-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.description.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.description.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="releases">${$.i18n.prop('releases')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="releases" name="releases" size="5"
+ data-bind="checked: managedRepository.releases"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-release-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.release.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.release.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="snapshots">${$.i18n.prop('snapshots')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="snapshots" name="snapshots" size="5"
+ data-bind="checked: managedRepository.snapshots"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-snapshots-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.snapshots.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.snapshots.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="blockRedeployments">${$.i18n.prop('blockRedeployments')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="blockRedeployments" name="blockRedeployments" size="5"
+ data-bind="checked: managedRepository.blockRedeployments"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-blockRedeployments-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.blockRedeployments.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.blockRedeployments.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="scanned">${$.i18n.prop('scanned')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="scanned" name="scanned" size="5" data-bind="checked: managedRepository.scanned"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-scanned-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.scanned.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.scanned.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="deleteReleasedSnapshots">${$.i18n.prop('deleteReleasedSnapshots')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="deleteReleasedSnapshots" name="deleteReleasedSnapshots" size="5"
+ data-bind="checked: managedRepository.deleteReleasedSnapshots"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-deleteReleasedSnapshots-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.deleteReleasedSnapshots.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.deleteReleasedSnapshots.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="stageRepoNeeded">${$.i18n.prop('stageRepoNeeded')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="stageRepoNeeded" name="stageRepoNeeded" size="5"
+ data-bind="checked: managedRepository.stageRepoNeeded"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="managedRepository-stageRepoNeeded-info-button"
+ data-original-title="${$.i18n.prop('managedRepository.stageRepoNeeded.help.title')}"
+ data-content="${$.i18n.prop('managedRepository.stageRepoNeeded.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="skipPackedIndexCreation">${$.i18n.prop('skipPackedIndexCreation')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="skipPackedIndexCreation" name="skipPackedIndexCreation" size="5"
+ data-bind="checked: managedRepository.skipPackedIndexCreation"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="skipPackedIndexCreation-info-button"
+ data-original-title="${$.i18n.prop('skipPackedIndexCreation.help.title')}"
+ data-content="${$.i18n.prop('skipPackedIndexCreation.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ </fieldset>
+ <button data-bind="click: save" class="btn" id="managed-repository-save-button">${$.i18n.prop('save')}</button>
+ <button data-bind="click: displayGrid" class="btn">${$.i18n.prop('cancel')}</button>
+ </form>
+</script>
+
+<script id="managed-repository-delete-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+
+ <div>
+ <span><strong>${$.i18n.prop('managedrepository.delete.warning.message')}</strong>.</span>
+
+ <div>${$.i18n.prop('id')}: ${id()}</div>
+ <div>${$.i18n.prop('name')}: ${name()}</div>
+ </div>
+ <div>
+ ${$.i18n.prop('managedrepository.delete.content')}: <input type="checkbox" id="managedrepository-deletecontent">
+ </div>
+ </div>
+</script>
+
+<script type="text/html" id="remote-repository-delete-modal-tmpl">
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+<script id="managed-repository-location-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('managedrepository.location.already.exists')}</span>
+
+ <div>
+ <span><strong>${$.i18n.prop('managedrepository.location.already.exists.warning.message')}</strong>.</span>
+
+ <div>${$.i18n.prop('id')}: ${id()}</div>
+ <div>${$.i18n.prop('name')}: ${name()}</div>
+ </div>
+ </div>
+</script>
+<script id="managed-repository-scan-now-modal-tmpl" type='text/html'>
+ <div>
+ ${$.i18n.prop('managedrepository.scan.all')}: <input type="checkbox" id="managed-repository-scan-now-all">
+ </div>
+</script>
+<script id="managed-repository-stats-tmpl" type='text/html'>
+ <div id="managedrepository-stats-${managedRepository.id()}-popover" style="display:none">
+ <div>${$.i18n.prop('managedrepository.stats.endTime')}: ${lastScanDate()}</div>
+ <div>${$.i18n.prop('managedrepository.stats.duration')}: ${duration()}ms</div>
+ <div>${$.i18n.prop('managedrepository.stats.totalFileCount')}: ${totalFileCount()}</div>
+ <div>${$.i18n.prop('managedrepository.stats.newFileCount')}: ${newFileCount()}</div>
+ </div>
+</script>
+<script id="pom-snippet-tmpl" type='text/html'>
+ <div class="page-header">
+ <h2>POM Snippet</h2></div>
+ </div>
+ <div><a onclick="$('#managed-repositories-pom-snippet').effect('blind')">${$.i18n.prop('hide')}</a></div>
+ <pre>${$data}</pre>
+</script>
+
+<!-- remote part -->
+
+<script id='ko_remote-repositoriesGrid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th title="${ columnDefinition.title }">${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('modified')}</th>
+ <th>${$.i18n.prop('description')}</th>
+ <th>${$.i18n.prop('remoterepository.downloadremoteindex')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ {{each(j, columnDefinition) columns}}
+ <td>
+ ${ typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText] }
+ </td>
+ {{/each}}
+ <td>
+ <a href="#" data-bind="click: function(){ editRemoteRepository(row) }">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ removeRemoteRepository(row) }">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ {{if row.modified()}}
+ <td>
+ <a href="#" class="btn btn-warning" data-bind="click: function(){ updateRemoteRepository(row) }">${$.i18n.prop('save')}</a>
+ </td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ <td>
+ {{if row.description()}}
+ <a class="btn btn-warning btn-mini popover-doc" id="remoterepo-description-help"
+ data-content="${row.description()}" data-title="${$.i18n.prop('description')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ {{/if}}
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ scheduleDownloadRemoteIndex(row) }">
+ <span class="btn btn-success">
+ <i class="icon-refresh icon-white"/>
+ </span>
+ </a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+
+<script id="remote-repository-edit-tmpl" type='text/html'>
+
+
+ <form id="remote-repository-edit-form" class="well form-horizontal">
+ <fieldset id="remote-repository-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="id">${$.i18n.prop('id')}</label>
+
+ <div class="controls">
+ {{if update}}
+ <span class="uneditable-input">${$data.remoteRepository.id}</span>
+ {{else}}
+ <input type="text" class="input-xlarge required" id="id" name="id" size="50"
+ data-bind="value: remoteRepository.id,css:{'uneditable-input': update},readonly:update"/>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="name">${$.i18n.prop('name')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xlarge required" id="name" name="name" size="50"
+ data-bind="value: remoteRepository.name"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="url">${$.i18n.prop('url')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xxlarge required" id="url" name="location" size="50"
+ data-bind="value: remoteRepository.url"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="userName">${$.i18n.prop('username')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xlarge" id="userName" name="userName" size="50"
+ data-bind="value: remoteRepository.userName"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-userName-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.userName.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.userName.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="password">${$.i18n.prop('password')}</label>
+ <div class="controls">
+ <input type="password" class="input-xlarge" id="password" name="password" size="50"
+ data-bind="value: remoteRepository.password"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-password-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.password.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.password.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="timeout">${$.i18n.prop('timeout')}</label>
+
+ <div class="controls">
+ <input type="text" id="timeout" class="digits" name="daysOlder" size="5"
+ data-bind="value: remoteRepository.timeout"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-timeout-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.timeout.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.timeout.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="layout">${$.i18n.prop('type')}</label>
+
+ <div class="controls">
+ <select id="layout"
+ data-bind="options: availableLayouts,optionsText: 'label',optionsValue:'type',value: remoteRepository.layout"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="downloadRemoteIndex">${$.i18n.prop('downloadRemoteIndex')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="downloadRemoteIndex" name="downloadRemoteIndex" size="5"
+ data-bind="checked: remoteRepository.downloadRemoteIndex"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-downloadRemoteIndex-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.downloadRemoteIndex.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.downloadRemoteIndex.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="remoteIndexUrl">${$.i18n.prop('remoteIndexUrl')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xxlarge" id="remoteIndexUrl" name="remoteIndexUrl" size="5"
+ data-bind="value: remoteRepository.remoteIndexUrl"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-remoteIndexUrl-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.remoteIndexUrl.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.remoteIndexUrl.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="cronExpression">${$.i18n.prop('cronExpression')}</label>
+
+ <div class="controls">
+ <input type="text" id="cronExpression" name="cronExpression" size="40"
+ data-bind="value: remoteRepository.cronExpression"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="cronExpression-info-button"
+ data-original-title="${$.i18n.prop('cronExpression.help.title')}"
+ data-content="${$.i18n.prop('cronExpression.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="indexDirectory">${$.i18n.prop('index.directory')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-xlarge" id="indexDirectory" name="indexDirectory" size="50"
+ data-bind="value: remoteRepository.indexDirectory"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-indexDirectory-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.indexDirectory.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.indexDirectory.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="remoteDownloadTimeout">${$.i18n.prop('remoteDownloadTimeout')}</label>
+
+ <div class="controls">
+ <input type="text" id="remoteDownloadTimeout" class="digits" name="remoteDownloadTimeout" size="5"
+ data-bind="value: remoteRepository.remoteDownloadTimeout"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-remoteDownloadTimeout-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.remoteDownloadTimeout.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.remoteDownloadTimeout.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label"
+ for="remoteDownloadNetworkProxyId">${$.i18n.prop('remoteDownloadNetworkProxyId')}</label>
+
+ <div class="controls">
+ <select id="remoteDownloadNetworkProxyId"
+ data-bind="options: networkProxies, optionsText: 'id',optionsValue:'id', value: remoteRepository.remoteDownloadNetworkProxyId, optionsCaption: 'Choose...'"></select>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-remoteDownloadNetworkProxyId-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.remoteDownloadNetworkProxyId.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.remoteDownloadNetworkProxyId.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label"
+ for="downloadRemoteIndexOnStartup">${$.i18n.prop('downloadRemoteIndexOnStartup')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="downloadRemoteIndexOnStartup" name="downloadRemoteIndexOnStartup"
+ data-bind="checked: remoteRepository.downloadRemoteIndexOnStartup"/>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-remoteDownloadNetworkProxyId-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.remoteDownloadNetworkProxyId.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.remoteDownloadNetworkProxyId.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="description">${$.i18n.prop('description')}</label>
+
+ <div class="controls">
+ <textarea rows="3" id="description" name="description"
+ data-bind="value: remoteRepository.description"></textarea>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-description-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.description.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.description.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ </div>
+ </div>
+
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <h4>${$.i18n.prop('remoteRepository.extraParametersEntries')}
+ </h4>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-extraParametersEntries-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.extraParametersEntries.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.extraParametersEntries.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ <div id="extra-parameters-error"></div>
+ <table class="table">
+ <thead>
+ <th>${$.i18n.prop('key')}:<input type="text" id="extraParameter-key"/></th>
+ <th>${$.i18n.prop('value')}:<input type="text" id="extraParameter-value"/></th>
+ <th><a href="#" data-bind="click: function(){ addExtraParameter() }">${$.i18n.prop('add')}</a></th>
+ </thead>
+ <tbody>
+ {{each(i, extraParameterEntry) remoteRepository.extraParametersEntries}}
+ <tr>
+ <td>${extraParameterEntry.key}</td>
+ <td>${extraParameterEntry.value}</td>
+ <td><a href="#" data-bind="click: function(){ deleteExtraParameter(extraParameterEntry.key)}">${$.i18n.prop('delete')}</a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <h4>${$.i18n.prop('remoteRepository.extraHeadersEntries')}
+ </h4>
+ <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-extraHeadersEntries-info-button"
+ data-original-title="${$.i18n.prop('remoteRepository.extraHeadersEntries.help.title')}"
+ data-content="${$.i18n.prop('remoteRepository.extraHeadersEntries.help.content')}">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+ <div id="extra-headers-error"></div>
+ <table class="table">
+ <thead>
+ <th>${$.i18n.prop('key')}:<input type="text" id="extraHeader-key"/></th>
+ <th>${$.i18n.prop('value')}:<input type="text" id="extraHeader-value"/></th>
+ <th><a href="#" data-bind="click: function(){ addExtraHeader() }">${$.i18n.prop('add')}</a></th>
+ </thead>
+ <tbody>
+ {{each(i, extraHeaderEntry) remoteRepository.extraHeadersEntries}}
+ <tr>
+ <td>${extraHeaderEntry.key}</td>
+ <td>${extraHeaderEntry.value}</td>
+ <td><a href="#" data-bind="click: function(){ deleteExtraHeader(extraHeaderEntry.key)}">${$.i18n.prop('delete')}</a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ </fieldset>
+ <button data-bind="click: save" data-loading-text="${$.i18n.prop('common.loading')}"
+ id="remote-repository-save-button" class="btn">${$.i18n.prop('save')}
+ </button>
+ <button data-bind="click: displayGrid" class="btn">${$.i18n.prop('cancel')}</button>
+ </form>
+</script>
+
+<script id="remote-repository-scan-modal-tmpl" type='text/html'>
+ <div>
+ ${$.i18n.prop('remoterepository.download.remote.now')}: <input type="checkbox" id="remoterepository-scan-now">
+ </div>
+ <div>
+ ${$.i18n.prop('remoterepository.download.remote.full')}: <input type="checkbox" id="remoterepository-scan-full">
+ </div>
+</script>
+
+<script id="managed-repositories-bulk-save-tmpl" type='text/html'>
+ {{if bulkSave()}}
+ <a data-bind="click: updateModifiedManagedRepositories" class="btn btn-danger" href="#">${$.i18n.prop('save.all')}</a>
+ {{/if}}
+</script>
+
+<script id="remote-repositories-bulk-save-tmpl" type='text/html'>
+ {{if bulkSave()}}
+ <a data-bind="click: updateModifiedRemoteRepositories" class="btn btn-danger" href="#">${$.i18n.prop('save.all')}</a>
+ {{/if}}
+</script>
+
+<script id="networkProxiesMain" type="text/html">
+ <div class="page-header">
+ <h2><img src="images/internet-web-browser-32-32.png"/>${$.i18n.prop('network-proxies.list')}</h2>
+ </div>
+
+ <ul id="network-proxies-view-tabs" class="nav nav-tabs">
+ <li id="network-proxies-view-tabs-li-grid">
+ <a data-toggle="tab" href="#network-proxies-view" id="network-proxies-view-tabs-a-network-proxies-grid">${$.i18n.prop('network-proxies.grid.tab.title')}</a>
+ </li>
+ <li id="network-proxies-view-tabs-li-edit">
+ <a data-toggle="tab" href="#network-proxies-edit">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="network-proxies-view-tabs-content" class="tab-content">
+ <div id="network-proxies-view" class="tab-pane">
+ <div id="network-proxies-bulk-save-btn" data-bind='template:{name:"network-proxies-bulk-save-tmpl"}'></div>
+ <table class="table table-striped table-bordered" id="networkProxiesTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko-network-proxies-grid',pageLinksId:'network-proxiesPagination'">
+ </table>
+ <div id="network-proxiesPagination"></div>
+ </div>
+ <div id="network-proxies-edit" class="tab-pane" data-bind='template: {name:"network-proxy-edit-tmpl"}'></div>
+ </div>
+
+</script>
+
+<script id='ko-network-proxies-grid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th>${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>${$.i18n.prop('password')}</th>
+ <th>${$.i18n.prop('network.proxy.useNtlm')}</th>
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('modified')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ {{each(j, columnDefinition) columns}}
+ {{var val = (typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) :
+ row[columnDefinition.rowText])}}
+ <td>
+ ${val}
+ </td>
+ {{/each}}
+ {{if row.password()}}
+ <td>*****</td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ <td>${row.useNtlm()}</td>
+ <td>
+ <a href="#" data-bind="click: function(){ editNetworkProxy(row) }">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ removeNetworkProxy(row) }">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ {{if row.modified()}}
+ <td>
+ <a href="#" data-bind="click: function(){ updateNetworkProxy(row) }" class="btn btn-warning">${$.i18n.prop('save')}</a>
+ </td>
+ {{else}}
+ <td></td>
+ {{/if}}
+
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+<script id="network-proxy-edit-tmpl" type='text/html'>
+ <form id="network-proxy-edit-form" class="well form-horizontal">
+ <fieldset id="network-proxy-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="id">${$.i18n.prop('id')}</label>
+
+ <div class="controls">
+ {{if update}}
+ <span class="uneditable-input">${$data.networkProxy.id}</span>
+ {{else}}
+ <input type="text" class="xlarge" id="id" name="id" size="10"
+ data-bind="value: networkProxy.id,css:{'uneditable-input': update},readonly:update"/>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="protocol">${$.i18n.prop('protocol')}</label>
+
+ <div class="controls">
+ <input type="text" class="xlarge required" id="protocol" name="protocol" size="8"
+ data-bind="value: networkProxy.protocol"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="host">${$.i18n.prop('host')}</label>
+
+ <div class="controls">
+ <input type="text" class="xlarge required" id="host" name="host" size="15"
+ data-bind="value: networkProxy.host"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="port">${$.i18n.prop('port')}</label>
+
+ <div class="controls">
+ <input type="text" class="xlarge required digits" id="port" name="port" size="6"
+ data-bind="value: networkProxy.port"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="username">${$.i18n.prop('username')}</label>
+
+ <div class="controls">
+ <input type="text" class="xlarge" id="username" name="username" size="50"
+ data-bind="value: networkProxy.username"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="password">${$.i18n.prop('password')}</label>
+
+ <div class="controls">
+ <input type="password" class="xlarge" id="password" name="password" size="50"
+ data-bind="value: networkProxy.password"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="useNtlm">${$.i18n.prop('network.proxy.useNtlm')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="useNtlm" name="useNtlm" data-bind="checked: networkProxy.useNtlm"/>
+ </div>
+ </div>
+
+ </fieldset>
+ <button id="network-proxy-btn-save" data-bind="click: save" class="btn">${$.i18n.prop('save')}</button>
+ {{if networkProxy.modified()}}
+ ${("#network-proxy-btn-save").button('reset')}
+ {{/if}}
+ <button data-bind="click: displayGrid" class="btn">${$.i18n.prop('cancel')}</button>
+ </form>
+</script>
+
+<script id="network-proxies-bulk-save-tmpl" type='text/html'>
+ {{if bulkSave()}}
+ <a data-bind="click: updateModifiedNetworkProxies" class="btn btn-danger" href="#">${$.i18n.prop('save.all')}</a>
+ {{/if}}
+</script>
+<script id="network-proxy-delete-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+<script id="proxyConnectorsMain" type="text/html">
+ <div class="page-header">
+ <h2><img src="images/preferences-system-network-proxy-32-32.png"/>${$.i18n.prop('proxy-connectors.list')}</h2>
+ </div>
+
+ <ul id="proxy-connectors-view-tabs" class="nav nav-tabs">
+ <li id="proxy-connectors-view-tabs-li-grid" class="active">
+ <a data-toggle="tab" href="#proxy-connectors-view" id="proxy-connectors-view-tabs-a-network-proxies-grid">${$.i18n.prop('proxy-connectors.grid.tab.title')}</a>
+ </li>
+ <li id="proxy-connectors-view-tabs-li-edit">
+ <a data-toggle="tab" href="#proxy-connectors-edit"
+ id="proxy-connectors-view-tabs-a-edit">${$.i18n.prop('add')}</a>
+ </li>
+ <li id="proxy-connectors-view-tabs-li-edit-order">
+ <a data-toggle="tab" href="#proxy-connectors-edit-order" id="proxy-connectors-view-tabs-a-edit-order">${$.i18n.prop('proxy-connectors.grid.tab.edit.order')}</a>
+ </li>
+ </ul>
+ <div id="proxy-connectors-view-tabs-content" class="tab-content">
+ <div id="proxy-connectors-view" class="tab-pane active">
+ <div id="proxy-connectors-bulk-save-btn" data-bind='template:{name:"proxy-connectors-bulk-save-tmpl"}'></div>
+ <table class="table table-striped table-bordered" id="proxyConnectorsTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko-proxy-connectors-grid',pageLinksId:'proxy-connectorsPagination'">
+ </table>
+ <div id="proxy-connectorsPagination"></div>
+ </div>
+ <div id="proxy-connectors-edit" class="tab-pane"></div>
+ <div id="proxy-connector-edit-order" class="tab-pane span8">
+ <div id="proxy-connector-edit-order-managed-repository-div"
+ data-bind='template:{name:"proxy-connector-edit-order-managed-repository-tmpl"}'></div>
+ <div id="proxy-connector-edit-order-div"
+ data-bind="sortable: { template: 'proxy-connector-edit-order-tmpl', data: proxyConnectors,afterMove: proxyConnectorMoved}">
+ </div>
+ </div>
+ </div>
+
+</script>
+
+<script id='ko-proxy-connectors-grid' type='text/html'>
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('proxy-connectors.grid.managedrepo.grid.header')}</th>
+ <th>${$.i18n.prop('proxy-connectors.grid.remoterepo.grid.header')}</th>
+ <th>${$.i18n.prop('proxy-connectors.grid.remoterepo.settings.popover.title')}</th>
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('save')}</th>
+ <th>${$.i18n.prop('proxy-connectors.grid.header.order')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ <td>${row.sourceRepoId()}</td>
+ <td>${row.targetRepoId()}</td>
+ <td>
+ <a class="btn btn-info btn-mini"
+ id="proxy-connectors-grid-remoterepo-settings-edit-${row.sourceRepoId()}-${row.targetRepoId()}"
+ data-original-title="${$.i18n.prop('proxy-connectors.grid.remoterepo.settings.popover.title')}"
+ data-content="${buildSettings(row)}" data-bind="click: showSettings" data-html="true">
+ <i class="icon-question-sign icon-white"></i>
+ </a>
+
+ </td>
+ <td>
+ <a data-bind="click: function(){ editProxyConnector(row)}" href="#">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ deleteProxyConnector(row)}">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ {{if row.modified()}}
+ <a href="#" class="btn btn-warning" data-bind="click: function(){ updateProxyConnector(row)}">
+ ${$.i18n.prop('save')}
+ </a>
+ {{/if}}
+ </td>
+ <td>
+ {{if orderChangeAware(row)}}
+ <a href="#" data-bind="click: function(){ displayOrderEdit(row)}">
+ <span class="btn btn-info">
+ <i class="icon-resize-vertical icon-white"/>
+ ${$.i18n.prop('proxy-connectors.order.edit')}
+ </span>
+
+ </a>
+ <span class="badge badge-info">${row.order()}</span>
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ <div id="proxy-connectors-grid-remoterepo-settings-content-${val}-${targetRepoId}" style="display:none"></div>
+</script>
+
+<script id='proxy-connectors-remote-settings-popover-tmpl' type='text/html'>
+ <span>
+ {{if proxyId}}
+ ${$.i18n.prop('proxy-connectors.remoterepo.settings.networkproxy')}: ${proxyConnector.proxyId}
+ {{else}}
+ ${$.i18n.prop('proxy-connectors.remoterepo.settings.networkproxy')}: ${$.i18n.prop('none')}
+ {{/if}}
+ <table class="table table-bordered">
+ <thead>
+ <th colspan="2">${$.i18n.prop('proxy-connector.policies')}</th>
+ </thead>
+ <tbody>
+ {{each(i, entry) proxyConnector.policiesEntries}}
+ {{var name = proxyConnectorsViewModel.findPolicyInformationName(entry.key)}}
+ <tr>
+ <td>${name}</td>
+ <td>${entry.value}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ </span>
+</script>
+
+<script id="proxy-connector-edit-form-tmpl" type='text/html'>
+
+ <form id="proxy-connector-edit-form" class="well form-horizontal">
+ <fieldset id="remote-repository-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="proxyId">${$.i18n.prop('proxy-connector.network-proxy.id')}</label>
+
+ <div class="controls">
+ <select id="proxyId"
+ data-bind="options: proxyConnectorsViewModel.networkProxies, optionsText: 'id',optionsValue:'id',
+ value: proxyConnector.proxyId, optionsCaption: 'direct connection'"></select>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="proxyId">${$.i18n.prop('proxy-connector.managed.repository.id')}</label>
+
+ <div class="controls">
+ <select id="sourceRepoId"
+ data-bind="options: proxyConnectorsViewModel.managedRepositories, optionsText: 'id',optionsValue:'id',
+ value: proxyConnector.sourceRepoId,attr: {disabled: isUpdate() }"></select>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="proxyId">${$.i18n.prop('proxy-connector.remote.repository.id')}</label>
+
+ <div class="controls">
+ <select id="targetRepoId"
+ data-bind="options: proxyConnectorsViewModel.remoteRepositories, optionsText: 'id',optionsValue:'id',
+ value: proxyConnector.targetRepoId,attr: {disabled: isUpdate() }"></select>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <table class="table">
+ <thead>
+ <th colspan="2">${$.i18n.prop('proxy-connector.policies')}</th>
+ </thead>
+ <tbody data-bind="foreach: proxyConnectorsViewModel.policyInformations()">
+ <tr>
+ <td data-bind="text: name"></td>
+ <td>
+ <select data-bind="options: getPolicyOptions(id()),value:getSelectedPolicyOption(id()),
+ attr: { id: 'policy-'+id() },event: { change: function(){ changePolicyOption(id())},}">
+ </select>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <h4>${$.i18n.prop('proxy-connector.properties')}</h4>
+ <table class="table">
+ <thead>
+ <th><input type="text" id="property-key"/></th>
+ <th><input type="text" id="property-value"/></th>
+ <th><a href="#" data-bind="click: function(){ addProperty() }">${$.i18n.prop('add')}</a></th>
+ </thead>
+ <tbody data-bind="foreach: proxyConnector.propertiesEntries">
+ <tr>
+ <td data-bind="text: key"></td>
+ <td data-bind="text: value"></td>
+ <td><a href="#" data-bind="click: function(){ $parent.deleteProperty(key)}">${$.i18n.prop('delete')}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <h4>${$.i18n.prop('proxy-connector.blacklist')}</h4>
+ <table class="table">
+ <thead>
+ <th><input type="text" id="blacklist-value"/></th>
+ <th><a href="#" data-bind="click: function(){ addBlacklistPattern() }">${$.i18n.prop('add')}</a></th>
+ </thead>
+ <tbody data-bind="foreach: proxyConnector.blackListPatterns">
+ <tr>
+ <td data-bind="text: $data"></td>
+ <td><a href="#" data-bind="click: function(){removeBlacklistPattern($data)}">${$.i18n.prop('delete')}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="control-group span6">
+ <h4>${$.i18n.prop('proxy-connector.whitelist')}</h4>
+ <table class="table">
+ <thead>
+ <th><input type="text" id="whitelist-value"/></th>
+ <th><a href="#" data-bind="click: function(){ addWhitelistPattern() }">${$.i18n.prop('add')}</a></th>
+ </thead>
+ <tbody data-bind="foreach: proxyConnector.whiteListPatterns">
+ <tr>
+ <td data-bind="text: $data"></td>
+ <td><a href="#" data-bind="click: function(){removeWhitelistPattern($data)}">${$.i18n.prop('delete')}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </fieldset>
+
+ <button id="proxy-connector-btn-save" data-bind="click: save" data-loading-text="${$.i18n.prop('common.loading')}"
+ class="btn">${$.i18n.prop('save')}
+ </button>
+ {{if modified()}}
+ ${("#network-proxy-btn-save").button('reset')}
+ {{/if}}
+ <button data-bind="click: displayGrid" class="btn">${$.i18n.prop('cancel')}</button>
+
+ </form>
+
+</script>
+<script id="proxy-connectors-bulk-save-tmpl" type='text/html'>
+ {{if bulkSave()}}
+ <a data-bind="click: updateModifiedProxyConnectors" class="btn btn-danger" href="#">${$.i18n.prop('save.all')}</a>
+ {{/if}}
+</script>
+
+<script id="proxy-connector-edit-order-tmpl" type='text/html'>
+ <div class="well draggable-item network-proxy-remote-item">
+ {{var remoteRepository=$parent.findRemoteRepository(targetRepoId)}}
+ <div class="row-fluid">
+ <div class="span1">
+ <img src="images/system-software-update-32-32.png"/>
+ <br/>
+ <img src="images/utilities-system-monitor-22-22.png"
+ id="proxy-connectors-order-remoterepo-settings-edit-${sourceRepoId()}-${targetRepoId()}"
+ data-original-title="${$.i18n.prop('proxy-connectors.grid.remoterepo.settings.popover.title')}"
+ data-bind="event: { mouseover: function(){ displaySettings(sourceRepoId(),targetRepoId())},}">
+
+ <div id="proxy-connectors-order-remoterepo-settings-content-${sourceRepoId()}-${targetRepoId()}"
+ style="display:none"></div>
+ </div>
+ <div class="span6 pull-left">
+ <blockquote>
+ ${targetRepoId}
+ <br/>
+ ${remoteRepository.name()}&nbsp;(<a href="${remoteRepository.url()}"
+ target="_blank">${remoteRepository.url()}</a>)
+ </blockquote>
+ </div>
+ <div class="span2">
+ <span class="badge badge-info">${order}</span>
+ </div>
+ </div>
+ </div>
+</script>
+
+<script id="proxy-connector-edit-order-managed-repository-tmpl" type="text/html">
+ <div class="well row-fluid">
+ <div class="span1">
+ <img src="images/applications-internet-32-32.png"/>
+ </div>
+ <div class="span6">
+ <blockquote>
+ ${managedRepository.id}
+ <br/>
+ ${managedRepository.name}
+ </blockquote>
+ </div>
+ <div class="span2">
+ {{if proxyConnectorsViewModel.bulkSave()}}
+ <p>
+ <a data-bind="click: function(){updateModifiedProxyConnectors()}"
+ href="#" class="btn btn-warning">${$.i18n.prop('save.all')}</a></p>
+ {{/if}}
+ </div>
+ </div>
+</script>
+
+<script id="proxy-connector-delete-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+<script id="repositoryGroupsMain" type="text/html">
+ <div class="page-header">
+ <h2><img src="images/applications-internet-2-32-32.png"/>${$.i18n.prop('repository.groups.list')}</h2>
+ </div>
+ <ul id="repository-groups-view-tabs" class="nav nav-tabs">
+ <li id="repository-groups-view-tabs-li-grid" class="active">
+ <a data-toggle="tab" href="#repository-groups-view" id="repository-groups-view-tabs-a-network-proxies-grid">
+ ${$.i18n.prop('repository-groups.grid.tab.title')}
+ </a>
+ </li>
+ <li id="repository-groups-view-tabs-li-edit">
+ <a data-toggle="tab" href="#repository-groups-edit"
+ id="repository-groups-view-tabs-a-edit">${$.i18n.prop('add')}</a>
+ </li>
+
+ </ul>
+ <div id="repository-groups-view-tabs-content" class="tab-content">
+ <div id="repository-groups-view" class="tab-pane active">
+ <div id="repository-groups-table" data-bind='template:{name:"repository-groups-table-tmpl"}'>
+ </div>
+ </div>
+ <div id="repository-groups-edit" class="tab-pane">
+ <div class="row-fluid">
+ <div class="span6 dotted">
+ <div id="repository-groups-edit-div" data-bind='template:{name:"repository-group-edit-tmpl"}'></div>
+ <div id="repository-groups-edit-order-div" style="min-height: 80px"
+ data-bind="sortable: { template: 'repository-group-edit-order-tmpl-choosed',data:repositoryGroup.managedRepositories,afterMove:repositoryMoved}">
+ </div>
+ </div>
+
+ <div class="span6 dotted">
+ <h5>${$.i18n.prop('repository.groups.available.repositories')}</h5>
+ <br/>
+
+ <div id="repository-groups-edit-available-repositories" style="min-height: 80px"
+ data-bind="sortable: { template: 'repository-group-edit-order-tmpl-available',data:availableRepositories,afterMove:repositoryMoved}">
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+</script>
+
+<script id="repository-group-edit-order-tmpl-choosed" type="text/html">
+ <div class="well draggable-item">
+ <span class="pull-right">
+ <i class="icon-minus-sign cursor-hand" id="minus-${$data.id()}"/>
+ </span>
+ <blockquote>
+ ${$data.id()}
+ <br/>
+ ${$data.name()}
+ <br/>
+ <a href="${$data.url}" target="_blank">
+ ${$data.url}
+ </a>
+ <br/>
+ </blockquote>
+
+ </div>
+</script>
+
+<script id="repository-group-edit-order-tmpl-available" type="text/html">
+ <div class="well draggable-item">
+ <span class="pull-right">
+ <i class="icon-plus-sign cursor-hand" id="plus-${$data.id()}"/>
+ </span>
+ <blockquote>
+ ${$data.id()}
+ <br/>
+ ${$data.name()}
+ <br/>
+ <a href="${$data.url}" target="_blank">
+ ${$data.url}
+ </a>
+ <br/>
+ </blockquote>
+
+ </div>
+</script>
+
+<script id="repository-groups-table-tmpl" type="text/html">
+ <table class="table table-striped table-bordered">
+ <thead>
+ <th>${$.i18n.prop('repository.groups.groups.grid.header')}</th>
+ <th>${$.i18n.prop('repository.groups.repositories.grid.header')}</th>
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('save')}</th>
+ </thead>
+ <tbody>
+ {{each(i, repositoryGroup) repositoryGroups}}
+ <tr data-bind="css:{ 'modified': repositoryGroup.modified()}">
+ <td>${repositoryGroup.id}</td>
+ <td>
+ <ul>
+ {{each(j,id) repositoryGroup.repositories()}}
+ <li>${id}</li>
+ {{/each}}
+ </ul>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){editRepositoryGroup(repositoryGroup)}">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){deleteRepositoryGroup(repositoryGroup)}">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ {{if repositoryGroup.modified()}}
+ <a href="#" class="btn btn-warning" data-bind="click: function(){saveRepositoryGroup(repositoryGroup)}">
+ ${$.i18n.prop('save')}
+ </a>
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</script>
+
+<script id="repository-group-edit-tmpl" type="text/html">
+ <div class="row-fluid">
+ {{if update}}
+ <div class="dotted span8">
+ <blockquote>
+ ${repositoryGroup.id}
+ <br/>
+ <a href="${window.archivaRuntimeInfo.baseUrl}/repository/${repositoryGroup.id()}" target="_blank">
+ ${applicationUrl}/repository/${repositoryGroup.id()}
+ </a>
+ </blockquote>
+ </div>
+ {{else}}
+ <div class="dotted span8">
+ <form id="repository-group-edit-form" class="well">
+ <fieldset id="repository-group-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="id">${$.i18n.prop('id')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-medium required" id="id" name="id" size="15"
+ data-bind="value: repositoryGroup.id,css:{'uneditable-input': update},readonly:update"/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ {{/if}}
+ {{if repositoryGroup.modified()}}
+ <div class="span3">
+ <a href="#" class="btn btn-warning" data-loading-text="${$.i18n.prop('common.loading')}"
+ id="repository-group-save" data-bind="click: function(){saveRepositoryGroup(repositoryGroup)}">${$.i18n.prop('save')}</a>
+ </div>
+ <br/>
+ {{/if}}
+ </div>
+</script>
+
+
+<script id="repository-group-delete-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+
+<script id="merge-repo-dialog-content" type="text/html">
+ <div class="btn-group btn-group-vertical">
+ {{each(i, repository) repositories}}
+ <button class="btn" type="button"
+ onclick="mergeRepositories(encodeURIComponent('${sourceRepoId}'),encodeURIComponent('${repository.id()}'))">
+ ${repository.name()}
+ </button>
+ {{/each}}
+ </div>
+</script>
+
+<script id="merge-repo-skip-conflicts" type="text/html">
+ <div>
+ <ul>
+ {{each(i, artifact) artifacts}}
+ <li>${artifact.groupId}:${artifact.artifactId}:${artifact.version}</li>
+ {{/each}}
+ </ul>
+ </div>
+ <div>
+ <button class="btn btn-success"
+ onclick="doMerge(encodeURIComponent('${sourceRepository}'),encodeURIComponent('${targetRepository}'),false);"
+ type="button">${$.i18n.prop('managedrepository.merge.domerge')}
+ </button>
+ {{if artifacts.length > 0}}
+ <button class="btn btn-warning"
+ onclick="doMerge(encodeURIComponent('${sourceRepository}'),encodeURIComponent('${targetRepository}'),true);"
+ type="button">${$.i18n.prop('managedrepository.merge.domerge.skipconflicts')}
+ </button>
+ {{/if}}
+ </div>
+</script>
+
+
+<script id="proxyConnectorsRulesMain" type="text/html">
+ <div class="page-header">
+ <h2>${$.i18n.prop('proxy-connector-rules.list')}</h2>
+ </div>
+
+ <ul id="proxy-connectors-rules-view-tabs" class="nav nav-tabs">
+ <li id="proxy-connectors-rules-view-tabs-li-grid" class="active">
+ <a data-toggle="tab" href="#proxy-connector-rules-view" id="proxy-connectors-rules-view-tabs-a-grid">${$.i18n.prop('proxy-connectors-rules.grid.tab.title')}</a>
+ </li>
+ <li id="proxy-connectors-rules-view-tabs-li-edit">
+ <a data-toggle="tab" href="#proxy-connector-rules-edit" id="proxy-connectors-rules-view-tabs-a-edit">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="proxy-connectors-rules-view-tabs-content" class="tab-content">
+ <div id="proxy-connector-rules-view" class="tab-pane active">
+ <div id="proxy-connectors-rules-view-tabs-bulk-save-btn"
+ data-bind='template:{name:"proxy-connectors-rules-view-tabs-bulk-save-tmpl"}'></div>
+ <table class="table table-striped table-bordered" id="proxy-connectors-rules-view-tabsTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko-proxy-connectors-rules-grid',pageLinksId:'proxy-connectors-rules-pagination'">
+ </table>
+ <div id="proxy-connectors-rules-view-tabs-pagination"></div>
+ </div>
+ <div id="proxy-connector-rules-edit" class="tab-pane">
+ <div class="row-fluid">
+ <div class="span6 dotted">
+ <div id="proxy-connectors-rules-edit-div"
+ data-bind='template:{name:"proxy-connectors-rules-edit-tmpl"}'></div>
+ <div id="proxy-connectors-rules-edit-order-div" style="min-height: 80px"
+ data-bind="sortable: { template: 'proxy-connectors-rules-edit-proxy-connectors-tmpl-choosen',data:proxyConnectorRule.proxyConnectors,afterMove:proxyConnectorMoved}">
+ </div>
+ </div>
+
+ <div class="span6 dotted">
+ <h5>${$.i18n.prop('proxy-connector-rules.available.proxyConnectors')}</h5>
+ <br/>
+
+ <div id="proxy-connectors-rules-available-proxy-connectors" style="min-height: 80px"
+ data-bind="sortable: { template: 'proxy-connectors-rules-edit-proxy-connectors-tmpl-availables',data:availableProxyConnectors,afterMove:proxyConnectorMoved}">
+
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+ </div>
+
+</script>
+
+<script id='ko-proxy-connectors-rules-grid' type='text/html'>
+ <thead>
+ <tr>
+ <th title="${$.i18n.prop('proxy-connector-rules.grid.pattern.title')}">
+ ${$.i18n.prop('proxy-connector-rules.grid.pattern.header')}
+ </th>
+ <th title="${$.i18n.prop('proxy-connector-rules.grid.type.title')}">
+ ${$.i18n.prop('proxy-connector-rules.grid.type.header')}
+ </th>
+ <th>${$.i18n.prop('proxy-connector-rules.grid.proxy-connectors.header')}</th>
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('save')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ <td>${row.pattern()}</td>
+ <td><img src="${row.ruleType.image}" title="${row.ruleType.label}"></img></td>
+ <td>
+ <ul>
+ {{each(j,proxyConnector) row.proxyConnectors()}}
+ <li>${proxyConnector.sourceRepoId()} <-> ${proxyConnector.targetRepoId()}</li>
+ {{/each}}
+ </ul>
+ </td>
+ <td>
+ <a href="#" data-bind="click: function(){ editProxyConnectorRule(row) }">
+ <span class="btn btn-primary" data-loading-text="${$.i18n.prop('common.loading')}">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ <a data-bind="click: function(){ removeProxyConnectorRule(row) }"
+ data-loading-text="${$.i18n.prop('common.loading')}">
+ <span class="btn btn-danger" data-loading-text="${$.i18n.prop('common.loading')}">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ {{if row.modified()}}
+ <a href="#" id="proxy-connector-rule-update-btn" class="btn btn-warning"
+ data-loading-text="${$.i18n.prop('common.loading')}"
+ data-bind="click: function(){ updateProxyConnectorRule(row) }">${$.i18n.prop('save')}</a>
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+</script>
+
+<script id="proxy-connectors-rules-view-tabs-bulk-save-tmpl" type="text/html">
+
+</script>
+
+<script id="proxy-connectors-rules-edit-tmpl" type="text/html">
+ <div class="row-fluid">
+ {{if update}}
+ <div class="dotted span8">
+ <blockquote>
+ ${proxyConnectorRule.pattern()}
+ <br/>
+ ${proxyConnectorRule.ruleType.label}
+ </blockquote>
+ </div>
+ {{else}}
+ <div class="dotted span8">
+ <form id="proxy-connector-rule-edit-form" class="well">
+ <fieldset id="proxy-connector-rule-edit-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="id">${$.i18n.prop('proxy-connector-rule.pattern')}</label>
+
+ <div class="controls">
+ <input type="text" class="input-large required" id="pattern" name="pattern" size="15"
+ data-bind="value:proxyConnectorRule.pattern,css:{'uneditable-input': update},readonly:update"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="layout">${$.i18n.prop('type')}</label>
+
+ <div class="controls">
+ <select id="proxy-connector-rule-pattern-type"
+ data-bind="options: proxyConnectorRulesViewModel.ruleTypes,optionsText: 'label',optionsValue:'type',value: proxyConnectorRule.proxyConnectorRuleType"/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ {{/if}}
+
+ <div class="span3" data-bind="visible: proxyConnectorRule.modified()">
+ {{if update && proxyConnectorRule.modified()}}
+ <a href="#" class="btn btn-warning" data-loading-text="${$.i18n.prop('common.loading')}"
+ id="proxy-connector-rule-update-btn"
+ data-bind="click: function(){updateProxyConnectorRule(proxyConnectorRule)}">${$.i18n.prop('update')}</a>
+ {{else}}
+ <a href="#" class="btn btn-warning" data-loading-text="${$.i18n.prop('common.loading')}"
+ id="proxy-connector-rule-add-btn" data-bind="click: function(){addProxyConnectorRule(proxyConnectorRule)}">${$.i18n.prop('add')}</a>
+ {{/if}}
+ </div>
+
+ <br/>
+
+ </div>
+</script>
+
+<script id="proxy-connectors-rules-edit-proxy-connectors-tmpl-choosen" type="text/html">
+ <div class="well draggable-item">
+ <i class="icon-minus-sign cursor-hand pull-right" data-source-repoId="${$data.sourceRepoId()}"
+ data-target-repoId="${$data.targetRepoId()}"/>
+ <blockquote>
+ ${$data.sourceRepoId()} <-> ${$data.targetRepoId()}
+ </blockquote>
+
+ </div>
+</script>
+
+<script id="proxy-connectors-rules-edit-proxy-connectors-tmpl-availables" type="text/html">
+ <div class="well draggable-item">
+ <i class="icon-plus-sign cursor-hand pull-right" data-source-repoId="${$data.sourceRepoId()}"
+ data-target-repoId="${$data.targetRepoId()}"/>
+ <blockquote>
+ ${$data.sourceRepoId()} <-> ${$data.targetRepoId()}
+ </blockquote>
+
+ </div>
+</script> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html
new file mode 100644
index 000000000..01a43dcbd
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html
@@ -0,0 +1,969 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+
+<script id="browse-tmpl" type="text/html">
+ <div>
+ <div class="page-header">
+ <div><b>${$.i18n.prop('browse.repository')}</b></div>
+ <div id="selected_repository"></div>
+ </div>
+ </div>
+ <div id="main_browse_result">
+ <div id="main_browse_result_content" class="well">
+ <div id="browse_breadcrumb" data-bind='template:{name:"browse-breadcrumb-tmpl"}'></div>
+ <div id="browse_result" class="well" data-bind='template:{name:"browse-groups-tmpl"}'></div>
+ <div id="browse_artifact" class="well" data-bind='template:{name:"browse-artifact-tmpl"}'></div>
+ <div id="browse_artifact_detail" class="well" data-bind='template:{name:"browse-artifact-detail-tmpl"}'></div>
+ </div>
+ </div>
+</script>
+
+<script id="browse-groups-div-tmpl" type="text/html">
+ <div id="browse-groups-div" data-bind='template:{name:"browse-groups-tmpl"}'>
+ </div>
+</script>
+
+<script id="browse-groups-tmpl" type="text/html">
+ <div>
+ <ul>
+
+ <!-- if null we are on root level -->
+ {{if $root.parentBrowseViewModel}}
+ <li class="browse-list" data-bind="click:function(){displayParentGroupId()}">
+ <a href="#">..</a>
+ </li>
+ {{/if}}
+ {{each(i,browseResultEntry) browseResultEntries}}
+ {{if browseResultEntry.project}}
+ {{if deleteKarma}}
+ <li class="browse-list-project">
+ <img class="cursor-hand" id="delete-${browseResultEntry.name}" src="images/trash.png"
+ data-bind="click:function(){deleteProject(groupId,displayEntry(browseResultEntry.name))}"/>
+ <a href="#" data-bind="click:function(){displayProjectEntry(browseResultEntry.name)}">${displayEntry(browseResultEntry.name)}</a>
+ <a href="${$root.feedsUrl}/${$root.groupId}/${browseResultEntry.name}"><img src="images/atom.gif"/></a>
+ </li>
+ {{else}}
+ <li class="browse-list-project">
+ <a href="#" data-bind="click:function(){displayProjectEntry(browseResultEntry.name)}">${displayEntry(browseResultEntry.name)}</a>
+ <a href="${$root.feedsUrl}/${$root.groupId}/${browseResultEntry.name}"><img src="images/atom.gif"/></a>
+ </li>
+ {{/if}}
+ {{else}}
+ {{if deleteKarma}}
+ <li class="browse-list">
+ <img class="cursor-hand" id="delete-${browseResultEntry.name}" src="images/trash.png"
+ data-bind="click:function(){deleteGroupId(browseResultEntry.name)}"/>
+ <a data-bind="click:function(){displayGroupId(browseResultEntry.name)}" href="#"
+ title="folder ${displayEntry(browseResultEntry.name)}">${displayEntry(browseResultEntry.name)}</a>
+ </li>
+ {{else}}
+ <li class="browse-list">
+ <a href="#" title="folder ${displayEntry(browseResultEntry.name)}"
+ data-bind="click:function(){displayGroupId(browseResultEntry.name)}">${displayEntry(browseResultEntry.name)}</a>
+ </li>
+ {{/if}}
+ {{/if}}
+
+ {{/each}}
+ </ul>
+ </div>
+</script>
+
+<script id="browse-breadcrumb-tmpl" type="text/html">
+ <ul class="breadcrumb">
+ <li>
+ <img class="cursor-hand" src="images/view-refresh.png" data-bind="click: function(){refreshContent()}"/>
+ </li>
+ <li>
+ <a href="#" data-bind="click: function(){ browseRoot()}"><img src="images/go-home.png"/></a>&nbsp;<span
+ class="divider">/</span>
+ </li>
+ {{var number=breadCrumbEntries().length}}
+ {{each(i,breadCrumbEntry) breadCrumbEntries}}
+ <li>
+ {{if i==(number-1)}}
+ ${breadCrumbEntry.displayValue}
+ {{else}}
+ {{if breadCrumbEntry.artifact}}
+ <a href="#" data-bind="click: function(){goToArtifactDetail(breadCrumbEntry.groupId,breadCrumbEntry.artifactId)}">${breadCrumbEntry.displayValue}</a>
+ {{else}}
+ <a href="#"
+ data-bind="click: function(){displayGroupId(breadCrumbEntry.groupId)}">${breadCrumbEntry.displayValue}</a>
+ {{/if}}
+ {{/if}}
+ {{if i<(number-1)}}
+ <span class="divider">/</span>
+ {{/if}}
+ </li>
+ {{/each}}
+ <li>
+ {{if number>0}}
+ <span class="divider" id="browse-autocomplete-divider">/</span>
+ {{/if}}
+ <input type="text" class="input-large" size="50" id="browse-autocomplete"/>
+ </li>
+ </ul>
+
+</script>
+
+<script id="browse-artifact-tmpl" type="text/html">
+ <div class="row-fluid">
+ <div class="span6">
+ <div class="page-header">
+ <h4>${$.i18n.prop('browse.artifact.display.artifactInfo')}</h4>
+ </div>
+ <div id="artifact-info" class="alert alert-info">
+ <table class="table table-condensed">
+ <tbody>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.groupId')}</th>
+ <td>${groupId}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.artifactId')}</th>
+ <td>${artifactId}</td>
+ </tr>
+ {{if projectVersionMetadata}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.name')}</th>
+ <td>${projectVersionMetadata.name}</td>
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.description')}</th>
+ <td>${projectVersionMetadata.description}</td>
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata && projectVersionMetadata.mavenFacet}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.packaging')}</th>
+ <td>${projectVersionMetadata.mavenFacet.packaging}</td>
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata && projectVersionMetadata.organization}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.organization.name')}</th>
+ {{if projectVersionMetadata.organization.url}}
+ <td>
+ <a href="${projectVersionMetadata.organization.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${projectVersionMetadata.organization.name}
+ </a>
+ </td>
+ {{else}}
+ <td>${projectVersionMetadata.organization.name}</td>
+ {{/if}}
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata && projectVersionMetadata.issueManagement}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.organization.issueManagement')}</th>
+ <td>
+ <a href="${projectVersionMetadata.issueManagement.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${projectVersionMetadata.issueManagement.system}
+ </a>
+ </td>
+ </tr>
+ {{/if}}
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="span4">
+ <div class="page-header">
+ <h4>${$.i18n.prop('browse.artifact.versions')}</h4>
+ </div>
+ <div class="alert alert-success">
+ <table class="table table-condensed">
+ {{each(i,version) versions}}
+ <tr>
+ {{if deleteKarma}}
+ <th><a id="delete-${version}" href="#" data-bind="click: function(){deleteVersion(version)}"><img
+ src="images/trash.png"/></a>&nbsp;<a href="#"
+ data-bind="click: function(){displayArtifactVersionDetail(version)}">${version}</a>
+ </th>
+ {{else}}
+ <th><a href="#" data-bind="click: function(){displayArtifactVersionDetail(version)}">${version}</a></th>
+ {{/if}}
+ </tr>
+ {{/each}}
+ </table>
+ </div>
+ </div>
+ </div>
+</script>
+<script id="search-artifacts-div-tmpl" type="text/html">
+ <div id="search-artifacts-div" data-bind='template:{name:"search-artifacts-form-tmpl"}'></div>
+</script>
+
+<script id="search-artifacts-form-tmpl" type="text/html">
+
+ <div class="page-header">
+ <h3>${$.i18n.prop('search.artifact.header')}</h3>
+ </div>
+ <div id="search-artifacts-tabs">
+ <div class="tabbable tabs-below">
+ <ul class="nav nav-tabs">
+ <li class="active" id="search-form-collapse-li">
+ <a data-toggle="tab" href="#search-form-collapse">${$.i18n.prop('search.artifact.form.header')}</a>
+ </li>
+ <li id="search-results-li">
+ <a data-toggle="tab" href="#search-results">${$.i18n.prop('search.artifact.results.header')}</a>
+ </li>
+ </ul>
+ <div class="tab-content">
+
+ <div id="search-form-collapse" class="tab-pane active">
+ <div class="tabbable tabs-below">
+ <ul class="nav nav-pills">
+ <li class="active">
+ <a href="#search-basic-form-pane"
+ data-toggle="tab">${$.i18n.prop('search.artifact.search.form.basic')}</a>
+ </li>
+ <li>
+ <a href="#search-advanced-form-pane" data-toggle="tab">${$.i18n.prop('search.artifact.search.form.advanced')}</a>
+ </li>
+ <li>
+ <a href="#search-osgi-form-pane"
+ data-toggle="tab">${$.i18n.prop('search.artifact.search.form.osgi')}</a>
+ </li>
+ </ul>
+ <div class="pill-content">
+ <div class="pill-pane active" id="search-basic-form-pane">
+ <form class="well form-inline" id="search-basic-form">
+ <fieldset>
+ <div class="control-group" id="search-basic-repositories">
+ <select data-placeholder="${$.i18n.prop('search.artifact.search.form.query.repositories')}"
+ id="search-basic-repositories-select"
+ multiple style="width:350px;" tabindex="4">
+ <option value="all">${$.i18n.prop('search.artifact.search.form.repositories.all')}</option>
+ {{each(i,repoId) observableRepoIds}}
+ <option value="${repoId}">${repoId}</option>
+ {{/each}}
+ </select>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="search-terms"></label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="search-terms" name="search-terms" size="50"
+ data-bind="value: searchRequest().queryTerms"
+ placeholder="${$.i18n.prop('search.artifact.search.form.query.terms')}"/>
+ </div>
+ </div>
+ <button type="submit" id="btn-basic-search" class="btn btn-primary"
+ data-loading-text="${$.i18n.prop('search.artifact.searching')}"
+ data-bind="click: basicSearch"
+ accesskey="${$.i18n.prop('search.artifact.search.form.btn.search')[0]}">
+ ${$.i18n.prop('search.artifact.search.form.btn.search')}
+ </button>
+ </fieldset>
+ </form>
+ </div>
+ <div class="pill-pane" id="search-advanced-form-pane">
+ <form class="well form-horizontal" id="search-advanced-form">
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="groupId">${$.i18n.prop('search.artifact.search.form.query.groupId')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="groupId" name="groupId" size="50"
+ placeholder="my.group.id"
+ data-bind="value: searchRequest().groupId"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="artifactId">${$.i18n.prop('search.artifact.search.form.query.artifactId')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="artifactId" name="artifactId" size="50"
+ placeholder="my.artifact.id"
+ data-bind="value: searchRequest().artifactId"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="version">${$.i18n.prop('search.artifact.search.form.query.version')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="version" name="version" size="50" placeholder="0.0.0"
+ data-bind="value: searchRequest().version"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="classifier">${$.i18n.prop('search.artifact.search.form.query.classifier')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="classifier" name="classifier" size="50"
+ placeholder="bin"
+ data-bind="value: searchRequest().classifier"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="packaging">${$.i18n.prop('search.artifact.search.form.query.packaging')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="packaging" name="packaging" size="50" placeholder="jar"
+ data-bind="value: searchRequest().packaging"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="className">${$.i18n.prop('search.artifact.search.form.query.className')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="className" name="className" size="50"
+ placeholder="my.ClassName"
+ data-bind="value: searchRequest().className"/>
+ </div>
+ </div>
+
+ </fieldset>
+ <button type="submit" id="btn-advanced-search" class="btn btn-primary"
+ data-bind="click: advancedSearch"
+ accesskey="${$.i18n.prop('search.artifact.search.form.btn.search')[0]}">
+ ${$.i18n.prop('search.artifact.search.form.btn.search')}
+ </button>
+
+ </form>
+ </div>
+ <div class="pill-pane" id="search-osgi-form-pane">
+ <form class="well form-horizontal" id="search-osgi-form">
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="bundleSymbolicName">${$.i18n.prop('search.artifact.search.form.query.bundleSymbolicName')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleSymbolicName" name="bundleSymbolicName" size="50"
+ placeholder="my.SymbolicName"
+ data-bind="value: searchRequest().bundleSymbolicName"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="bundleVersion">${$.i18n.prop('search.artifact.search.form.query.bundleVersion')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleVersion" name="bundleVersion" size="50"
+ placeholder="0.0.0"
+ data-bind="value: searchRequest().bundleVersion"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="bundleExportPackage">${$.i18n.prop('search.artifact.search.form.query.bundleExportPackage')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleExportPackage" name="bundleExportPackage"
+ size="50" placeholder="my.package;version=0.0,..."
+ data-bind="value: searchRequest().bundleExportPackage"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="bundleExportService">${$.i18n.prop('search.artifact.search.form.query.bundleExportService')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleExportService" name="bundleExportService"
+ size="50" placeholder="my.SomeService"
+ data-bind="value: searchRequest().bundleExportService"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="bundleImportPackage">${$.i18n.prop('search.artifact.search.form.query.bundleImportPackage')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleImportPackage" name="bundleImportPackage"
+ size="50" placeholder="my.package;version=0.0,..."
+ data-bind="value: searchRequest().bundleImportPackage"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="bundleRequireBundle">${$.i18n.prop('search.artifact.search.form.query.bundleRequireBundle')}</label>
+
+ <div class="controls">
+ <input type="text" class="defaults" id="bundleRequireBundle" name="bundleRequireBundle"
+ size="50" placeholder="my.package;version=0.0,..."
+ data-bind="value: searchRequest().bundleRequireBundle"/>
+ </div>
+ </div>
+ </fieldset>
+ <button type="submit" id="btn-osgi-search" class="btn btn-primary"
+ data-bind="click: advancedSearch"
+ accesskey="${$.i18n.prop('search.artifact.search.form.btn.search')[0]}">
+ ${$.i18n.prop('search.artifact.search.form.btn.search')}
+ </button>
+
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <div id="search-results" class="tab-pane">
+ <div class="row-fluid">
+ <div class="span6">
+ <a href="#" class="btn btn-warning" data-bind="click: removeFilter" id="remove-filter-id">${$.i18n.prop('search.artifact.result.filter')}</a>
+ </div>
+ <div class="span6" id="search-result-number-div">
+ </div>
+ </div>
+ <table class="table table-striped table-bordered" id="search-results-grid">
+ </table>
+ <div id="search-results-view-grid-pagination"></div>
+
+ </div>
+
+ </div>
+ </div>
+ </div>
+
+</script>
+
+<script type="text/html" id="search-result-number-div-tmpl">
+ <blockquote>
+ ${$.i18n.prop('search.artifact.result.size')}:&nbsp;${resultViewModel.artifacts().length}
+ </blockquote>
+
+</script>
+
+<script id="search-results-view-grid-tmpl" type="text/html">
+ <thead>
+ <tr>
+ <th title="${$.i18n.prop('search.artifact.results.groupId')}">${$.i18n.prop('search.artifact.results.groupId')}</th>
+ <th title="${$.i18n.prop('search.artifact.results.artifactId')}">
+ ${$.i18n.prop('search.artifact.results.artifactId')}
+ </th>
+ <th title="${$.i18n.prop('search.artifact.results.version')}">${$.i18n.prop('search.artifact.results.version')}</th>
+ <th title="${$.i18n.prop('search.artifact.results.classifier')}">
+ ${$.i18n.prop('search.artifact.results.classifier')}
+ </th>
+ </tr>
+ <tr>
+
+ <th title="${$.i18n.prop('search.artifact.results.groupId')}">
+ <input type="text" class="form-search" id="search-filter-auto-groupId"
+ placeholder="${$.i18n.prop('search.artifact.result.grid.filter')}"/>
+ </th>
+ <th title="${$.i18n.prop('search.artifact.results.artifactId')}">
+ <input type="text" class="form-search" id="search-filter-auto-artifactId"
+ placeholder="${$.i18n.prop('search.artifact.result.grid.filter')}"/>
+ </th>
+ <th title="${$.i18n.prop('search.artifact.results.version')}">
+ <input type="text" class="form-search" id="search-filter-auto-version"
+ placeholder="${$.i18n.prop('search.artifact.result.grid.filter')}"/>
+ </th>
+ <th title="${$.i18n.prop('search.artifact.results.classifier')}">
+ <input type="text" class="form-search" id="search-filter-auto-classifier"
+ placeholder="${$.i18n.prop('search.artifact.result.grid.filter')}"/>
+ </th>
+
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr>
+ <td><a href="#" data-bind="click: function(){groupIdView(row)}">${row.groupId}</a></td>
+ <td><a href="#" data-bind="click: function(){artifactIdView(row)}">${row.artifactId}</a></td>
+ <td><a href="#" data-bind="click: function(){artifactDetailView(row)}">${row.version}</a></td>
+ <td>${row.classifier}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+</script>
+
+
+<script id="selected_repository_tmpl" type="text/html">
+ <select id="select_browse_repository" onchange="changeBrowseRepository()">
+ <option value="">All</option>
+ {{each(i,repository) repositories}}
+ {{if selected && selected==repository.id}}
+ <option value="${repository.id}" selected>${repository.name}</option>
+ {{else}}
+ <option value="${repository.id}">${repository.name}</option>
+ {{/if}}
+ {{/each}}
+ </select>
+ {{if selected && feedsUrl}}
+ <a href="${feedsUrl}"><img src="images/atom.gif"/></a>
+ {{/if}}
+</script>
+
+<script id="browse-artifact-detail-tmpl" type="text/html">
+<ul id="artifact-details-tabs" class="nav nav-tabs">
+ <li class="active">
+ <a data-toggle="tab" id="artifact-details-info-content-a" data-target="#artifact-details-info-content"
+ href="#artifact-details-info-content">${$.i18n.prop('artifact.detail.tab.header.info')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-dependencies-content-a"
+ data-target="#artifact-details-dependencies-content" href="#artifact-details-dependencies-content">${$.i18n.prop('artifact.detail.tab.header.dependencies')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-dependency-tree-content-a"
+ data-target="#artifact-details-dependency-tree-content" href="#artifact-details-dependency-tree-content">${$.i18n.prop('artifact.detail.tab.header.dependency.tree')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-download-content-a" data-target="#artifact-details-download-content"
+ href="#artifact-details-download-content">${$.i18n.prop('artifact.detail.tab.header.file.download')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-used-by-content-a" data-target="#artifact-details-used-by-content"
+ href="#artifact-details-used-by-content">${$.i18n.prop('artifact.detail.tab.header.used.by')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-mailing-list-content-a"
+ data-target="#artifact-details-mailing-list-content" href="#artifact-details-mailing-list-content">${$.i18n.prop('artifact.detail.tab.header.mailing.list')}</a>
+ </li>
+ <li>
+ <a data-toggle="tab" id="artifact-details-metadatas-content-a" data-target="#artifact-details-metadatas-content"
+ href="#artifact-details-metadatas-content">${$.i18n.prop('artifact.detail.tab.header.metadatas')}</a>
+ </li>
+</ul>
+<div class="tab-content">
+{{if projectVersionMetadata}}
+<div id="artifact-details-info-content" class="tab-pane active">
+ <blockquote>${projectVersionMetadata.description}</blockquote>
+ <div class="row-fluid">
+ <div class="span6">
+ <table class="table">
+ <tbody>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.groupId')}</th>
+ <td>${groupId}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.artifactId')}</th>
+ <td>${artifactId}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.version')}</th>
+ <td>${version}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.packaging')}</th>
+ {{if projectVersionMetadata.mavenFacet}}
+ <td>${projectVersionMetadata.mavenFacet.packaging}</td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ </tr>
+ {{if projectVersionMetadata.mavenFacet}}
+ {{if projectVersionMetadata.mavenFacet.parent }}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.parent')}</th>
+ <td>
+ <a href="#" data-bind="click: displayParent">
+ ${projectVersionMetadata.mavenFacet.parent.groupId}:${projectVersionMetadata.mavenFacet.parent.artifactId}:${projectVersionMetadata.mavenFacet.parent.version}
+ </a>
+ </td>
+ </tr>
+ {{/if}}
+ {{/if}}
+ </tbody>
+ </table>
+ </div>
+ <div class="span6">
+ <h4>${$.i18n.prop('browse.artifact.pom.snippet')}</h4>
+ <pre class="prettyprint">&lt;dependency&gt;<br/>&nbsp;&nbsp;&lt;groupId&gt;${groupId}&lt;/groupId&gt;<br/>&nbsp;&nbsp;&lt;artifactId&gt;${artifactId}&lt;/artifactId&gt;<br/>&nbsp;&nbsp;&lt;version&gt;${version}&lt;/version&gt;<br/>&lt;/dependency&gt;</pre>
+ </div>
+ </div>
+ <div>
+ <div class="page-header">
+ <h4>${$.i18n.prop('browse.artifact.other.details')}</h4>
+ </div>
+ <div>
+ <div class="row-fluid">
+ <div class="span9">
+ <table class="table">
+ <tbody>
+ {{if projectVersionMetadata.url}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.url')}</th>
+ <td><a href="${projectVersionMetadata.url}" target="_blank">${projectVersionMetadata.url}</a></td>
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata.organization}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.organization.name')}</th>
+ {{if projectVersionMetadata.organization.url}}
+ <td>
+ <a href="${projectVersionMetadata.organization.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${projectVersionMetadata.organization.name}
+ </a>
+ </td>
+ {{else}}
+ <td>${projectVersionMetadata.organization.name}</td>
+ {{/if}}
+ </tr>
+ {{/if}}
+ {{each(i,license) projectVersionMetadata.licenses}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.license')}</th>
+ {{if license.url}}
+ <td>
+ <a href="${license.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${license.name}
+ </a>
+ </td>
+ {{else}}
+ <td>${license.name}</td>
+ {{/if}}
+ </tr>
+ {{/each}}
+ {{if projectVersionMetadata.issueManagement}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.organization.issueManagement')}</th>
+ <td>
+ <a href="${projectVersionMetadata.issueManagement.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${projectVersionMetadata.issueManagement.system}
+ </a>
+ </td>
+ </tr>
+ {{/if}}
+ {{if projectVersionMetadata.ciManagement}}
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.organization.ciManagement')}</th>
+ <td>
+ <a href="${projectVersionMetadata.ciManagement.url}" target="_blank">
+ <img src="images/internet-web-browser.png" alt=""/>${projectVersionMetadata.ciManagement.system}
+ </a>
+ </td>
+ </tr>
+ {{/if}}
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ {{if projectVersionMetadata.scm}}
+ <div>
+ <div class="page-header">
+ <h4>${$.i18n.prop('browse.artifact.scm')}</h4>
+ </div>
+ <div>
+ <div class="row-fluid">
+ <div class="span12">
+ <table class="table">
+ <tbody>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.scm.connection')}</th>
+ <td>${projectVersionMetadata.scm.connection}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.scm.devconnection')}</th>
+ <td>${projectVersionMetadata.scm.developerConnection}</td>
+ </tr>
+ <tr>
+ <th>${$.i18n.prop('browse.artifact.scm.viewer')}</th>
+ <td><a href="${projectVersionMetadata.scm.url}" target="_blank">${projectVersionMetadata.scm.url}</a></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ {{/if}}
+</div>
+{{/if}}
+
+
+<div id="artifact-details-dependencies-content" class="tab-pane">
+ <table class="table table-striped table-bordered" id="artifact-dependencies-table"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko_dependenciesGrid',pageLinksId:'dependenciesPagination',data:'dependencies'">
+ </table>
+ <div id="dependenciesPagination"></div>
+</div>
+
+<div id="artifact-details-dependency-tree-content" class="tab-pane"></div>
+
+<div id="artifact-details-files-content" class="tab-pane"></div>
+
+<div id="artifact-details-download-content" class="tab-pane"></div>
+
+<div id="artifact-details-used-by-content" class="tab-pane">
+ <table class="table table-striped table-bordered" id="artifact-usedby-table">
+ </table>
+ <div id="usedbyPagination"></div>
+</div>
+
+<div id="artifact-details-mailing-list-content" class="tab-pane">
+ {{if projectVersionMetadata.mailingLists && projectVersionMetadata.mailingLists.length>0}}
+ <div id="accordion_mailing_lists" class="accordion">
+ {{each(i,mailingList) projectVersionMetadata.mailingLists}}
+ <div class="accordion-group">
+ <div class="accordion-heading">
+ <a class="accordion-toggle" href="#ml_collapse_${i}" data-parent="#accordion_mailing_lists"
+ data-toggle="collapse">${mailingList.name}</a>
+ </div>
+ {{if i==0}}
+ <div id="ml_collapse_${i}" class="accordion-body collapse in">
+ {{else}}
+ <div id="ml_collapse_${i}" class="accordion-body collapse">
+ {{/if}}
+ <div class="accordion-inner">
+ {{if mailingList.subscribeAddress}}
+ <div>
+ <b>${$.i18n.prop('browse.artifact.mailingList.subscribe')}</b>: <a
+ href="mailto:${mailingList.subscribeAddress}">${mailingList.subscribeAddress}</a>
+ </div>
+ {{/if}}
+ {{if mailingList.postAddress}}
+ <div>
+ <b>${$.i18n.prop('browse.artifact.mailingList.post')}</b>: <a href="mailto:${mailingList.postAddress}">${mailingList.postAddress}</a>
+ </div>
+ {{/if}}
+ {{if mailingList.unsubscribeAddress}}
+ <div>
+ <b>${$.i18n.prop('browse.artifact.mailingList.unsubscribe')}</b>: <a
+ href="mailto:${mailingList.unsubscribeAddress}">${mailingList.unsubscribeAddress}</a>
+ </div>
+ {{/if}}
+ {{if mailingList.mainArchiveUrl}}
+ <div>
+ <b>${$.i18n.prop('browse.artifact.mailingList.mainArchiveUrl')}</b>: <a
+ href="${mailingList.mainArchiveUrl}" target="_blank">${mailingList.mainArchiveUrl}</a>
+ </div>
+ {{/if}}
+ {{if mailingList.otherArchives && mailingList.otherArchives.length>0}}
+ <div>
+ <b>${$.i18n.prop('browse.artifact.mailingList.otherArchivesUrls')}:</b>
+ <ul>
+ {{each(j,otherArchive) mailingList.otherArchives}}
+ <li><b>${$.i18n.prop('browse.artifact.mailingList.otherArchiveUrl')}</b>: <a href="${otherArchive}"
+ target="_blank">${otherArchive}</a>
+ </li>
+ {{/each}}
+ </ul>
+ </div>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ {{/each}}
+ </div>
+ {{else}}
+ ${$.i18n.prop('browse.artifact.mailingList.none')}
+ {{/if}}
+ </div>
+
+ <div id="artifact-details-metadatas-content" class="tab-pane">
+ <table class="table table-striped table-bordered" id="artifact-details-metadatas-content-table"
+ data-bind="simpleGrid: gridMetatadasViewModel,simpleGridTemplate:'artifact_metadata_properties_tmpl',pageLinksId:'artifactMetadata_Pagination'">
+
+ </table>
+ <div id="artifactMetadata_Pagination"></div>
+ {{if hasSavePropertyKarma()}}
+ <a href="#" class="btn btn-primary"
+ data-bind="click: addProperty">${$.i18n.prop('browse.artifact.metadatas.add')}</a>
+ {{/if}}
+ </div>
+
+</div>
+</div>
+</script>
+
+<script id="ko_dependenciesGrid" type="text/html">
+ <tbody>
+
+
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr>
+ <th>${row.artifactId}</th>
+ </tr>
+ <tr>
+ <td>
+ {{var entries=row.crumbEntries()}}
+ {{each(j,crumbEntry) entries}}
+ {{if j < entries.length - 2}}
+ <a href="#" data-bind="click: function(){displayGroup(crumbEntry.groupId)}">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 2}}
+ <a href="#" data-bind="click: function(){displayArtifactDetailView(crumbEntry.groupId,crumbEntry.artifactId)}">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 1}}
+ &nbsp;|&nbsp;<b>${$.i18n.prop('browse.artifact.version')}:</b>&nbsp;
+ <a href="#"
+ data-bind="click: function(){displayArtifactVersionDetailViewModel(crumbEntry.groupId,crumbEntry.artifactId,crumbEntry.version)}">${row.version}</a>&nbsp;
+ {{/if}}
+ {{if j < entries.length - 2}}
+ &nbsp;/&nbsp;
+ {{/if}}
+ {{/each}}
+
+ {{if row.scope}}
+ |&nbsp;<b>${$.i18n.prop('browse.artifact.scope')}:</b>&nbsp;${row.scope}
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+
+ </tbody>
+</script>
+
+<script id="dependency_tree_tmpl" type="text/html">
+ <ul>
+ {{each(i,treeEntry) treeEntries}}
+ <li>
+ {{var entries=treeEntry.artifact.crumbEntries()}}
+ {{each(j,crumbEntry) entries}}
+ {{if j < entries.length - 2}}
+ <a class="cursor-hand" onclick="generalDisplayGroup(encodeURIComponent('${crumbEntry.groupId}'))">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 2}}
+ <a class="cursor-hand"
+ onclick="generalDisplayArtifactDetailView(encodeURIComponent('${crumbEntry.groupId}'),encodeURIComponent('${crumbEntry.artifactId}'))">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 1}}
+ &nbsp;|&nbsp;<b>${$.i18n.prop('browse.artifact.version')}:</b>&nbsp;
+ <a class="cursor-hand"
+ onclick="generalDisplayArtifactVersionDetailViewModel(encodeURIComponent('${crumbEntry.groupId}'),encodeURIComponent('${crumbEntry.artifactId}'),encodeURIComponent('${crumbEntry.version}'))">${crumbEntry.version}</a>&nbsp;
+ {{/if}}
+ {{if j < entries.length - 2}}
+ &nbsp;/&nbsp;
+ {{/if}}
+ {{/each}}
+ </li>
+ {{if treeEntry.childs.length>0}}
+ {{tmpl({treeEntries:treeEntry.childs}) "#dependency_tree_tmpl"}}
+ {{/if}}
+ {{/each}}
+ </ul>
+</script>
+
+<script id="dependees_tmpl" type="text/html">
+ <ul>
+ {{each(i, artifact) itemsOnCurrentPage()}}
+
+ <li>
+ {{var entries=artifact.crumbEntries()}}
+ {{each(j,crumbEntry) entries}}
+ {{if j < entries.length - 2}}
+ <a class="cursor-hand" onclick="generalDisplayGroup(encodeURIComponent('${crumbEntry.groupId}'))">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 2}}
+ <a class="cursor-hand"
+ onclick="generalDisplayArtifactDetailView(encodeURIComponent('${crumbEntry.groupId}'),encodeURIComponent('${crumbEntry.artifactId}'))">${crumbEntry.displayValue}</a>
+ {{else j == entries.length - 1}}
+ &nbsp;|&nbsp;<b>${$.i18n.prop('browse.artifact.version')}:</b>&nbsp;
+ <a class="cursor-hand"
+ onclick="generalDisplayArtifactVersionDetailViewModel(encodeURIComponent('${crumbEntry.groupId}'),encodeURIComponent('${crumbEntry.artifactId}'),encodeURIComponent('${crumbEntry.version}'))">${crumbEntry.version}</a>&nbsp;
+ {{/if}}
+ {{if j < entries.length - 2}}
+ &nbsp;/&nbsp;
+ {{/if}}
+ {{/each}}
+ </li>
+ {{/each}}
+ </ul>
+</script>
+
+<script id="artifact_metadata_properties_tmpl" type="text/html">
+ <thead>
+ <tr>
+ <th title="${$.i18n.prop('browse.artifact.metadatas.key')}">${$.i18n.prop('browse.artifact.metadatas.key')}</th>
+ <th title="${$.i18n.prop('browse.artifact.metadatas.value')}">${$.i18n.prop('browse.artifact.metadatas.value')}</th>
+ <th title="${$.i18n.prop('browse.artifact.metadatas.delete')}">${$.i18n.prop('browse.artifact.metadatas.delete')}
+ </th>
+ <th title="${$.i18n.prop('browse.artifact.metadatas.save')}">${$.i18n.prop('browse.artifact.metadatas.save')}</th>
+ </tr>
+
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr>
+ {{if row.editable && hasSavePropertyKarma()}}
+ <td><input type="text" data-bind="value: row.key"/></td>
+ {{else}}
+ <td>${row.key}</td>
+ {{/if}}
+ <td>
+ {{if hasSavePropertyKarma()}}
+ <input type="text" data-bind="value: row.value"/>
+ {{else}}
+ ${row.value}
+ {{/if}}
+ </td>
+ <td>
+ {{if hasDeletePropertyKarma()}}
+ <a href="#" class="btn btn-danger" data-bind="click: function(){deleteProperty(row)}">${$.i18n.prop('browse.artifact.metadatas.delete')}</a>
+ {{/if}}
+ </td>
+ <td>
+ {{if row.modified && hasSavePropertyKarma()}}
+ <a href="#" class="btn btn-warning" data-bind="click: function(){saveProperty(row)}">${$.i18n.prop('browse.artifact.metadatas.save')}</a>
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+</script>
+
+<script id="artifact_content_tree_partial" type="text/html">
+ <ul class="jqueryFileTree" style="display: none;">
+ {{each artifactContentEntries}}
+ {{if $value.file == true}}
+ <li class="file">
+ <a href="#" rel="${$value.path}/">${$value.text}</a>
+ </li>
+ {{else}}
+ <li class="directory collapsed">
+ <a href="#" rel="${$value.path}/">${$value.text}</a>
+ </li>
+ {{/if}}
+ {{/each}}
+ </ul>
+</script>
+
+<script id="artifact-details-download-content_tmpl" type="text/html">
+
+ <div class="row-fluid">
+ <div class="span5">
+ <ul id="artifact-download-list-files" class="package-list">
+ {{each(i, row) artifacts()}}
+ <li>
+ <img src="images/system-search-16-16.png" class="cursor-hand" id="${row.classifier}:${row.version}:${row.packaging}"
+ title="${$.i18n.prop('browse.artifact.content.view.tooltip')}"/>
+ {{if deleteKarma}}
+ <a href="#" data-bind="click: function(){deleteArtifact(row)}">
+ <img src="images/trash.png" title="${$.i18n.prop('browse.artifact.content.delete.tooltip')}"/>
+ </a>
+ &nbsp;
+ <a href="${row.url}">
+ <img src="images/drive-removable-media-16-16.png" title="${$.i18n.prop('browse.artifact.content.download.tooltip')}"/>
+ </a>
+ &nbsp;
+ <span class="text-info">${row.packaging}:${row.version}&nbsp;-&nbsp;${row.size}</span>
+ {{else}}
+ <a href="${row.url}">
+ <img src="images/drive-removable-media-16-16.png" title="${$.i18n.prop('browse.artifact.content.download.tooltip')}"/>
+ </a>
+ &nbsp;
+ <span class="text-info">${row.packaging}:${row.version}&nbsp;-&nbsp;${row.size}</span>
+ {{/if}}
+ </li>
+ {{/each}}
+ </ul>
+ </div>
+ <div class="span7">
+ <div id="artifact_content_tree">
+ </div>
+ </div>
+ </div>
+
+ <h4 id="artifact-content-text-header">${$.i18n.prop('browse.artifact.content.header')}</h4>
+
+ <div class="source">
+ <pre class="prettyprint linenums" id="artifact-content-text"></pre>
+ </div>
+
+</script> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/login.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/login.html
new file mode 100644
index 000000000..6e036cc17
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/login.html
@@ -0,0 +1,163 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<div id="modal-login" class="modal hide fade">
+ <div class="modal-header">
+ <a href="#" class="close" data-dismiss="modal">&times;</a>
+
+ <h3>${$.i18n.prop('login.section.title')}</h3>
+ </div>
+ <div class="modal-body" id="modal-login-content">
+ <form id="user-login-form" class="form-horizontal">
+ <div id="modal-login-err-message" class="alert alert-error" style="display:none"></div>
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="user-login-form-username">${$.i18n.prop('username')}</label>
+
+ <div class="controls">
+ <input type="text" id="user-login-form-username" name="user-login-form-username" class="required"
+ placeholder="${$.i18n.prop('login.username.placehoder')}"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="user-login-form-password">${$.i18n.prop('password')}</label>
+
+ <div class="controls">
+ <input type="password" id="user-login-form-password" name="user-login-form-password" class="required"
+ placeholder="${$.i18n.prop('login.password.placehoder')}"/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer" id="modal-login-footer">
+ <div class="pull-left">
+ <label class="checkbox" id="user-login-form-rememberme-label">
+ <input type="checkbox" id="user-login-form-rememberme">${$.i18n.prop('rememberme')}
+ </label>
+ </div>
+ <button class="btn btn-primary" id="modal-login-ok" data-loading-text="${$.i18n.prop('common.loading')}">
+ ${$.i18n.prop('login')}
+ </button>
+ <button class="btn btn-info" id="modal-login-password-reset">${$.i18n.prop('password.reset')}</button>
+ </div>
+</div>
+
+<div id="modal-register" class="modal hide fade">
+ <div class="modal-header">
+ <a href="#" class="close" data-dismiss="modal">&times;</a>
+
+ <h3>${$.i18n.prop('register.section.title')}</h3>
+ </div>
+ <div class="modal-body" id="modal-register-content">
+ <form id="user-register-form" class="form-horizontal">
+ <div id="modal-register-err-message" class="alert-message error" style="display:none"></div>
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="user-register-form-username">${$.i18n.prop('username')}</label>
+
+ <div class="controls">
+ <input type="text" id="user-register-form-username" name="user-register-form-username" class="required"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="user-register-form-fullname">${$.i18n.prop('full.name')}</label>
+
+ <div class="controls">
+ <input type="text" id="user-register-form-fullname" name="user-register-form-fullname" class="required"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="user-register-form-email">${$.i18n.prop('email')}</label>
+
+ <div class="controls">
+ <input type="text" id="user-register-form-email" name="user-register-form-email" class="required email"/>
+ </div>
+ </div>
+
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer" id="modal-register-footer">
+ <button class="btn btn-primary" id="modal-register-ok">${$.i18n.prop('register')}</button>
+ </div>
+</div>
+
+<div id="modal-password-change" class="modal hide fade">
+ <div class="modal-header">
+ <a href="#" class="close" data-dismiss="modal">&times;</a>
+
+ <h3>${$.i18n.prop('password.section.title')}</h3>
+ </div>
+ <div class="modal-body" id="modal-password-change-content">
+ <form id="password-change-form" class="form-horizontal">
+ <div id="modal-password-change-err-message" class="alert-message error" style="display:none"></div>
+ <fieldset>
+ <!-- part displayed only when a logged user want to change password will be hide when validate user registration -->
+ <div class="control-group" id="password-change-form-current-password-div">
+ <label class="control-label"
+ for="password-change-form-current-password">${$.i18n.prop('password.existing')}</label>
+
+ <div class="controls">
+ <input type="password" id="password-change-form-current-password"
+ name="password-change-form-current-password" class="required" value=""/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="passwordChangeFormNewPassword">${$.i18n.prop('password.new')}</label>
+
+ <div class="controls">
+ <input type="password" id="passwordChangeFormNewPassword" name="passwordChangeFormNewPassword"
+ class="required" value=""/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label"
+ for="passwordChangeFormNewPasswordConfirm">${$.i18n.prop('password.new.confirm')}</label>
+
+ <div class="controls">
+ <input type="password" id="passwordChangeFormNewPasswordConfirm" name="passwordChangeFormNewPasswordConfirm"
+ class="required" value=""/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer" id="modal-password-change-footer">
+ <button class="btn btn-primary" onclick="return" id="modal-change-password-ok">${$.i18n.prop('ok')}</button>
+ </div>
+</div>
+
+<div id="modal-user-edit" class="modal hide fade">
+ <div class="modal-header">
+ <a href="#" class="close" data-dismiss="modal">&times;</a>
+
+ <h3>${$.i18n.prop('password.section.title')}</h3>
+ </div>
+ <div class="modal-body" id="modal-user-edit-content">
+
+ </div>
+ <div class="modal-footer" id="modal-user-edit-footer">
+ <button class="btn primary" onclick="return" id="modal-user-edit-ok">${$.i18n.prop('ok')}</button>
+ </div>
+</div>
+
+
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/user-edit.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/user-edit.html
new file mode 100644
index 000000000..9102ce2f0
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/redback/user-edit.html
@@ -0,0 +1,572 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+-->
+<script id='redback/user-edit-tmpl' type='text/html'>
+ <div id="edit-user-details-pills">
+ <ul id="edit_user_details_pills_headers" class="nav nav-pills" data-target="#edit-user-details-pills-content">
+ <li class="active" id="user-view-detail-li">
+ <a data-toggle="tab" href="#user-create-div">${$.i18n.prop('edit')}</a>
+ </li>
+ <li id="user-edit-roles-edit-li">
+ <a data-toggle="tab" href="#user-edit-roles-edit">${$.i18n.prop('effective.roles.edit')}</a>
+ </li>
+ </ul>
+ <div class="pill-content" id="edit-user-details-pills-content">
+ <div id="user-create-div" class="active pill-pane">
+ <div class="row-fluid">
+ <div class="span8 columns">
+ <form id="user-create" class="well form-horizontal" data-bind="submit: save">
+ <fieldset id="user-create-fieldset">
+ <div class="control-group">
+ <label class="control-label" for="username">${$.i18n.prop('username')}</label>
+
+ <div class="controls" id="username-div">
+ {{if $data.username.length>0}}
+ <span class="uneditable-input">${$data.username}</span>
+ {{else}}
+ <input type="text" id="username" name="username" size="30" class="required"
+ data-bind="value: username"/>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="fullname">${$.i18n.prop('full.name')}</label>
+
+ <div class="controls">
+ <input type="text" id="fullname" name="fullname" size="30" class="required"
+ data-bind="value: fullName"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="password">${$.i18n.prop('password')}</label>
+
+ <div class="controls">
+ <input type="password" id="password" name="password" class="required" data-bind="value: password"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="confirmPassword">${$.i18n.prop('confirm.password')}</label>
+
+ <div class="controls">
+ <input type="password" id="confirmPassword" name="confirmPassword"
+ data-bind="value: confirmPassword"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="email">${$.i18n.prop('email.address')}</label>
+
+ <div class="controls">
+ <input type="text" id="email" name="email" class="required email" data-bind="value: email"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="validated">${$.i18n.prop('validated')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="validated" name="validated" data-bind="checked: validated"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="locked">${$.i18n.prop('locked')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="locked" name="locked" data-bind="checked: locked"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="passwordChangeRequired">${$.i18n.prop('user.change.password.required')}</label>
+
+ <div class="controls">
+ <input type="checkbox" id="passwordChangeRequired" name="passwordChangeRequired"
+ data-bind="checked: passwordChangeRequired"/>
+ </div>
+ </div>
+ </fieldset>
+ <button data-bind="click: saveUser" class="btn" id="user-create-form-register-button">
+ ${$.i18n.prop('save')}
+ </button>
+ <button class="btn" id="user-create-form-cancel-button">${$.i18n.prop('cancel')}</button>
+ </form>
+ </div>
+ <div class="span4 columns" id="user-edit-roles">
+ <div id="user-edit-roles-view"></div>
+ </div>
+ </div>
+ </div>
+
+ <div id="user-edit-roles-edit" class="pill-pane">
+ roles edit
+ </div>
+ </div>
+ </div>
+</script>
+
+<script id="user_view_roles_list_tmpl" type="text/html">
+ <div class="page-header">
+ <h3>${$.i18n.prop('effective.roles')}</h3>
+ </div>
+ <div>
+ <ul>
+ {{each $data.user.assignedRoles}}
+ <li>${$value}</li>
+ {{/each}}
+ </ul>
+ </div>
+</script>
+
+<script id="user_edit_roles_tmpl" type="text/html">
+
+ <div>
+ {{each $data.applicationRoles}}
+ <div class="page-header">
+ <h3>${$value.name}</h3>
+ </div>
+ <blockquote>
+ <p>${$value.description}</p>
+ </blockquote>
+ <ul>
+ {{each $value.globalRoles}}
+ <li><input type="checkbox" value="${$value}" data-bind="checked: user.assignedRoles">&nbsp;${$value}</input></li>
+ {{/each}}
+ </ul>
+
+ {{if roleTemplates}}
+ <table class="bordered-table">
+ <thead>
+ <tr>
+ <th>&nbsp;</th>
+ {{each roleTemplates}}
+ <th>${$value.namePrefix}</th>
+ {{/each}}
+ </tr>
+ </thead>
+ <tbody>
+ {{each resources}}
+ {{var curResource = $value}}
+ <tr>
+ <td>${curResource}</td>
+ {{each roleTemplates}}
+ <td><input type="checkbox" value="${$value.namePrefix}${$value.delimiter}${curResource}"
+ data-bind="checked: user.assignedRoles"/></td>
+ {{/each}}
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ {{/if}}
+
+ {{/each}}
+
+ <button class="btn" data-bind="click:updateUserRoles">${$.i18n.prop('update')}</button>
+
+ </div>
+</script>
+
+<script id='ko_usersGrid_grid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th>${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('delete')}</th>
+ <th>${$.i18n.prop('user.list.locked')}</th>
+ <th>${$.i18n.prop('user.change.password.required')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()}">
+ {{each(j, columnDefinition) columns}}
+ <td>
+ ${ typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText] }
+ </td>
+ {{/each}}
+ <td id="users-grid-user-id-${row.username()}">
+ <a href="#" data-bind="click: function(){ editUserBox(row) }">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ {{if row.username()=="admin" || row.username()=="guest"}}
+ <td></td>
+ {{else}}
+ <td>
+ <a href="#" data-bind="click: function(){ deleteUser(row) }" id="users-grid-delete-${row.username()}">
+ <span class="btn btn-danger">
+ <i class="icon-trash icon-white"/>
+ </span>
+ </a>
+ </td>
+ {{/if}}
+
+ {{if row.locked()==true}}
+ <td>
+ <a href="#" data-bind="click: function(){ unlock(row) }"><img src="images/system-lock-screen-22-22.png"/></a>
+ </td>
+ {{else}}
+ <td>
+ <a href="#" data-bind="click: function(){ lock(row) }"><img src="images/weather-clear-22-22.png"/></a>
+ </td>
+ {{/if}}
+
+ {{if row.username()=="admin"}}
+ <td></td>
+ {{else}}
+ {{if row.passwordChangeRequired()==true}}
+ <td>
+ <a href="#" data-bind="click: function(){ passwordChangeRequire(row,false) }">
+ <img src="images/dialog-error-22-22.png"/>
+ </a>
+ </td>
+ {{else}}
+ <td>
+ <a href="#" data-bind="click: function(){ passwordChangeRequire(row,true) }">
+ <img src="images/weather-clear-22-22.png"/>
+ </a>
+ </td>
+ {{/if}}
+ {{/if}}
+ </tr>
+ {{/each}}
+ </tbody>
+
+</script>
+
+<script id="usersGrid" type="text/html">
+ <div class="page-header">
+ <h3><img src="images/system-users-32-32.png"/>${$.i18n.prop('users.list')}</h3>
+ </div>
+ <ul id="users-view-tabs" class="nav nav-tabs" data-target="#users-view-tabs-content">
+ <li class="active" id="users-view-tabs-li-users-grid">
+ <a data-toggle="tab" href="#users-view">${$.i18n.prop('users.grid.tab.title')}</a>
+ </li>
+ <li id="users-view-tabs-li-user-edit">
+ <a data-toggle="tab" href="#createUserForm" id="users-view-tabs-li-user-edit-a">${$.i18n.prop('add')}</a>
+ </li>
+ </ul>
+ <div id="users-view-tabs-content" class="tab-content">
+ <div id="users-view" class="tab-pane">
+ <button data-bind='click: sortByName' class="btn">
+ ${$.i18n.prop('users.sort.byname')}
+ </button>
+ <table class="table table-striped table-bordered" id="usersTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko_usersGrid_grid',pageLinksId:'usersPagination'">
+ </table>
+ <div id="usersPagination"></div>
+ </div>
+ <div id="createUserForm" class="tab-pane"></div>
+ </div>
+</script>
+
+<script id="user-delete-warning-tmpl" type='text/html'>
+ <div>
+ <span class="label label-warning">${$.i18n.prop('warning.not.undone.operation')}</span>
+ </div>
+</script>
+
+<script id="rolesTabs" type="text/html">
+ <div class="page-header">
+ <h2>${$.i18n.prop('roles.management.header')}</h2>
+ </div>
+
+ <ul id="roles-view-tabs" class="nav nav-tabs" data-target="roles-view-tabs-content">
+ <li class="active" id="roles-view-tabs-li-roles-grid">
+ <a data-toggle="tab" href="#roles-view"
+ id="roles-view-tabs-a-roles-grid">${$.i18n.prop('roles.grid.tab.title')}</a>
+ </li>
+ <li id="roles-view-tabs-li-roles-edit">
+ <a data-toggle="tab" href="#role-edit">${$.i18n.prop('edit')}</a>
+ </li>
+ </ul>
+ <div id="roles-view-tabs-content" class="tab-content">
+ <div id="roles-view" class="tab-pane">
+ <div data-bind="style: { display: bulkSave() ? '' : 'none' }">
+ <a data-bind="click: updateModifiedRoles" class="btn btn-danger" href="#">${$.i18n.prop('save.all')}</a>
+ <br/>
+ </div>
+ <table class="table table-striped table-bordered" id="rolesTable"
+ data-bind="simpleGrid: gridViewModel,simpleGridTemplate:'ko_rolesGrid',pageLinksId:'rolesPagination'">
+ </table>
+ <div id="rolesPagination"></div>
+ </div>
+ <div id="role-edit" class="tab-pane" data-bind="template: {name:'editRoleTab',data: currentRole}"></div>
+ </div>
+
+</script>
+
+<script id="editRoleTab" type="text/html">
+ <div class="accordion" id="edit-role-accordion">
+ <div class="accordion-group">
+ <div class="accordion-heading">
+ <h3>
+ <a class="accordion-toggle" href="#role-collapse" data-parent="#edit-role-accordion" data-toggle="collapse">${$.i18n.prop('role')}</a>
+ </h3>
+ </div>
+ <div id="role-collapse" class="accordion-body collapse in">
+ <table class="table table-bordered" id="editRoleTable">
+ <tbody>
+ <tr>
+ <td>${$.i18n.prop('name')}:</td>
+ <td id="role-edit-name">${$data.name}</td>
+ </tr>
+ <tr>
+ <td>${$.i18n.prop('description')}:</td>
+ <td><input type="text" id="role-edit-description" data-bind="value: description"></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <div class="pull-left">
+ <button class="btn" id="role-edit-description-save" data-bind="click: saveRoleDescription">
+ ${$.i18n.prop('save')}
+ </button>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="page-header">
+ <h3>${$.i18n.prop('role.model.parent.roles')}</h3>
+ </div>
+ {{if $data.parentRoleNames}}
+ <ul>
+ {{each $data.parentRoleNames}}
+ <li>${$value}</li>
+ {{/each}}
+ </ul>
+ {{/if}}
+
+ <div class="page-header">
+ <h3>${$.i18n.prop('role.model.child.roles')}</h3>
+ </div>
+ {{if $data.childRoleNames}}
+ <ul>
+ {{each $data.childRoleNames}}
+ <li>${$value}</li>
+ {{/each}}
+ </ul>
+ {{/if}}
+
+ <div class="page-header">
+ <h3>${$.i18n.prop('permissions')}</h3>
+ </div>
+ {{if $data.permissions}}
+ <table class="table table-striped table-bordered" id="rolePermissionsTable">
+ <thead>
+ <tr>
+ <th>${$.i18n.prop('name')}</th>
+ <th>${$.i18n.prop('role.operation')}</th>
+ <th>${$.i18n.prop('role.resource')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each permissions}}
+ <tr>
+ <td>${$value.name}</td>
+ {{if $value.operation }}
+ <td>${$value.operation().name}</td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ {{if $value.resource }}
+ <td>${$value.resource().identifier}</td>
+ {{else}}
+ <td></td>
+ {{/if}}
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ {{/if}}
+ </div>
+ </div>
+ <div class="accordion-group>">
+ <div class="accordion-heading">
+ <h3>
+ <a class="accordion-toggle" href="#role-users-collapse" data-parent="#edit-role-accordion"
+ data-toggle="collapse">${$.i18n.prop('role.edit.section.users')}</a>
+ </h3>
+ </div>
+ <div id="role-users-collapse" class="accordion-body collapse">
+ {{if $data.parentsRolesUsers}}
+ <div class="page-header">
+ <h3>${$.i18n.prop('role.edit.users.defined.in.parent.roles')}</h3>
+ </div>
+ <ul>
+ {{each $data.parentsRolesUsers}}
+ <li>${$value.fullName} - ( ${$value.username} - ${$value.email} )</li>
+ {{/each}}
+ </ul>
+ {{/if}}
+
+ <ul id="role-edit-users-tabs" class="nav nav-tabs">
+ <li class="active" id="role-view-users-li">
+ <a data-toggle="tab" href="#role-view-users">${$.i18n.prop('role.edit.users.list')}</a>
+ </li>
+ <li id="role-edit-users-li">
+ <a data-toggle="tab" href="#role-edit-users">${$.i18n.prop('edit')}</a>
+ </li>
+ </ul>
+
+ <div class="pill-content" id="role-edit-users-tabs-content">
+ <div id="role-view-users" class="active pill-pane">
+ <div class="page-header">
+ <h3>${$.i18n.prop('role.edit.users.defined.in.current.role')}</h3>
+ </div>
+ <div id="role-list-users">
+ {{if users().length>0}}
+ <ul>
+ {{each(j, user) users()}}
+ <li>${user.fullName()} - ( ${user.username()} - ${user.email()} )</li>
+ {{/each}}
+ </ul>
+ {{else}}
+ ${$.i18n.prop('role.edit.no.user.defined')}
+ {{/if}}
+ </div>
+ </div>
+
+ <div id="role-edit-users" class="clearfix ar-multiselect pill-pane">
+
+ <div class="ar-multiselect-column ar-multiselect-left">
+ <select data-bind="options: otherUsers ,optionsText: 'username',selectedOptions:selectedOtherUsers"
+ multiple="true" id="role-edit-available-users"></select>
+ </div>
+ <div class="ar-multiselect-column ar-multiselect-center">
+ <ul style="list-style: none">
+ <li><input class="btn" id="role-edit-users-add-user" type="button" data-bind="click: addUser"
+ value="&gt;"/></li>
+ <li><input class="btn" id="role-edit-users-remove-user" type="button" data-bind="click: removeUser"
+ value="&lt;"/></li>
+ </ul>
+ </div>
+ <div class="ar-multiselect-column ar-multiselect-right">
+ <select data-bind="options: users ,optionsText: 'username',selectedOptions:selectedUsers" multiple="true"
+ id="role-edit-affected-users"></select>
+ </div>
+ <button class="btn" id="role-edit-users-save" data-bind="click: saveUsers">${$.i18n.prop('save')}</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</script>
+
+<script id='ko_rolesGrid' type='text/html'>
+ <thead>
+ <tr>
+ {{each(i, columnDefinition) columns}}
+ <th>${ columnDefinition.headerText }</th>
+ {{/each}}
+ <th>${$.i18n.prop('edit')}</th>
+ <th>${$.i18n.prop('save')}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{each(i, row) itemsOnCurrentPage()}}
+ <tr data-bind="css:{ 'modified': row.modified()||row.usersModified()}">
+ {{each(j, columnDefinition) columns}}
+ {{var val = (typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) :
+ row[columnDefinition.rowText])}}
+ <td id="role-${columnDefinition.rowText}-${row.name()}">
+ ${val}
+ </td>
+ {{/each}}
+ <td>
+ <a id="edit-role-${row.name()}" href="#" data-bind="click: function(){ editRole(row) }">
+ <span class="btn btn-primary">
+ <i class="icon-pencil icon-white"/>
+ </span>
+ </a>
+ </td>
+ <td>
+ {{if row.modified()}}
+ <a href="#" class="btn btn-warning" data-bind="click: function(){ updateRole(row) }">${$.i18n.prop('save')}</a>
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+</script>
+
+
+<script type="text/html" id="modal-user-edit-tmpl">
+
+ <form id="user-edit-form" class="form-horizontal">
+ <div id="modal-user-edit-err-message" class="alert-message error" style="display:none"></div>
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="username">${$.i18n.prop('username')}</label>
+
+ <div class="controls" id="username-div">
+ <span class="uneditable-input" data-bind="text: user.username"></span>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="fullname">${$.i18n.prop('full.name')}</label>
+
+ <div class="controls">
+ {{if user.readOnly}}
+ <span class="uneditable-input" data-bind="text: user.fullName"></span>
+ {{else}}
+ <input type="text" id="fullname" name="fullname" size="30" class="required" data-bind="value: user.fullName"/>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" for="email">${$.i18n.prop('email.address')}</label>
+
+ <div class="controls">
+ {{if user.readOnly}}
+ <span class="uneditable-input" data-bind="text: user.email"></span>
+ {{else}}
+ <input type="text" id="email" name="email" size="30" class="required email" data-bind="value: user.email"/>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group" id="user-edit-form-current-password-div">
+ <label class="control-label" for="userEditFormCurrentPassword">${$.i18n.prop('password.existing')}</label>
+
+ <div class="controls">
+ <input type="password" id="userEditFormCurrentPassword" name="userEditFormCurrentPassword" class="required"
+ value=""/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditFormNewPassword">${$.i18n.prop('password.new')}</label>
+
+ <div class="controls">
+ <input type="password" id="userEditFormNewPassword" name="userEditFormNewPassword" class="" value=""/>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditFormNewPasswordConfirm">${$.i18n.prop('password.new.confirm')}</label>
+
+ <div class="controls">
+ <input type="password" id="userEditFormNewPasswordConfirm" name="userEditFormNewPasswordConfirm" class=""
+ value=""/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+
+</script>
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/text.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/text.js
new file mode 100644
index 000000000..39016dc03
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/text.js
@@ -0,0 +1,305 @@
+/**
+ * @license RequireJS text 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/requirejs/text for details
+ */
+/*jslint regexp: true */
+/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
+ define: false, window: false, process: false, Packages: false,
+ java: false, location: false */
+
+define(['module'], function (module) {
+ 'use strict';
+
+ var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
+ xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
+ bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
+ hasLocation = typeof location !== 'undefined' && location.href,
+ defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
+ defaultHostName = hasLocation && location.hostname,
+ defaultPort = hasLocation && (location.port || undefined),
+ buildMap = [],
+ masterConfig = (module.config && module.config()) || {},
+ text, fs;
+
+ text = {
+ version: '2.0.1',
+
+ strip: function (content) {
+ //Strips <?xml ...?> declarations so that external SVG and XML
+ //documents can be added to a document without worry. Also, if the string
+ //is an HTML document, only the part inside the body tag is returned.
+ if (content) {
+ content = content.replace(xmlRegExp, "");
+ var matches = content.match(bodyRegExp);
+ if (matches) {
+ content = matches[1];
+ }
+ } else {
+ content = "";
+ }
+ return content;
+ },
+
+ jsEscape: function (content) {
+ return content.replace(/(['\\])/g, '\\$1')
+ .replace(/[\f]/g, "\\f")
+ .replace(/[\b]/g, "\\b")
+ .replace(/[\n]/g, "\\n")
+ .replace(/[\t]/g, "\\t")
+ .replace(/[\r]/g, "\\r")
+ .replace(/[\u2028]/g, "\\u2028")
+ .replace(/[\u2029]/g, "\\u2029");
+ },
+
+ createXhr: masterConfig.createXhr || function () {
+ //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
+ var xhr, i, progId;
+ if (typeof XMLHttpRequest !== "undefined") {
+ return new XMLHttpRequest();
+ } else if (typeof ActiveXObject !== "undefined") {
+ for (i = 0; i < 3; i += 1) {
+ progId = progIds[i];
+ try {
+ xhr = new ActiveXObject(progId);
+ } catch (e) {}
+
+ if (xhr) {
+ progIds = [progId]; // so faster next time
+ break;
+ }
+ }
+ }
+
+ return xhr;
+ },
+
+ /**
+ * Parses a resource name into its component parts. Resource names
+ * look like: module/name.ext!strip, where the !strip part is
+ * optional.
+ * @param {String} name the resource name
+ * @returns {Object} with properties "moduleName", "ext" and "strip"
+ * where strip is a boolean.
+ */
+ parseName: function (name) {
+ var strip = false, index = name.indexOf("."),
+ modName = name.substring(0, index),
+ ext = name.substring(index + 1, name.length);
+
+ index = ext.indexOf("!");
+ if (index !== -1) {
+ //Pull off the strip arg.
+ strip = ext.substring(index + 1, ext.length);
+ strip = strip === "strip";
+ ext = ext.substring(0, index);
+ }
+
+ return {
+ moduleName: modName,
+ ext: ext,
+ strip: strip
+ };
+ },
+
+ xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
+
+ /**
+ * Is an URL on another domain. Only works for browser use, returns
+ * false in non-browser environments. Only used to know if an
+ * optimized .js version of a text resource should be loaded
+ * instead.
+ * @param {String} url
+ * @returns Boolean
+ */
+ useXhr: function (url, protocol, hostname, port) {
+ var match = text.xdRegExp.exec(url),
+ uProtocol, uHostName, uPort;
+ if (!match) {
+ return true;
+ }
+ uProtocol = match[2];
+ uHostName = match[3];
+
+ uHostName = uHostName.split(':');
+ uPort = uHostName[1];
+ uHostName = uHostName[0];
+
+ return (!uProtocol || uProtocol === protocol) &&
+ (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
+ ((!uPort && !uHostName) || uPort === port);
+ },
+
+ finishLoad: function (name, strip, content, onLoad) {
+ content = strip ? text.strip(content) : content;
+ if (masterConfig.isBuild) {
+ buildMap[name] = content;
+ }
+ onLoad(content);
+ },
+
+ load: function (name, req, onLoad, config) {
+ //Name has format: some.module.filext!strip
+ //The strip part is optional.
+ //if strip is present, then that means only get the string contents
+ //inside a body tag in an HTML string. For XML/SVG content it means
+ //removing the <?xml ...?> declarations so the content can be inserted
+ //into the current doc without problems.
+
+ // Do not bother with the work if a build and text will
+ // not be inlined.
+ if (config.isBuild && !config.inlineText) {
+ onLoad();
+ return;
+ }
+
+ masterConfig.isBuild = config.isBuild;
+
+ var parsed = text.parseName(name),
+ nonStripName = parsed.moduleName + '.' + parsed.ext,
+ url = req.toUrl(nonStripName),
+ useXhr = (masterConfig.useXhr) ||
+ text.useXhr;
+
+ //Load the text. Use XHR if possible and in a browser.
+ if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
+ text.get(url, function (content) {
+ text.finishLoad(name, parsed.strip, content, onLoad);
+ }, function (err) {
+ if (onLoad.error) {
+ onLoad.error(err);
+ }
+ });
+ } else {
+ //Need to fetch the resource across domains. Assume
+ //the resource has been optimized into a JS module. Fetch
+ //by the module name + extension, but do not include the
+ //!strip part to avoid file system issues.
+ req([nonStripName], function (content) {
+ text.finishLoad(parsed.moduleName + '.' + parsed.ext,
+ parsed.strip, content, onLoad);
+ });
+ }
+ },
+
+ write: function (pluginName, moduleName, write, config) {
+ if (buildMap.hasOwnProperty(moduleName)) {
+ var content = text.jsEscape(buildMap[moduleName]);
+ write.asModule(pluginName + "!" + moduleName,
+ "define(function () { return '" +
+ content +
+ "';});\n");
+ }
+ },
+
+ writeFile: function (pluginName, moduleName, req, write, config) {
+ var parsed = text.parseName(moduleName),
+ nonStripName = parsed.moduleName + '.' + parsed.ext,
+ //Use a '.js' file name so that it indicates it is a
+ //script that can be loaded across domains.
+ fileName = req.toUrl(parsed.moduleName + '.' +
+ parsed.ext) + '.js';
+
+ //Leverage own load() method to load plugin value, but only
+ //write out values that do not have the strip argument,
+ //to avoid any potential issues with ! in file names.
+ text.load(nonStripName, req, function (value) {
+ //Use own write() method to construct full module value.
+ //But need to create shell that translates writeFile's
+ //write() to the right interface.
+ var textWrite = function (contents) {
+ return write(fileName, contents);
+ };
+ textWrite.asModule = function (moduleName, contents) {
+ return write.asModule(moduleName, fileName, contents);
+ };
+
+ text.write(pluginName, nonStripName, textWrite, config);
+ }, config);
+ }
+ };
+
+ if (typeof process !== "undefined" &&
+ process.versions &&
+ !!process.versions.node) {
+ //Using special require.nodeRequire, something added by r.js.
+ fs = require.nodeRequire('fs');
+
+ text.get = function (url, callback) {
+ var file = fs.readFileSync(url, 'utf8');
+ //Remove BOM (Byte Mark Order) from utf8 files if it is there.
+ if (file.indexOf('\uFEFF') === 0) {
+ file = file.substring(1);
+ }
+ callback(file);
+ };
+ } else if (text.createXhr()) {
+ text.get = function (url, callback, errback) {
+ var xhr = text.createXhr();
+ xhr.open('GET', url, true);
+
+ //Allow overrides specified in config
+ if (masterConfig.onXhr) {
+ masterConfig.onXhr(xhr, url);
+ }
+
+ xhr.onreadystatechange = function (evt) {
+ var status, err;
+ //Do not explicitly handle errors, those should be
+ //visible via console output in the browser.
+ if (xhr.readyState === 4) {
+ status = xhr.status;
+ if (status > 399 && status < 600) {
+ //An http 4xx or 5xx error. Signal an error.
+ err = new Error(url + ' HTTP status: ' + status);
+ err.xhr = xhr;
+ errback(err);
+ } else {
+ callback(xhr.responseText);
+ }
+ }
+ };
+ xhr.send(null);
+ };
+ } else if (typeof Packages !== 'undefined') {
+ //Why Java, why is this so awkward?
+ text.get = function (url, callback) {
+ var encoding = "utf-8",
+ file = new java.io.File(url),
+ lineSeparator = java.lang.System.getProperty("line.separator"),
+ input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
+ StringBuilder, line,
+ content = '';
+ try {
+ StringBuilder = new java.lang.StringBuilder();
+ line = input.readLine();
+
+ // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
+ // http://www.unicode.org/faq/utf_bom.html
+
+ // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
+ if (line && line.length() && line.charAt(0) === 0xfeff) {
+ // Eat the BOM, since we've already found the encoding on this file,
+ // and we plan to concatenating this buffer with others; the BOM should
+ // only appear at the top of a file.
+ line = line.substring(1);
+ }
+
+ StringBuilder.append(line);
+
+ while ((line = input.readLine()) !== null) {
+ StringBuilder.append(lineSeparator);
+ StringBuilder.append(line);
+ }
+ //Make sure we return a JavaScript string and not a Java string.
+ content = String(StringBuilder.toString()); //String
+ } finally {
+ input.close();
+ }
+ callback(content);
+ };
+ }
+
+ return text;
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/tmpl.min.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/tmpl.min.js
new file mode 100644
index 000000000..065532e7c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/tmpl.min.js
@@ -0,0 +1 @@
+(function(a){"use strict";var b=function(a,c){var d=/[^\w\-\.:]/.test(a)?new Function(b.arg+",tmpl","var _e=tmpl.encode"+b.helper+",_s='"+a.replace(b.regexp,b.func)+"';return _s;"):b.cache[a]=b.cache[a]||b(b.load(a));return c?d(c,b):function(a){return d(a,b)}};b.cache={},b.load=function(a){return document.getElementById(a).innerHTML},b.regexp=/([\s'\\])(?![^%]*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,b.func=function(a,b,c,d,e,f){if(b)return{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[a]||"\\"+a;if(c)return c==="="?"'+_e("+d+")+'":"'+("+d+"||'')+'";if(e)return"';";if(f)return"_s+='"},b.encReg=/[<>&"'\x00]/g,b.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},b.encode=function(a){return String(a||"").replace(b.encReg,function(a){return b.encMap[a]||""})},b.arg="o",b.helper=",print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=tmpl(s,d);}",typeof define=="function"&&define.amd?define(function(){return b}):a.tmpl=b})(this); \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/auto-admin-creation.properties b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/auto-admin-creation.properties
new file mode 100644
index 000000000..7c8c5815b
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/auto-admin-creation.properties
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+redback.admin.fullname=Archiva Admin
+redback.admin.email=admin@toto.com
+redback.admin.password=admin123 \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/log4j2-test.xml b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/log4j2-test.xml
new file mode 100644
index 000000000..5537a174f
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/log4j2-test.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+
+<configuration status="debug">
+
+ <properties>
+ <property name="logsDirectory">${sys:appserver.base}/logs</property>
+ </properties>
+
+ <appenders>
+ <Console name="console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+ </Console>
+
+ <!--RollingFile name="console" fileName="${logsDirectory}/archiva.log"
+ filePattern="${logsDirectory}/archiva-%d{MM-dd-yyyy}.log">
+ <PatternLayout>
+ <pattern>%d [%t] %-5p %c %x - %m%n</pattern>
+ </PatternLayout>
+ <Policies>
+ <TimeBasedTriggeringPolicy />
+ </Policies>
+ </RollingFile-->
+
+ </appenders>
+ <loggers>
+
+ <!-- apache httpclient debug content transfer-->
+ <!--
+ <logger name="org.apache.http.wire">
+ <level value="debug"/>
+ </logger>
+ <logger name="org.apache.http.headers" level="debug"/>
+ -->
+
+
+ <logger name="org.apache.archiva.indexer.search.MavenRepositorySearch" level="info"/>
+
+ <logger name="org.apache.archiva.common.plexusbridge.MavenIndexerUtils" level="info"/>
+
+ <logger name="JPOX" level="error"/>
+
+
+ <logger name="org.apache.commons.configuration.DefaultConfigurationBuilder" level="error"/>
+
+
+ <logger name="org.apache.archiva.admin.repository.managed" level="info"/>
+
+ <logger name="org.springframework" level="info"/>
+
+
+ <logger name="org.codehaus.plexus" level="info"/>
+
+
+ <logger name="org.codehaus.redback" level="info"/>
+
+
+ <logger name="org.apache.cxf" level="info"/>
+
+ <logger name="org.quartz" level="info"/>
+
+ <logger name="org.apache.archiva.indexer.merger" level="info"/>
+
+ <logger name="org.apache.archiva.metadata.repository.stats.DefaultRepositoryStatisticsManager" level="debug" />
+
+ <logger name="org.apache.archiva.scheduler.repository.DefaultRepositoryArchivaTaskScheduler" level="debug"/>
+
+ <root level="info">
+ <appender-ref ref="console"/>
+ </root>
+ </loggers>
+</configuration>
+
+
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/tomcat-context-archiva.xml b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/tomcat-context-archiva.xml
new file mode 100644
index 000000000..4f7ce1d69
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/test/tomcat/tomcat-context-archiva.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<Context path="/archiva">
+ <Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"
+ username="sa"
+ password=""
+ driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
+ url="jdbc:derby:${appserver.base}/database/users;create=true"
+ />
+ <Resource name="mail/Session" auth="Container"
+ type="javax.mail.Session"
+ mail.smtp.host="localhost"/>
+
+</Context>