Mercurial > hg > orthanc
changeset 57:4bc019d2f969 orthanc-renaming
renaming
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sun, 16 Sep 2012 09:22:48 +0200 |
parents | 088c4f23e2c8 |
children | 6da7fc87efaa |
files | AUTHORS CMakeLists.txt INSTALL NEWS OrthancCppClient/CMakeLists.txt OrthancCppClient/HttpClient.cpp OrthancCppClient/HttpClient.h OrthancCppClient/HttpEnumerations.h OrthancCppClient/HttpException.cpp OrthancCppClient/HttpException.h OrthancCppClient/main.cpp OrthancExplorer/explorer.css OrthancExplorer/explorer.html OrthancExplorer/explorer.js OrthancExplorer/file-upload.js OrthancExplorer/images/Unsupported.png OrthancExplorer/libs/date.js OrthancExplorer/libs/images/ajax-loader.gif OrthancExplorer/libs/images/ajax-loader.png OrthancExplorer/libs/images/ajax-loader2.gif OrthancExplorer/libs/images/icons-18-black.png OrthancExplorer/libs/images/icons-18-white.png OrthancExplorer/libs/images/icons-36-black.png OrthancExplorer/libs/images/icons-36-white.png OrthancExplorer/libs/jqm.page.params.js OrthancExplorer/libs/jqtree-icons.png OrthancExplorer/libs/jqtree.css OrthancExplorer/libs/jquery-1.7.2.min.js OrthancExplorer/libs/jquery-file-upload/css/jquery.fileupload-ui.css OrthancExplorer/libs/jquery-file-upload/css/style.css OrthancExplorer/libs/jquery-file-upload/img/loading.gif OrthancExplorer/libs/jquery-file-upload/img/progressbar.gif OrthancExplorer/libs/jquery-file-upload/js/cors/jquery.postmessage-transport.js OrthancExplorer/libs/jquery-file-upload/js/cors/jquery.xdr-transport.js OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload-fp.js OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload-ui.js OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload.js OrthancExplorer/libs/jquery-file-upload/js/jquery.iframe-transport.js OrthancExplorer/libs/jquery-file-upload/js/locale.js OrthancExplorer/libs/jquery-file-upload/js/vendor/jquery.ui.widget.js OrthancExplorer/libs/jquery.blockUI.js OrthancExplorer/libs/jquery.mobile-1.1.0.min.css OrthancExplorer/libs/jquery.mobile-1.1.0.min.js OrthancExplorer/libs/jquery.mobile.simpledialog.min.css OrthancExplorer/libs/jquery.mobile.simpledialog2.js OrthancExplorer/libs/jquery.mobile.structure-1.1.0.min.css OrthancExplorer/libs/jquery.mobile.theme-1.1.0.min.css OrthancExplorer/libs/slimbox2.js OrthancExplorer/libs/slimbox2/closelabel.gif OrthancExplorer/libs/slimbox2/loading.gif OrthancExplorer/libs/slimbox2/nextlabel.gif OrthancExplorer/libs/slimbox2/prevlabel.gif OrthancExplorer/libs/slimbox2/slimbox2-rtl.css OrthancExplorer/libs/slimbox2/slimbox2.css OrthancExplorer/libs/tree.jquery.js OrthancServer/DicomIntegerPixelAccessor.cpp OrthancServer/DicomIntegerPixelAccessor.h OrthancServer/DicomProtocol/DicomFindAnswers.cpp OrthancServer/DicomProtocol/DicomFindAnswers.h OrthancServer/DicomProtocol/DicomServer.cpp OrthancServer/DicomProtocol/DicomServer.h OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/DicomProtocol/DicomUserConnection.h OrthancServer/DicomProtocol/IApplicationEntityFilter.h OrthancServer/DicomProtocol/IFindRequestHandler.h OrthancServer/DicomProtocol/IFindRequestHandlerFactory.h OrthancServer/DicomProtocol/IMoveRequestHandler.h OrthancServer/DicomProtocol/IMoveRequestHandlerFactory.h OrthancServer/DicomProtocol/IStoreRequestHandler.h OrthancServer/DicomProtocol/IStoreRequestHandlerFactory.h OrthancServer/FromDcmtkBridge.cpp OrthancServer/FromDcmtkBridge.h OrthancServer/Internals/CommandDispatcher.cpp OrthancServer/Internals/CommandDispatcher.h OrthancServer/Internals/FindScp.cpp OrthancServer/Internals/FindScp.h OrthancServer/Internals/MoveScp.cpp OrthancServer/Internals/MoveScp.h OrthancServer/Internals/StoreScp.cpp OrthancServer/Internals/StoreScp.h OrthancServer/PalanthirInitialization.cpp OrthancServer/PalanthirInitialization.h OrthancServer/PalanthirRestApi.cpp OrthancServer/PalanthirRestApi.h OrthancServer/PrepareDatabase.sql OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h OrthancServer/ToDcmtkBridge.cpp OrthancServer/ToDcmtkBridge.h OrthancServer/main.cpp PalanthirCppClient/CMakeLists.txt PalanthirCppClient/HttpClient.cpp PalanthirCppClient/HttpClient.h PalanthirCppClient/HttpEnumerations.h PalanthirCppClient/HttpException.cpp PalanthirCppClient/HttpException.h PalanthirCppClient/main.cpp PalanthirExplorer/explorer.css PalanthirExplorer/explorer.html PalanthirExplorer/explorer.js PalanthirExplorer/file-upload.js PalanthirExplorer/images/Unsupported.png PalanthirExplorer/libs/date.js PalanthirExplorer/libs/images/ajax-loader.gif PalanthirExplorer/libs/images/ajax-loader.png PalanthirExplorer/libs/images/ajax-loader2.gif PalanthirExplorer/libs/images/icons-18-black.png PalanthirExplorer/libs/images/icons-18-white.png PalanthirExplorer/libs/images/icons-36-black.png PalanthirExplorer/libs/images/icons-36-white.png PalanthirExplorer/libs/jqm.page.params.js PalanthirExplorer/libs/jqtree-icons.png PalanthirExplorer/libs/jqtree.css PalanthirExplorer/libs/jquery-1.7.2.min.js PalanthirExplorer/libs/jquery-file-upload/css/jquery.fileupload-ui.css PalanthirExplorer/libs/jquery-file-upload/css/style.css PalanthirExplorer/libs/jquery-file-upload/img/loading.gif PalanthirExplorer/libs/jquery-file-upload/img/progressbar.gif PalanthirExplorer/libs/jquery-file-upload/js/cors/jquery.postmessage-transport.js PalanthirExplorer/libs/jquery-file-upload/js/cors/jquery.xdr-transport.js PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload-fp.js PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload-ui.js PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload.js PalanthirExplorer/libs/jquery-file-upload/js/jquery.iframe-transport.js PalanthirExplorer/libs/jquery-file-upload/js/locale.js PalanthirExplorer/libs/jquery-file-upload/js/vendor/jquery.ui.widget.js PalanthirExplorer/libs/jquery.blockUI.js PalanthirExplorer/libs/jquery.mobile-1.1.0.min.css PalanthirExplorer/libs/jquery.mobile-1.1.0.min.js PalanthirExplorer/libs/jquery.mobile.simpledialog.min.css PalanthirExplorer/libs/jquery.mobile.simpledialog2.js PalanthirExplorer/libs/jquery.mobile.structure-1.1.0.min.css PalanthirExplorer/libs/jquery.mobile.theme-1.1.0.min.css PalanthirExplorer/libs/slimbox2.js PalanthirExplorer/libs/slimbox2/closelabel.gif PalanthirExplorer/libs/slimbox2/loading.gif PalanthirExplorer/libs/slimbox2/nextlabel.gif PalanthirExplorer/libs/slimbox2/prevlabel.gif PalanthirExplorer/libs/slimbox2/slimbox2-rtl.css PalanthirExplorer/libs/slimbox2/slimbox2.css PalanthirExplorer/libs/tree.jquery.js PalanthirServer/DicomIntegerPixelAccessor.cpp PalanthirServer/DicomIntegerPixelAccessor.h PalanthirServer/DicomProtocol/DicomFindAnswers.cpp PalanthirServer/DicomProtocol/DicomFindAnswers.h PalanthirServer/DicomProtocol/DicomServer.cpp PalanthirServer/DicomProtocol/DicomServer.h PalanthirServer/DicomProtocol/DicomUserConnection.cpp PalanthirServer/DicomProtocol/DicomUserConnection.h PalanthirServer/DicomProtocol/IApplicationEntityFilter.h PalanthirServer/DicomProtocol/IFindRequestHandler.h PalanthirServer/DicomProtocol/IFindRequestHandlerFactory.h PalanthirServer/DicomProtocol/IMoveRequestHandler.h PalanthirServer/DicomProtocol/IMoveRequestHandlerFactory.h PalanthirServer/DicomProtocol/IStoreRequestHandler.h PalanthirServer/DicomProtocol/IStoreRequestHandlerFactory.h PalanthirServer/FromDcmtkBridge.cpp PalanthirServer/FromDcmtkBridge.h PalanthirServer/Internals/CommandDispatcher.cpp PalanthirServer/Internals/CommandDispatcher.h PalanthirServer/Internals/FindScp.cpp PalanthirServer/Internals/FindScp.h PalanthirServer/Internals/MoveScp.cpp PalanthirServer/Internals/MoveScp.h PalanthirServer/Internals/StoreScp.cpp PalanthirServer/Internals/StoreScp.h PalanthirServer/PalanthirInitialization.cpp PalanthirServer/PalanthirInitialization.h PalanthirServer/PalanthirRestApi.cpp PalanthirServer/PalanthirRestApi.h PalanthirServer/PrepareDatabase.sql PalanthirServer/ServerIndex.cpp PalanthirServer/ServerIndex.h PalanthirServer/ToDcmtkBridge.cpp PalanthirServer/ToDcmtkBridge.h PalanthirServer/main.cpp README THANKS |
diffstat | 178 files changed, 14554 insertions(+), 14558 deletions(-) [+] |
line wrap: on
line diff
--- a/AUTHORS Sun Sep 16 09:21:12 2012 +0200 +++ b/AUTHORS Sun Sep 16 09:22:48 2012 +0200 @@ -1,9 +1,9 @@ -Palanthir - A Lightweight, RESTful DICOM Server -=============================================== +Orthanc - A Lightweight, RESTful DICOM Server +============================================= -Authors of Palanthir --------------------- +Authors of Orthanc +------------------ * Sebastien Jodogne <s.jodogne@gmail.com> Department of Medical Physics, CHU of Liege, Belgium
--- a/CMakeLists.txt Sun Sep 16 09:21:12 2012 +0200 +++ b/CMakeLists.txt Sun Sep 16 09:22:48 2012 +0200 @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(Palanthir) +project(Orthanc) include(${CMAKE_SOURCE_DIR}/Resources/CMake/AutoGeneratedCode.cmake) include(${CMAKE_SOURCE_DIR}/Resources/CMake/DownloadPackage.cmake) include(CheckIncludeFiles) @@ -30,10 +30,10 @@ ) if (${ENABLE_SSL}) - add_definitions(-DPALANTHIR_SSL_ENABLED=1) + add_definitions(-DORTHANC_SSL_ENABLED=1) include(${CMAKE_SOURCE_DIR}/Resources/CMake/OpenSslConfiguration.cmake) else() - add_definitions(-DPALANTHIR_SSL_ENABLED=0) + add_definitions(-DORTHANC_SSL_ENABLED=0) endif() include(${CMAKE_SOURCE_DIR}/Resources/CMake/BoostConfiguration.cmake) @@ -98,29 +98,29 @@ if (${STATIC_BUILD}) - add_definitions(-DPALANTHIR_STATIC=1) + add_definitions(-DORTHANC_STATIC=1) else() - add_definitions(-DPALANTHIR_STATIC=0) + add_definitions(-DORTHANC_STATIC=0) endif() if (${STANDALONE_BUILD}) add_definitions( - -DPALANTHIR_STANDALONE=1 + -DORTHANC_STANDALONE=1 ) EmbedResources( - PREPARE_DATABASE PalanthirServer/PrepareDatabase.sql - PALANTHIR_EXPLORER PalanthirExplorer + PREPARE_DATABASE OrthancServer/PrepareDatabase.sql + ORTHANC_EXPLORER OrthancExplorer ) else() add_definitions( - -DPALANTHIR_STANDALONE=0 - -DPALANTHIR_PATH=\"${CMAKE_SOURCE_DIR}\" + -DORTHANC_STANDALONE=0 + -DORTHANC_PATH=\"${CMAKE_SOURCE_DIR}\" ) EmbedResources( - PREPARE_DATABASE PalanthirServer/PrepareDatabase.sql + PREPARE_DATABASE OrthancServer/PrepareDatabase.sql ) endif() @@ -133,7 +133,7 @@ Core/ChunkedBuffer.cpp Core/Compression/BufferCompressor.cpp Core/Compression/ZlibCompressor.cpp - Core/PalanthirException.cpp + Core/OrthancException.cpp Core/DicomFormat/DicomArray.cpp Core/DicomFormat/DicomMap.cpp Core/DicomFormat/DicomTag.cpp @@ -154,33 +154,33 @@ Core/Toolbox.cpp Core/Uuid.cpp - PalanthirCppClient/HttpClient.cpp - PalanthirCppClient/HttpException.cpp + OrthancCppClient/HttpClient.cpp + OrthancCppClient/HttpException.cpp ) add_library(ServerLibrary - PalanthirServer/DicomIntegerPixelAccessor.cpp - PalanthirServer/DicomProtocol/DicomFindAnswers.cpp - PalanthirServer/DicomProtocol/DicomServer.cpp - PalanthirServer/DicomProtocol/DicomUserConnection.cpp - PalanthirServer/FromDcmtkBridge.cpp - PalanthirServer/Internals/CommandDispatcher.cpp - PalanthirServer/Internals/FindScp.cpp - PalanthirServer/Internals/MoveScp.cpp - PalanthirServer/Internals/StoreScp.cpp - PalanthirServer/PalanthirInitialization.cpp - PalanthirServer/PalanthirRestApi.cpp - PalanthirServer/ServerIndex.cpp - PalanthirServer/ToDcmtkBridge.cpp - PalanthirServer/ToDcmtkBridge.cpp - PalanthirServer/DicomIntegerPixelAccessor.cpp + OrthancServer/DicomIntegerPixelAccessor.cpp + OrthancServer/DicomProtocol/DicomFindAnswers.cpp + OrthancServer/DicomProtocol/DicomServer.cpp + OrthancServer/DicomProtocol/DicomUserConnection.cpp + OrthancServer/FromDcmtkBridge.cpp + OrthancServer/Internals/CommandDispatcher.cpp + OrthancServer/Internals/FindScp.cpp + OrthancServer/Internals/MoveScp.cpp + OrthancServer/Internals/StoreScp.cpp + OrthancServer/OrthancInitialization.cpp + OrthancServer/OrthancRestApi.cpp + OrthancServer/ServerIndex.cpp + OrthancServer/ToDcmtkBridge.cpp + OrthancServer/ToDcmtkBridge.cpp + OrthancServer/DicomIntegerPixelAccessor.cpp ) # Ensure autogenerated code is built before building ServerLibrary add_dependencies(ServerLibrary CoreLibrary) -add_executable(Palanthir - PalanthirServer/main.cpp +add_executable(Orthanc + OrthancServer/main.cpp ) add_executable(UnitTests @@ -191,17 +191,17 @@ UnitTests/Versions.cpp ) -TARGET_LINK_LIBRARIES(Palanthir ServerLibrary CoreLibrary) +TARGET_LINK_LIBRARIES(Orthanc ServerLibrary CoreLibrary) TARGET_LINK_LIBRARIES(UnitTests ServerLibrary CoreLibrary) find_package(Doxygen) if (DOXYGEN_FOUND) configure_file( - ${CMAKE_SOURCE_DIR}/Resources/Palanthir.doxygen - ${CMAKE_CURRENT_BINARY_DIR}/Palanthir.doxygen + ${CMAKE_SOURCE_DIR}/Resources/Orthanc.doxygen + ${CMAKE_CURRENT_BINARY_DIR}/Orthanc.doxygen @ONLY) add_custom_target(doc - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Palanthir.doxygen + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Orthanc.doxygen WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM )
--- a/INSTALL Sun Sep 16 09:21:12 2012 +0200 +++ b/INSTALL Sun Sep 16 09:22:48 2012 +0200 @@ -1,12 +1,12 @@ -Palanthir - A Lightweight, RESTful DICOM Server -=============================================== +Orthanc - A Lightweight, RESTful DICOM Server +============================================= Dependencies ------------ -1) CMake: Palanthir uses CMake (http://www.cmake.org/) to automate its - building process. +1) CMake: Orthanc uses CMake (http://www.cmake.org/) to automate its + building process. 2) Python: Some code is autogenerated through Python (http://www.python.org/). @@ -26,17 +26,17 @@ "ThirdPartyDownloads" directory. -Building Palanthir at a glance ------------------------------- +Building Orthanc at a glance +---------------------------- -To build Palanthir, you must: +To build Orthanc, you must: 1) Download the source code (either using Mercurial, or through the released versions). For the examples below, we assume the source - directory is "~/Palanthir". + directory is "~/Orthanc". 2) Create a build directory. For the examples below, we assume the - build directory is "~/PalanthirBuild". + build directory is "~/OrthancBuild". @@ -45,26 +45,26 @@ To build binaries with debug information: -# cd ~/PalanthirBuild -# cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Palanthir +# cd ~/OrthancBuild +# cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Orthanc # make # make doc To build a release version: -# cd ~/PalanthirBuild -# cmake -DCMAKE_BUILD_TYPE=RELEASE ~/Palanthir +# cd ~/OrthancBuild +# cmake -DCMAKE_BUILD_TYPE=RELEASE ~/Orthanc # make # make doc -Under Linux, you have the possibility to dynamically link Palanthir +Under Linux, you have the possibility to dynamically link Orthanc against the shared libraries of your system, provided their version is recent enough. This greatly speeds up the compilation: -# cd ~/PalanthirBuild -# cmake -DSTATIC_BUILD=OFF -DCMAKE_BUILD_TYPE=DEBUG ~/Palanthir +# cd ~/OrthancBuild +# cmake -DSTATIC_BUILD=OFF -DCMAKE_BUILD_TYPE=DEBUG ~/Orthanc # make @@ -75,8 +75,8 @@ To cross-compile Windows binaries under Linux using MinGW, please use the following command: -# cd ~/PalanthirBuild -# cmake -DCMAKE_TOOLCHAIN_FILE=~/Palanthir/Resources/MinGWToolchain.cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Palanthir +# cd ~/OrthancBuild +# cmake -DCMAKE_TOOLCHAIN_FILE=~/Orthanc/Resources/MinGWToolchain.cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Orthanc # make @@ -84,8 +84,8 @@ Native Windows build with MinGW (VERY SLOW) ------------------------------------------- -# cd [...]\PalanthirBuild -# cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=DEBUG [...]\Palanthir +# cd [...]\OrthancBuild +# cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=DEBUG [...]\Orthanc # mingw32-make @@ -93,10 +93,10 @@ Native Windows build with Microsoft Visual Studio 2005 ------------------------------------------------------ -# cd [...]\PalanthirBuild -# cmake -G "Visual Studio 8 2005" [...]\Palanthir +# cd [...]\OrthancBuild +# cmake -G "Visual Studio 8 2005" [...]\Orthanc -Then open the "[...]/PalanthirBuild/Palanthir.sln" with Visual Studio. +Then open the "[...]/OrthancBuild/Orthanc.sln" with Visual Studio. NOTES: * More recent versions of Visual Studio should also work.
--- a/NEWS Sun Sep 16 09:21:12 2012 +0200 +++ b/NEWS Sun Sep 16 09:22:48 2012 +0200 @@ -1,7 +1,7 @@ Pending changes =============== -* Renaming to "Palanthir" +* Renaming to "Orthanc" * Access to multi-frame images * Access to the raw PNG images (in 8bpp and 16bpp) * Security: Support of SSL, HTTP Basic Authentication and interdiction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/CMakeLists.txt Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,35 @@ +# Mini-project to check whether "PalanthirCppClient" can compile in a +# standalone fashion + +cmake_minimum_required(VERSION 2.8) + +project(PalanthirCppClientTest) + +SET(STATIC_BUILD OFF) + +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DownloadPackage.cmake) +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/JsonCppConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/LibCurlConfiguration.cmake) + +if (${CMAKE_COMPILER_IS_GNUCXX}) + set(CMAKE_C_FLAGS "-Wall -pedantic -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile + set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wno-long-long -Wno-variadic-macros") + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") +elseif (${MSVC}) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) +endif() + +add_library(PalanthirCppClient + SHARED + + ${THIRD_PARTY_SOURCES} + HttpException.cpp + HttpClient.cpp + ) + +add_executable(Test + main.cpp + ) + +target_link_libraries(Test PalanthirCppClient)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/HttpClient.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,200 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpClient.h" + +#include <string.h> +#include <curl/curl.h> + + +namespace Palanthir +{ + struct HttpClient::PImpl + { + CURL* curl_; + struct curl_slist *postHeaders_; + }; + + + static CURLcode CheckCode(CURLcode code) + { + if (code != CURLE_OK) + { + printf("ICI: %s\n", curl_easy_strerror(code)); + throw HttpException("CURL: " + std::string(curl_easy_strerror(code))); + } + + return code; + } + + + static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *payload) + { + std::string& target = *(static_cast<std::string*>(payload)); + + size_t length = size * nmemb; + if (length == 0) + return 0; + + size_t pos = target.size(); + + target.resize(pos + length); + memcpy(&target.at(pos), buffer, length); + + return length; + } + + + HttpClient::HttpClient() : pimpl_(new PImpl) + { + pimpl_->postHeaders_ = NULL; + if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL) + { + throw HttpException("HttpClient: Not enough memory"); + } + + pimpl_->curl_ = curl_easy_init(); + if (!pimpl_->curl_) + { + curl_slist_free_all(pimpl_->postHeaders_); + throw HttpException("HttpClient: Not enough memory"); + } + + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1)); + +#if PALANTHIR_SSL_ENABLED == 1 + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); +#endif + + url_ = ""; + method_ = Palanthir_HttpMethod_Get; + lastStatus_ = Palanthir_HttpStatus_200_Ok; + isVerbose_ = false; + } + + + HttpClient::~HttpClient() + { + curl_easy_cleanup(pimpl_->curl_); + curl_slist_free_all(pimpl_->postHeaders_); + } + + + void HttpClient::SetVerbose(bool isVerbose) + { + isVerbose_ = isVerbose; + + if (isVerbose_) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1)); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0)); + } + } + + + bool HttpClient::Apply(std::string& answer) + { + answer.clear(); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, NULL)); + + switch (method_) + { + case Palanthir_HttpMethod_Get: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L)); + break; + + case Palanthir_HttpMethod_Post: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->postHeaders_)); + + if (postData_.size() > 0) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, postData_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, postData_.size())); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0)); + } + + break; + + case Palanthir_HttpMethod_Delete: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE")); + break; + + case Palanthir_HttpMethod_Put: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L)); + break; + + default: + throw HttpException("HttpClient: Internal error"); + } + + // Do the actual request + CheckCode(curl_easy_perform(pimpl_->curl_)); + + long status; + CheckCode(curl_easy_getinfo(pimpl_->curl_, CURLINFO_RESPONSE_CODE, &status)); + + if (status == 0) + { + // This corresponds to a call to an inexistent host + lastStatus_ = Palanthir_HttpStatus_500_InternalServerError; + } + else + { + lastStatus_ = static_cast<Palanthir_HttpStatus>(status); + } + + return (status >= 200 && status < 300); + } + + + bool HttpClient::Apply(Json::Value& answer) + { + std::string s; + if (Apply(s)) + { + Json::Reader reader; + return reader.parse(s, answer); + } + else + { + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/HttpClient.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,113 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + +#include "HttpEnumerations.h" +#include "HttpException.h" + +#include <string> +#include <boost/shared_ptr.hpp> +#include <json/json.h> + +namespace Palanthir +{ + class HttpClient + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + std::string url_; + Palanthir_HttpMethod method_; + Palanthir_HttpStatus lastStatus_; + std::string postData_; + bool isVerbose_; + + public: + HttpClient(); + + ~HttpClient(); + + void SetUrl(const char* url) + { + url_ = std::string(url); + } + + void SetUrl(const std::string& url) + { + url_ = url; + } + + const std::string& GetUrl() const + { + return url_; + } + + void SetMethod(Palanthir_HttpMethod method) + { + method_ = method; + } + + Palanthir_HttpMethod GetMethod() const + { + return method_; + } + + std::string& AccessPostData() + { + return postData_; + } + + const std::string& AccessPostData() const + { + return postData_; + } + + void SetVerbose(bool isVerbose); + + bool IsVerbose() const + { + return isVerbose_; + } + + bool Apply(std::string& answer); + + bool Apply(Json::Value& answer); + + Palanthir_HttpStatus GetLastStatus() const + { + return lastStatus_; + } + + const char* GetLastStatusText() const + { + return HttpException::GetDescription(lastStatus_); + } + + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/HttpEnumerations.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,113 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + + +/** + * This file contains the enumerations for the access to the Palanthir + * REST API in C and C++. Namespaces are not used, in order to enable + * the access in C. + **/ + +// Most common, non-joke and non-experimental HTTP status codes +// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes +enum Palanthir_HttpStatus +{ + Palanthir_HttpStatus_None = -1, + + // 1xx Informational + Palanthir_HttpStatus_100_Continue = 100, + Palanthir_HttpStatus_101_SwitchingProtocols = 101, + Palanthir_HttpStatus_102_Processing = 102, + + // 2xx Success + Palanthir_HttpStatus_200_Ok = 200, + Palanthir_HttpStatus_201_Created = 201, + Palanthir_HttpStatus_202_Accepted = 202, + Palanthir_HttpStatus_203_NonAuthoritativeInformation = 203, + Palanthir_HttpStatus_204_NoContent = 204, + Palanthir_HttpStatus_205_ResetContent = 205, + Palanthir_HttpStatus_206_PartialContent = 206, + Palanthir_HttpStatus_207_MultiStatus = 207, + Palanthir_HttpStatus_208_AlreadyReported = 208, + Palanthir_HttpStatus_226_IMUsed = 226, + + // 3xx Redirection + Palanthir_HttpStatus_300_MultipleChoices = 300, + Palanthir_HttpStatus_301_MovedPermanently = 301, + Palanthir_HttpStatus_302_Found = 302, + Palanthir_HttpStatus_303_SeeOther = 303, + Palanthir_HttpStatus_304_NotModified = 304, + Palanthir_HttpStatus_305_UseProxy = 305, + Palanthir_HttpStatus_307_TemporaryRedirect = 307, + + // 4xx Client Error + Palanthir_HttpStatus_400_BadRequest = 400, + Palanthir_HttpStatus_401_Unauthorized = 401, + Palanthir_HttpStatus_402_PaymentRequired = 402, + Palanthir_HttpStatus_403_Forbidden = 403, + Palanthir_HttpStatus_404_NotFound = 404, + Palanthir_HttpStatus_405_MethodNotAllowed = 405, + Palanthir_HttpStatus_406_NotAcceptable = 406, + Palanthir_HttpStatus_407_ProxyAuthenticationRequired = 407, + Palanthir_HttpStatus_408_RequestTimeout = 408, + Palanthir_HttpStatus_409_Conflict = 409, + Palanthir_HttpStatus_410_Gone = 410, + Palanthir_HttpStatus_411_LengthRequired = 411, + Palanthir_HttpStatus_412_PreconditionFailed = 412, + Palanthir_HttpStatus_413_RequestEntityTooLarge = 413, + Palanthir_HttpStatus_414_RequestUriTooLong = 414, + Palanthir_HttpStatus_415_UnsupportedMediaType = 415, + Palanthir_HttpStatus_416_RequestedRangeNotSatisfiable = 416, + Palanthir_HttpStatus_417_ExpectationFailed = 417, + Palanthir_HttpStatus_422_UnprocessableEntity = 422, + Palanthir_HttpStatus_423_Locked = 423, + Palanthir_HttpStatus_424_FailedDependency = 424, + Palanthir_HttpStatus_426_UpgradeRequired = 426, + + // 5xx Server Error + Palanthir_HttpStatus_500_InternalServerError = 500, + Palanthir_HttpStatus_501_NotImplemented = 501, + Palanthir_HttpStatus_502_BadGateway = 502, + Palanthir_HttpStatus_503_ServiceUnavailable = 503, + Palanthir_HttpStatus_504_GatewayTimeout = 504, + Palanthir_HttpStatus_505_HttpVersionNotSupported = 505, + Palanthir_HttpStatus_506_VariantAlsoNegotiates = 506, + Palanthir_HttpStatus_507_InsufficientStorage = 507, + Palanthir_HttpStatus_509_BandwidthLimitExceeded = 509, + Palanthir_HttpStatus_510_NotExtended = 510 +}; + + +enum Palanthir_HttpMethod +{ + Palanthir_HttpMethod_Get = 0, + Palanthir_HttpMethod_Post = 1, + Palanthir_HttpMethod_Delete = 2, + Palanthir_HttpMethod_Put = 3 +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/HttpException.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,208 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpException.h" + +namespace Palanthir +{ + const char* HttpException::What() const + { + if (status_ == Palanthir_HttpStatus_None) + { + return custom_.c_str(); + } + else + { + return GetDescription(status_); + } + } + + const char* HttpException::GetDescription(Palanthir_HttpStatus status) + { + switch (status) + { + case Palanthir_HttpStatus_100_Continue: + return "Continue"; + + case Palanthir_HttpStatus_101_SwitchingProtocols: + return "Switching Protocols"; + + case Palanthir_HttpStatus_102_Processing: + return "Processing"; + + case Palanthir_HttpStatus_200_Ok: + return "OK"; + + case Palanthir_HttpStatus_201_Created: + return "Created"; + + case Palanthir_HttpStatus_202_Accepted: + return "Accepted"; + + case Palanthir_HttpStatus_203_NonAuthoritativeInformation: + return "Non-Authoritative Information"; + + case Palanthir_HttpStatus_204_NoContent: + return "No Content"; + + case Palanthir_HttpStatus_205_ResetContent: + return "Reset Content"; + + case Palanthir_HttpStatus_206_PartialContent: + return "Partial Content"; + + case Palanthir_HttpStatus_207_MultiStatus: + return "Multi-Status"; + + case Palanthir_HttpStatus_208_AlreadyReported: + return "Already Reported"; + + case Palanthir_HttpStatus_226_IMUsed: + return "IM Used"; + + case Palanthir_HttpStatus_300_MultipleChoices: + return "Multiple Choices"; + + case Palanthir_HttpStatus_301_MovedPermanently: + return "Moved Permanently"; + + case Palanthir_HttpStatus_302_Found: + return "Found"; + + case Palanthir_HttpStatus_303_SeeOther: + return "See Other"; + + case Palanthir_HttpStatus_304_NotModified: + return "Not Modified"; + + case Palanthir_HttpStatus_305_UseProxy: + return "Use Proxy"; + + case Palanthir_HttpStatus_307_TemporaryRedirect: + return "Temporary Redirect"; + + case Palanthir_HttpStatus_400_BadRequest: + return "Bad Request"; + + case Palanthir_HttpStatus_401_Unauthorized: + return "Unauthorized"; + + case Palanthir_HttpStatus_402_PaymentRequired: + return "Payment Required"; + + case Palanthir_HttpStatus_403_Forbidden: + return "Forbidden"; + + case Palanthir_HttpStatus_404_NotFound: + return "Not Found"; + + case Palanthir_HttpStatus_405_MethodNotAllowed: + return "Method Not Allowed"; + + case Palanthir_HttpStatus_406_NotAcceptable: + return "Not Acceptable"; + + case Palanthir_HttpStatus_407_ProxyAuthenticationRequired: + return "Proxy Authentication Required"; + + case Palanthir_HttpStatus_408_RequestTimeout: + return "Request Timeout"; + + case Palanthir_HttpStatus_409_Conflict: + return "Conflict"; + + case Palanthir_HttpStatus_410_Gone: + return "Gone"; + + case Palanthir_HttpStatus_411_LengthRequired: + return "Length Required"; + + case Palanthir_HttpStatus_412_PreconditionFailed: + return "Precondition Failed"; + + case Palanthir_HttpStatus_413_RequestEntityTooLarge: + return "Request Entity Too Large"; + + case Palanthir_HttpStatus_414_RequestUriTooLong: + return "Request-URI Too Long"; + + case Palanthir_HttpStatus_415_UnsupportedMediaType: + return "Unsupported Media Type"; + + case Palanthir_HttpStatus_416_RequestedRangeNotSatisfiable: + return "Requested Range Not Satisfiable"; + + case Palanthir_HttpStatus_417_ExpectationFailed: + return "Expectation Failed"; + + case Palanthir_HttpStatus_422_UnprocessableEntity: + return "Unprocessable Entity"; + + case Palanthir_HttpStatus_423_Locked: + return "Locked"; + + case Palanthir_HttpStatus_424_FailedDependency: + return "Failed Dependency"; + + case Palanthir_HttpStatus_426_UpgradeRequired: + return "Upgrade Required"; + + case Palanthir_HttpStatus_500_InternalServerError: + return "Internal Server Error"; + + case Palanthir_HttpStatus_501_NotImplemented: + return "Not Implemented"; + + case Palanthir_HttpStatus_502_BadGateway: + return "Bad Gateway"; + + case Palanthir_HttpStatus_503_ServiceUnavailable: + return "Service Unavailable"; + + case Palanthir_HttpStatus_504_GatewayTimeout: + return "Gateway Timeout"; + + case Palanthir_HttpStatus_505_HttpVersionNotSupported: + return "HTTP Version Not Supported"; + + case Palanthir_HttpStatus_506_VariantAlsoNegotiates: + return "Variant Also Negotiates"; + + case Palanthir_HttpStatus_507_InsufficientStorage: + return "Insufficient Storage"; + + case Palanthir_HttpStatus_509_BandwidthLimitExceeded: + return "Bandwidth Limit Exceeded"; + + case Palanthir_HttpStatus_510_NotExtended: + return "Not Extended"; + + default: + throw HttpException("Unknown HTTP status"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/HttpException.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,63 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + +#include "HttpEnumerations.h" + +#include <string> + +namespace Palanthir +{ + class HttpException + { + private: + Palanthir_HttpStatus status_; + std::string custom_; + + public: + static const char* GetDescription(Palanthir_HttpStatus status); + + HttpException(const std::string& custom) + { + status_ = Palanthir_HttpStatus_None; + custom_ = custom; + } + + HttpException(Palanthir_HttpStatus status) + { + status_ = status; + } + + Palanthir_HttpStatus GetHttpStatus() const + { + return status_; + } + + const char* What() const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/main.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,46 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpClient.h" + +#include <iostream> + +int main() +{ + // Prepare a simple call to a Web service + Palanthir::HttpClient c; + c.SetUrl("http://nominatim.openstreetmap.org/search?format=json&q=chu+liege+belgium"); + + // Do the request and store the result in a JSON structure + Json::Value result; + c.Apply(result); + + // Display the JSON answer + std::cout << result << std::endl; + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/explorer.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,34 @@ +ul.tree ul { + margin-left: 36px; +} + +#progress { + position: relative; + /*height: 2em; */ + width: 100%; + background-color: grey; + height: 2.5em; +} + +#progress .label { + z-index: 10; + position: absolute; + left:0; + top: 0; + width: 100%; + font-weight: bold; + text-align: center; + text-shadow: none; + padding: .5em; + color: white; +} + +#progress .bar { + z-index: 0; + position: absolute; + left:0; + top: 0; + height: 100%; + width: 0%; + background-color: green; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/explorer.html Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,201 @@ +<!DOCTYPE html> + +<html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Palanthir Explorer</title> + + <link rel="stylesheet" href="libs/jquery.mobile-1.1.0.min.css" /> + <link rel="stylesheet" href="libs/jqtree.css" /> + <link rel="stylesheet" href="libs/jquery.mobile.simpledialog.min.css" /> + <link rel="stylesheet" href="libs/jquery-file-upload/css/style.css" /> + <link rel="stylesheet" href="libs/jquery-file-upload/css/jquery.fileupload-ui.css" /> + <link rel="stylesheet" href="libs/slimbox2/slimbox2.css" /> + + <script src="libs/jquery-1.7.2.min.js"></script> + <script src="libs/jquery.mobile-1.1.0.min.js"></script> + <script src="libs/jqm.page.params.js"></script> + <script src="libs/tree.jquery.js"></script> + <script src="libs/date.js"></script> + <script src="libs/jquery.mobile.simpledialog2.js"></script> + <script src="libs/slimbox2.js"></script> + <script src="libs/jquery.blockUI.js"></script> + + <!-- https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin --> + <script src="libs/jquery-file-upload/js/vendor/jquery.ui.widget.js"></script> + <script src="libs/jquery-file-upload/js/jquery.iframe-transport.js"></script> + <script src="libs/jquery-file-upload/js/jquery.fileupload.js"></script> + + <link rel="stylesheet" href="explorer.css" /> + <script src="file-upload.js"></script> + <script src="explorer.js"></script> + </head> + <body> + <div data-role="page" id="find-patients" > + <div data-role="header" > + <h1>Find a patient</h1> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <ul id="all-patients" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + + <div data-role="page" id="upload" > + <div data-role="header" > + <h1>Upload DICOM files</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + </div> + <div data-role="content"> + <div style="display:none"> + <input id="fileupload" type="file" name="files[]" data-url="/instances/" multiple> + </div> + <p> + <ul data-role="listview" data-inset="true"> + <li data-icon="arrow-r" data-theme="e"><a href="#" id="upload-button">Start the upload</a></li> + <!--li data-icon="gear" data-theme="e"><a href="#" id="upload-abort" class="ui-disabled">Abort the current upload</a></li--> + <li data-icon="delete" data-theme="e"><a href="#" id="upload-clear">Clear the pending uploads</a></li> + </ul> + <div id="progress" class="ui-corner-all"> + <span class="bar ui-corner-all"></span> + <div class="label"></div> + </div> + </p> + <ul id="upload-list" data-role="listview" data-inset="true"> + <li data-role="list-divider">Drag and drop DICOM files here</li> + </ul> + </div> + </div> + + <div data-role="page" id="patient" > + <div data-role="header" > + <h1>List of the studies of one patient</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="patient-info"> + </ul> + <p> + <a href="#find-patients" data-role="button" data-icon="search">Go to patient finder</a> + <a href="#" data-role="button" data-icon="delete" id="patient-delete">Delete this patient</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-studies" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="study"> + <div data-role="header"> + <h1>List of the series of one study</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="study-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="study-delete">Delete this study</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-series" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="series"> + <div data-role="header"> + <h1>List of the instances of one series</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="series-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="series-delete">Delete this series</a> + <a href="#" data-role="button" data-icon="arrow-d" id="series-preview">Preview this series</a> + <a href="#" data-role="button" data-icon="arrow-d" id="series-store">Store in another DICOM modality</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-instances" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="instance"> + <div data-role="header"> + <h1>One DICOM instance</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="instance-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="instance-delete">Delete this instance</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-dicom">Download the DICOM file</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-json">Download the JSON file</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-preview">Preview the instance</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-store">Store in another DICOM modality</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <div class="ui-body ui-body-b"> + <h1>DICOM Tags</h1> + <p align="right"> + <input type="checkbox" id="show-tag-name" checked="checked" class="custom" data-mini="true" /> + <label for="show-tag-name">Show tag description</label> + </p> + <div id="dicom-tree"></div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div id="loading" style="display:none;" class="ui-body-c"> + <p align="center"><b>Sending to DICOM modality...</b></p> + <p><img src="libs/images/ajax-loader2.gif" alt="" /></p> + </div> + + <div id="dialog" style="display:none" > + </div> + </body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/explorer.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,729 @@ +// http://stackoverflow.com/questions/1663741/is-there-a-good-jquery-drag-and-drop-file-upload-plugin + + +// Forbid the access to IE +if ($.browser.msie) +{ + alert("Please use Mozilla Firefox or Google Chrome. Microsoft Internet Explorer is not supported."); +} + +// http://jquerymobile.com/demos/1.1.0/docs/api/globalconfig.html +//$.mobile.ajaxEnabled = false; +//$.mobile.page.prototype.options.addBackBtn = true; +//$.mobile.defaultPageTransition = 'slide'; + +// http://stackoverflow.com/a/4673436 +String.prototype.format = function() { + var args = arguments; + return this.replace(/{(\d+)}/g, function(match, number) { + /*return typeof args[number] != 'undefined' + ? args[number] + : match;*/ + + return args[number]; + }); +}; + + +$(document).ready(function() { + var $tree = $('#dicom-tree'); + $tree.tree({ + autoEscape: false + }); + + $('#dicom-tree').bind( + 'tree.click', + function(event) { + if (event.node.is_open) + $tree.tree('closeNode', event.node, true); + else + $tree.tree('openNode', event.node, true); + } + ); +}); + + +function SplitLongUid(s) +{ + return '<span>' + s.substr(0, s.length / 2) + '</span> <span>' + s.substr(s.length / 2, s.length - s.length / 2) + '</span>'; +} + + +function ParseDicomDate(s) +{ + y = parseInt(s.substr(0, 4), 10); + m = parseInt(s.substr(4, 2), 10) - 1; + d = parseInt(s.substr(6, 2), 10); + + if (y == null || m == null || d == null || + !isFinite(y) || !isFinite(m) || !isFinite(d)) + { + return null; + } + + if (y < 1900 || y > 2100 || + m < 0 || m >= 12 || + d <= 0 || d >= 32) + { + return null; + } + + return new Date(y, m, d); +} + + +function FormatDicomDate(s) +{ + if (s == undefined) + return "No date"; + + var d = ParseDicomDate(s); + if (d == null) + return '?'; + else + return d.toString('dddd, MMMM d, yyyy'); +} + + + +function SortOnDicomTag(arr, tag, isInteger, reverse) +{ + var defaultValue; + if (isInteger) + defaultValue = 0; + else + defaultValue = ''; + + arr.sort(function(a, b) { + var ta = a.MainDicomTags[tag]; + var tb = b.MainDicomTags[tag]; + var order; + + if (ta == undefined) + ta = defaultValue; + + if (tb == undefined) + tb = defaultValue; + + if (isInteger) + { + ta = parseInt(ta, 10); + tb = parseInt(tb, 10); + order = ta - tb; + } + else + { + if (ta < tb) + order = -1; + else if (ta > tb) + order = 1; + else + order = 0; + } + + if (reverse) + return -order; + else + return order; + }); +} + + + +function GetSingleResource(type, uuid, callback) +{ + var resource = null; + $.ajax({ + url: '/' + type + '/' + uuid, + dataType: 'json', + async: false, + success: function(s) { + callback(s); + } + }); +} + + +function GetMultipleResources(type, uuids, callback) +{ + if (uuids == null) + { + $.ajax({ + url: '/' + type, + dataType: 'json', + async: false, + success: function(s) { + uuids = s; + } + }); + } + + var resources = []; + var ajaxRequests = uuids.map(function(uuid) { + return $.ajax({ + url: '/' + type + '/' + uuid, + dataType: 'json', + async: true, + success: function(s) { + resources.push(s); + } + }); + }); + + // Wait for all the AJAX requests to end + $.when.apply($, ajaxRequests).then(function() { + callback(resources); + }); +} + + + +function CompleteFormatting(s, link, isReverse) +{ + if (link != null) + { + s = 'href="' + link + '">' + s + '</a>'; + + if (isReverse) + s = 'data-direction="reverse" '+ s; + + s = '<a ' + s; + } + + if (isReverse) + return '<li data-icon="back">' + s + '</li>'; + else + return '<li>' + s + '</li>'; +} + + +function FormatMainDicomTags(tags, tagsToIgnore) +{ + var s = ''; + + for (var i in tags) + { + if (tagsToIgnore.indexOf(i) == -1) + { + var v = tags[i]; + + if (i == "PatientBirthDate" || + i == "StudyDate" || + i == "SeriesDate") + { + v = FormatDicomDate(v); + } + else if (i == "DicomStudyInstanceUID" || + i == "DicomSeriesInstanceUID") + { + v = SplitLongUid(v); + } + + + s += ('<p>{0}: <strong>{1}</strong></p>').format(i, v); + } + } + + return s; +} + + +function FormatPatient(patient, link, isReverse) +{ + var s = ('<h3>{0}</h3>{1}' + + '<span class="ui-li-count">{2}</span>' + ).format + (patient.MainDicomTags.PatientName, + FormatMainDicomTags(patient.MainDicomTags, [ + "PatientName", + "OtherPatientIDs" + ]), + patient.Studies.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + + +function FormatStudy(study, link, isReverse) +{ + var s = ('<h3>{0}</h3>{1}' + + '<span class="ui-li-count">{2}</span>' + ).format + (study.MainDicomTags.StudyDescription, + FormatMainDicomTags(study.MainDicomTags, [ + "StudyDescription", + "StudyTime" + ]), + study.Series.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + + +function FormatSeries(series, link, isReverse) +{ + var s = ('<h3>{0}</h3>{1}' + + '<span class="ui-li-count">{2}</span>').format + (series.MainDicomTags.SeriesDescription, + FormatMainDicomTags(series.MainDicomTags, [ + "SeriesDescription", + "SeriesTime", + "Manufacturer", + "ImagesInAcquisition", + "SeriesDate" + ]), + series.Instances.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + +function FormatInstance(instance, link, isReverse) +{ + var s = ('<h3>Instance {0}</h3>{1}').format + (instance.MainDicomTags.InstanceNumber, + FormatMainDicomTags(instance.MainDicomTags, [ + "AcquisitionNumber", + "InstanceNumber", + "InstanceCreationDate", + "InstanceCreationTime" + ]) + ); + + return CompleteFormatting(s, link, isReverse); +} + + + + +$('#find-patients').live('pagebeforeshow', function() { + GetMultipleResources('patients', null, function(patients) { + var target = $('#all-patients'); + $('li', target).remove(); + + SortOnDicomTag(patients, 'PatientName', false, false); + + for (var i = 0; i < patients.length; i++) { + var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID); + target.append(p); + } + + target.listview('refresh'); + }); +}); + + + +$('#patient').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('patients', $.mobile.pageData.uuid, function(patient) { + GetMultipleResources('studies', patient.Studies, function(studies) { + SortOnDicomTag(studies, 'StudyDate', false, true); + + $('#patient-info li').remove(); + $('#patient-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient)) + .listview('refresh'); + + var target = $('#list-studies'); + $('li', target).remove(); + + for (var i = 0; i < studies.length; i++) { + if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate) + { + target.append('<li data-role="list-divider">{0}</li>'.format + (FormatDicomDate(studies[i].MainDicomTags.StudyDate))); + } + + target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID)); + } + + target.listview('refresh'); + }); + }); + } +}); + + +$('#study').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('studies', $.mobile.pageData.uuid, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + GetMultipleResources('series', study.Series, function(series) { + SortOnDicomTag(series, 'SeriesDate', false, true); + + $('#study-info li').remove(); + $('#study-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study)) + .listview('refresh'); + + var target = $('#list-series'); + $('li', target).remove(); + for (var i = 0; i < series.length; i++) { + if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate) + { + target.append('<li data-role="list-divider">{0}</li>'.format + (FormatDicomDate(series[i].MainDicomTags.SeriesDate))); + } + target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID)); + } + target.listview('refresh'); + }); + }); + }); + } +}); + + +$('#series').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('series', $.mobile.pageData.uuid, function(series) { + GetSingleResource('studies', series.ParentStudy, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + GetMultipleResources('instances', series.Instances, function(instances) { + SortOnDicomTag(instances, 'InstanceNumber', true, false); + + $('#series-info li').remove(); + $('#series-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) + .append('<li data-role="list-divider">Series</li>') + .append(FormatSeries(series)) + .listview('refresh'); + + var target = $('#list-instances'); + $('li', target).remove(); + for (var i = 0; i < instances.length; i++) { + target.append(FormatInstance(instances[i], '#instance?uuid=' + instances[i].ID)); + } + target.listview('refresh'); + }); + }); + }); + }); + } +}); + + + +function ConvertForTree(dicom) +{ + var result = []; + + for (var i in dicom) { + if (dicom[i] != null) { + var label = i + '<span class="tag-name"> (<i>' + dicom[i]["Name"] + '</i>)</span>: '; + + if (dicom[i]["Type"] == 'String') + { + result.push({ + label: label + '<strong>' + dicom[i]["Value"] + '</strong>', + children: [] + }); + } + else if (dicom[i]["Type"] == 'TooLong') + { + result.push({ + label: label + '<i>Too long</i>', + children: [] + }); + } + else if (dicom[i]["Type"] == 'Null') + { + result.push({ + label: label + '<i>Null</i>', + children: [] + }); + } + else if (dicom[i]["Type"] == 'Sequence') + { + var c = []; + for (var j = 0; j < dicom[i]["Value"].length; j++) { + c.push({ + label: 'Item ' + j, + children: ConvertForTree(dicom[i]["Value"][j]) + }); + } + + result.push({ + label: label + '[]', + children: c + }); + } + } + } + + return result; +} + + +$('#instance').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('instances', $.mobile.pageData.uuid, function(instance) { + GetSingleResource('series', instance.ParentSeries, function(series) { + GetSingleResource('studies', series.ParentStudy, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + + $('#instance-info li').remove(); + $('#instance-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) + .append('<li data-role="list-divider">Series</li>') + .append(FormatSeries(series, '#series?uuid=' + series.ID, true)) + .append('<li data-role="list-divider">Instance</li>') + .append(FormatInstance(instance)) + .listview('refresh'); + + $.ajax({ + url: '/instances/' + instance.ID + '/tags', + dataType: 'json', + success: function(s) { + $('#dicom-tree').tree('loadData', ConvertForTree(s)); + } + }); + + }); + }); + }); + }); + } +}); + + + +function DeleteResource(path) +{ + $.ajax({ + url: path, + type: 'DELETE', + dataType: 'json', + async: false, + success: function(s) { + var ancestor = s.RemainingAncestor; + if (ancestor == null) + $.mobile.changePage('#find-patients'); + else + $.mobile.changePage('#' + ancestor.Type + '?uuid=' + ancestor.ID); + } + }); +} + + + +function OpenDeleteResourceDialog(path, title) +{ + $(document).simpledialog2({ + // http://dev.jtsage.com/jQM-SimpleDialog/demos2/ + // http://dev.jtsage.com/jQM-SimpleDialog/demos2/options.html + mode: 'button', + animate: false, + headerText: title, + headerClose: true, + width: '500px', + buttons : { + 'OK': { + click: function () { + DeleteResource(path); + }, + icon: "delete", + theme: "c" + }, + 'Cancel': { + click: function () { + } + } + } + }); +} + + + +$('#instance-delete').live('click', function() { + OpenDeleteResourceDialog('/instances/' + $.mobile.pageData.uuid, + 'Delete this instance?'); +}); + +$('#study-delete').live('click', function() { + OpenDeleteResourceDialog('/studies/' + $.mobile.pageData.uuid, + 'Delete this study?'); +}); + +$('#series-delete').live('click', function() { + OpenDeleteResourceDialog('/series/' + $.mobile.pageData.uuid, + 'Delete this series?'); +}); + +$('#patient-delete').live('click', function() { + OpenDeleteResourceDialog('/patients/' + $.mobile.pageData.uuid, + 'Delete this patient?'); +}); + + +$('#instance-download-dicom').live('click', function(e) { + // http://stackoverflow.com/a/1296101 + e.preventDefault(); //stop the browser from following + window.location.href = '/instances/' + $.mobile.pageData.uuid + '/file'; +}); + +$('#instance-download-json').live('click', function(e) { + // http://stackoverflow.com/a/1296101 + e.preventDefault(); //stop the browser from following + window.location.href = '/instances/' + $.mobile.pageData.uuid + '/tags'; +}); + + +$('#instance-preview').live('click', function(e) { + if ($.mobile.pageData) { + GetSingleResource('instances', $.mobile.pageData.uuid + '/frames', function(frames) { + if (frames.length == 1) + { + // Viewing a single-frame image + jQuery.slimbox('/instances/' + $.mobile.pageData.uuid + '/preview', '', { + overlayFadeDuration : 1, + resizeDuration : 1, + imageFadeDuration : 1 + }); + } + else + { + // Viewing a multi-frame image + + var images = []; + for (var i = 0; i < frames.length; i++) { + images.push([ '/instances/' + $.mobile.pageData.uuid + '/frames/' + i + '/preview' ]); + } + + jQuery.slimbox(images, 0, { + overlayFadeDuration : 1, + resizeDuration : 1, + imageFadeDuration : 1, + loop : true + }); + } + }); + + } +}); + +$('#series-preview').live('click', function(e) { + if ($.mobile.pageData) { + GetSingleResource('series', $.mobile.pageData.uuid, function(series) { + GetMultipleResources('instances', series.Instances, function(instances) { + SortOnDicomTag(instances, 'InstanceNumber', true, false); + + var images = []; + for (var i = 0; i < instances.length; i++) { + images.push([ '/instances/' + instances[i].ID + '/preview', + '{0}/{1}'.format(i + 1, instances.length) ]) + } + + jQuery.slimbox(images, 0, { + overlayFadeDuration : 1, + resizeDuration : 1, + imageFadeDuration : 1, + loop : true + }); + }) + }); + } +}); + + + + + + +function ChooseDicomModality(callback) +{ + $.ajax({ + url: '/modalities', + type: 'GET', + dataType: 'json', + async: false, + success: function(modalities) { + var clickedModality = ''; + var items = $('<ul>') + .attr('data-role', 'listview'); + + for (var i = 0; i < modalities.length; i++) { + var modality = modalities[i]; + var item = $('<li>') + .html('<a href="#" rel="close">' + modality + '</a>') + .attr('modality', modality) + .click(function() { + clickedModality = $(this).attr('modality'); + }); + items.append(item); + } + + $('#dialog').simpledialog2({ + mode: 'blank', + animate: false, + headerText: 'DICOM modality', + headerClose: true, + width: '100%', + blankContent: items, + callbackClose: function() { + var timer; + function WaitForDialogToClose() { + if (!$('#dialog').is(':visible')) { + clearInterval(timer); + callback(clickedModality); + } + } + timer = setInterval(WaitForDialogToClose, 100); + } + }); + } + }); +} + + +$('#instance-store,#series-store').live('click', function(e) { + ChooseDicomModality(function(modality) { + if (modality != '') { + $.ajax({ + url: '/modalities/' + modality + '/store', + type: 'POST', + dataType: 'text', + data: $.mobile.pageData.uuid, + async: true, // Necessary to block UI + beforeSend: function() { + $.blockUI({ message: $('#loading') }); + }, + complete: function(s) { + $.unblockUI(); + }, + success: function(s) { + console.log('done !'); + }, + error: function() { + alert('Error during C-Store'); + } + }); + + } + }); +}); + + +$('#show-tag-name').live('change', function(e) { + var checked = e.currentTarget.checked; + if (checked) + $('.tag-name').show(); + else + $('.tag-name').hide(); +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/file-upload.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,88 @@ +var pendingUploads = []; +var currentUpload = 0; +var totalUpload = 0; + +$(document).ready(function() { + // Initialize the jQuery File Upload widget: + $('#fileupload').fileupload({ + //dataType: 'json', + //maxChunkSize: 500, + //sequentialUploads: true, + limitConcurrentUploads: 3, + add: function (e, data) { + pendingUploads.push(data); + } + }) + .bind('fileuploadstop', function(e, data) { + $('#upload-button').removeClass('ui-disabled'); + //$('#upload-abort').addClass('ui-disabled'); + $('#progress .bar').css('width', '100%'); + if ($('#progress .label').text() != 'Failure') + $('#progress .label').text('Done'); + }) + .bind('fileuploadfail', function(e, data) { + $('#progress .bar') + .css('width', '100%') + .css('background-color', 'red'); + $('#progress .label').text('Failure'); + }) + .bind('fileuploaddrop', function (e, data) { + var target = $('#upload-list'); + $.each(data.files, function (index, file) { + target.append('<li class="pending-file">' + file.name + '</li>'); + }); + target.listview('refresh'); + }) + .bind('fileuploadsend', function (e, data) { + // Update the progress bar. Note: for some weird reason, the + // "fileuploadprogressall" does not work under Firefox. + var progress = parseInt(currentUpload / totalUploads * 100, 10); + currentUpload += 1; + $('#progress .label').text('Uploading: ' + progress + '%'); + $('#progress .bar') + .css('width', progress + '%') + .css('background-color', 'green'); + }); +}); + + + +$('#upload').live('pageshow', function() { + $('#fileupload').fileupload('enable'); +}); + +$('#upload').live('pagehide', function() { + $('#fileupload').fileupload('disable'); +}); + + +$('#upload-button').live('click', function() { + var pu = pendingUploads; + pendingUploads = []; + + $('.pending-file').remove(); + $('#upload-list').listview('refresh'); + $('#progress .bar').css('width', '0%'); + $('#progress .label').text(''); + + currentUpload = 1; + totalUploads = pu.length + 1; + if (pu.length > 0) { + $('#upload-button').addClass('ui-disabled'); + //$('#upload-abort').removeClass('ui-disabled'); + } + + for (var i = 0; i < pu.length; i++) { + pu[i].submit(); + } +}); + +$('#upload-clear').live('click', function() { + pendingUploads = []; + $('.pending-file').remove(); + $('#upload-list').listview('refresh'); +}); + +/*$('#upload-abort').live('click', function() { + $('#fileupload').fileupload().abort(); + });*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/date.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,104 @@ +/** + * Version: 1.0 Alpha-1 + * Build Date: 13-Nov-2007 + * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. + * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. + * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/ + */ +Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}}; +Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} +return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} +return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}} +return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);} +if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;} +var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);} +if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);} +if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);} +if(x.hour||x.hours){this.addHours(x.hour||x.hours);} +if(x.month||x.months){this.addMonths(x.month||x.months);} +if(x.year||x.years){this.addYears(x.year||x.years);} +if(x.day||x.days){this.addDays(x.day||x.days);} +return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");} +return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;} +if(!x.second&&x.second!==0){x.second=-1;} +if(!x.minute&&x.minute!==0){x.minute=-1;} +if(!x.hour&&x.hour!==0){x.hour=-1;} +if(!x.day&&x.day!==0){x.day=-1;} +if(!x.month&&x.month!==0){x.month=-1;} +if(!x.year&&x.year!==0){x.year=-1;} +if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());} +if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());} +if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());} +if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());} +if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());} +if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());} +if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());} +if(x.timezone){this.setTimezone(x.timezone);} +if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);} +return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;} +var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}} +return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();}; +Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;} +return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);} +var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;} +return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);} +var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";} +return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}}; +(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;} +break;} +return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];} +rx.push(r[0]);s=r[1];} +return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];} +return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];} +throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));} +return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;} +if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} +try{r=(px[i].call(this,s));}catch(e){r=null;} +if(r){return r;}} +throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} +try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);} +rx.push(r[0]);s=r[1];} +return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];} +return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;} +rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;} +s=q[1];} +if(!r){throw new $P.Exception(s);} +if(q){throw new $P.Exception(q[1]);} +if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}} +return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;} +rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;} +if(!last&&q[1].length===0){last=true;} +if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}} +p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}} +if(rx[1].length<best[1].length){best=rx;} +if(best[1].length===0){break;}} +if(best[0].length===0){return best;} +if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);} +best[1]=q[1];} +return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);} +return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];} +if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);} +var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}} +return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}} +this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");} +var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});} +return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;} +for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}} +if(this.now){return new Date();} +var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);} +if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;} +if(!this.unit){this.unit="day";} +if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;} +if(this.unit=="week"){this.unit="day";this.value=this.value*7;} +this[this.unit+"s"]=this.value*orient;} +return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;} +if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();} +if(this.month&&!this.day){this.day=1;} +return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));} +fn=_C[keys]=_.any.apply(null,px);} +return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));} +return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){} +return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;} +try{r=Date.Grammar.start.call({},s);}catch(e){return null;} +return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;} +return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jqm.page.params.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,111 @@ +// jqm.page.params.js - version 0.1 +// Copyright (c) 2011, Kin Blas +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the <organization> nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(function( $, window, undefined ) { + +// Given a query string, convert all the name/value pairs +// into a property/value object. If a name appears more than +// once in a query string, the value is automatically turned +// into an array. +function queryStringToObject( qstr ) +{ + var result = {}, + nvPairs = ( ( qstr || "" ).replace( /^\?/, "" ).split( /&/ ) ), + i, pair, n, v; + + for ( i = 0; i < nvPairs.length; i++ ) { + var pstr = nvPairs[ i ]; + if ( pstr ) { + pair = pstr.split( /=/ ); + n = pair[ 0 ]; + v = pair[ 1 ]; + if ( result[ n ] === undefined ) { + result[ n ] = v; + } else { + if ( typeof result[ n ] !== "object" ) { + result[ n ] = [ result[ n ] ]; + } + result[ n ].push( v ); + } + } + } + + return result; +} + +// The idea here is to listen for any pagebeforechange notifications from +// jQuery Mobile, and then muck with the toPage and options so that query +// params can be passed to embedded/internal pages. So for example, if a +// changePage() request for a URL like: +// +// http://mycompany.com/myapp/#page-1?foo=1&bar=2 +// +// is made, the page that will actually get shown is: +// +// http://mycompany.com/myapp/#page-1 +// +// The browser's location will still be updated to show the original URL. +// The query params for the embedded page are also added as a property/value +// object on the options object. You can access it from your page notifications +// via data.options.pageData. +$( document ).bind( "pagebeforechange", function( e, data ) { + + // We only want to handle the case where we are being asked + // to go to a page by URL, and only if that URL is referring + // to an internal page by id. + + if ( typeof data.toPage === "string" ) { + var u = $.mobile.path.parseUrl( data.toPage ); + if ( $.mobile.path.isEmbeddedPage( u ) ) { + // The request is for an internal page, if the hash + // contains query (search) params, strip them off the + // toPage URL and then set options.dataUrl appropriately + // so the location.hash shows the originally requested URL + // that hash the query params in the hash. + + var u2 = $.mobile.path.parseUrl( u.hash.replace( /^#/, "" ) ); + if ( u2.search ) { + if ( !data.options.dataUrl ) { + data.options.dataUrl = data.toPage; + } + data.options.pageData = queryStringToObject( u2.search ); + data.toPage = u.hrefNoHash + "#" + u2.pathname; + } + } + } +}); + +})( jQuery, window ); + + + + +// http://stackoverflow.com/a/8295488 +$(document).bind("pagebeforechange", function( event, data ) { + $.mobile.pageData = (data && data.options && data.options.pageData) + ? data.options.pageData + : {}; +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jqtree.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,143 @@ +ul.tree { + margin-left: 12px; +} + +ul.tree, +ul.tree ul { + list-style: none outside; + margin-bottom: 0; + padding: 0; +} + +ul.tree ul { + display: block; + margin-left: 12px; + margin-right: 0; +} + +ul.tree li.closed > ul { + display: none; +} + +ul.tree li { + clear: both; +} + +ul.tree .toggler { + background-image: url(jqtree-icons.png); + background-repeat: no-repeat; + background-position: -8px 0; + width: 8px; + height: 8px; + display: block; + position: absolute; + left: -12px; + top: 30%; + text-indent: -9999px; + border-bottom: none; +} + +ul.tree div { + cursor: pointer; +} + +ul.tree .title { + color: #1C4257; + vertical-align: middle; +} + +ul.tree li.folder { + margin-bottom: 4px; +} + +ul.tree li.folder.closed { + margin-bottom: 1px; +} + +ul.tree li.folder .title { + margin-left: 0; +} + +ul.tree .toggler.closed { + background-position: 0 0; +} + +span.tree-dragging { + color: #fff; + background: #000; + opacity: 0.6; + cursor: pointer; + padding: 2px 8px; +} + +ul.tree li.ghost { + position: relative; + z-index: 10; + margin-right: 10px; +} + +ul.tree li.ghost span { + display: block; +} + +ul.tree li.ghost span.circle { + background-image: url(jqtree-icons.png); + background-repeat: no-repeat; + background-position: 0 -8px; + height: 8px; + width: 8px; + position: absolute; + top: -4px; + left: 2px; +} + +ul.tree li.ghost span.line { + background-color: #0000ff; + height: 2px; + padding: 0; + position: absolute; + top: -1px; + left: 10px; + width: 100%; +} + +ul.tree li.ghost.inside { + margin-left: 48px; +} + +ul.tree span.tree-hit { + position: absolute; + display: block; +} + +ul.tree span.border { + position: absolute; + display: block; + left: -2px; + top: 0; + border: solid 2px #0000ff; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + margin: 0; +} + +ul.tree div { + width: 100%; /* todo: why is this in here? */ + *width: auto; /* ie7 fix; issue 41 */ + position: relative; +} + +ul.tree li.selected > div, +ul.tree li.selected > div:hover { + background-color: #97BDD6; + background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#89AFCA)); + background: -moz-linear-gradient(top, #BEE0F5, #89AFCA); + background: -ms-linear-gradient(top, #BEE0F5, #89AFCA); + background: -o-linear-gradient(top, #BEE0F5, #89AFCA); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); +} + +ul.tree .moving > div .title { + outline: dashed 1px #0000ff; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-1.7.2.min.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,4 @@ +/*! jQuery v1.7.2 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},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(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( +a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.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(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.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(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={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,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f +.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[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","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/css/jquery.fileupload-ui.css Sun Sep 16 09:22:48 2012 +0200 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/css/style.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,15 @@ +@charset 'UTF-8'; +/* + * jQuery File Upload Plugin CSS Example 1.0 + * 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 + */ + +body{ + padding-top: 60px; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/cors/jquery.postmessage-transport.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,117 @@ +/* + * jQuery postMessage Transport Plugin 1.1 + * 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'; + + var counter = 0, + names = [ + 'accepts', + 'cache', + 'contents', + 'contentType', + 'crossDomain', + 'data', + 'dataType', + 'headers', + 'ifModified', + 'mimeType', + 'password', + 'processData', + 'timeout', + 'traditional', + 'type', + 'url', + 'username' + ], + convert = function (p) { + return p; + }; + + $.ajaxSetup({ + converters: { + 'postmessage text': convert, + 'postmessage json': convert, + 'postmessage html': convert + } + }); + + $.ajaxTransport('postmessage', function (options) { + if (options.postMessage && window.postMessage) { + var iframe, + loc = $('<a>').prop('href', options.postMessage)[0], + target = loc.protocol + '//' + loc.host, + xhrUpload = options.xhr().upload; + return { + send: function (_, completeCallback) { + var message = { + id: 'postmessage-transport-' + (counter += 1) + }, + eventName = 'message.' + message.id; + iframe = $( + '<iframe style="display:none;" src="' + + options.postMessage + '" name="' + + message.id + '"></iframe>' + ).bind('load', function () { + $.each(names, function (i, name) { + message[name] = options[name]; + }); + message.dataType = message.dataType.replace('postmessage ', ''); + $(window).bind(eventName, function (e) { + e = e.originalEvent; + var data = e.data, + ev; + if (e.origin === target && data.id === message.id) { + if (data.type === 'progress') { + ev = document.createEvent('Event'); + ev.initEvent(data.type, false, true); + $.extend(ev, data); + xhrUpload.dispatchEvent(ev); + } else { + completeCallback( + data.status, + data.statusText, + {postmessage: data.result}, + data.headers + ); + iframe.remove(); + $(window).unbind(eventName); + } + } + }); + iframe[0].contentWindow.postMessage( + message, + target + ); + }).appendTo(document.body); + }, + abort: function () { + if (iframe) { + iframe.remove(); + } + } + }; + } + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/cors/jquery.xdr-transport.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,85 @@ +/* + * jQuery XDomainRequest Transport Plugin 1.1.2 + * 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 + * + * Based on Julian Aubourg's ajaxHooks xdr.js: + * https://github.com/jaubourg/ajaxHooks/ + */ + +/*jslint unparam: true */ +/*global define, window, XDomainRequest */ + +(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'; + if (window.XDomainRequest && !$.support.cors) { + $.ajaxTransport(function (s) { + if (s.crossDomain && s.async) { + if (s.timeout) { + s.xdrTimeout = s.timeout; + delete s.timeout; + } + var xdr; + return { + send: function (headers, completeCallback) { + function callback(status, statusText, responses, responseHeaders) { + xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; + xdr = null; + completeCallback(status, statusText, responses, responseHeaders); + } + xdr = new XDomainRequest(); + // XDomainRequest only supports GET and POST: + if (s.type === 'DELETE') { + s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + + '_method=DELETE'; + s.type = 'POST'; + } else if (s.type === 'PUT') { + s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + + '_method=PUT'; + s.type = 'POST'; + } + xdr.open(s.type, s.url); + xdr.onload = function () { + callback( + 200, + 'OK', + {text: xdr.responseText}, + 'Content-Type: ' + xdr.contentType + ); + }; + xdr.onerror = function () { + callback(404, 'Not Found'); + }; + if (s.xdrTimeout) { + xdr.ontimeout = function () { + callback(0, 'timeout'); + }; + xdr.timeout = s.xdrTimeout; + } + xdr.send((s.hasContent && s.data) || null); + }, + abort: function () { + if (xdr) { + xdr.onerror = $.noop(); + xdr.abort(); + } + } + }; + } + }); + } +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload-fp.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,219 @@ +/* + * jQuery File Upload File Processing Plugin 1.0 + * 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 + ); + } +}(function ($, loadImage) { + 'use strict'; + + // The File Upload IP version extends the basic fileupload widget + // with file processing functionality: + $.widget('blueimpFP.fileupload', $.blueimp.fileupload, { + + options: { + // The list of file processing actions: + process: [ + /* + { + action: 'load', + fileTypes: /^image\/(gif|jpeg|png)$/, + maxFileSize: 20000000 // 20MB + }, + { + action: 'resize', + maxWidth: 1920, + maxHeight: 1200, + minWidth: 800, + minHeight: 600 + }, + { + action: 'save' + } + */ + ], + + // 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('process', data).done(function () { + data.submit(); + }); + } + }, + + processActions: { + // Loads the image given via data.files and data.index + // as canvas element. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + load: function (data, options) { + var that = this, + file = data.files[data.index], + dfd = $.Deferred(); + if (window.HTMLCanvasElement && + window.HTMLCanvasElement.prototype.toBlob && + ($.type(options.maxFileSize) !== 'number' || + file.size < options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + loadImage( + file, + function (canvas) { + data.canvas = canvas; + dfd.resolveWith(that, [data]); + }, + {canvas: true} + ); + } else { + dfd.rejectWith(that, [data]); + } + return dfd.promise(); + }, + // Resizes the image given as data.canvas and updates + // data.canvas with the resized image. + // Accepts the options maxWidth, maxHeight, minWidth and + // minHeight to scale the given image: + resize: function (data, options) { + if (data.canvas) { + var canvas = loadImage.scale(data.canvas, options); + if (canvas.width !== data.canvas.width || + canvas.height !== data.canvas.height) { + data.canvas = canvas; + data.processed = true; + } + } + return data; + }, + // Saves the processed image given as data.canvas + // inplace at data.index of data.files: + save: function (data, options) { + // Do nothing if no processing has happened: + if (!data.canvas || !data.processed) { + return data; + } + var that = this, + file = data.files[data.index], + name = file.name, + dfd = $.Deferred(), + callback = 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) + ); + } + } + // Store the created blob at the position + // of the original file in the files list: + data.files[data.index] = blob; + dfd.resolveWith(that, [data]); + }; + // Use canvas.mozGetAsFile directly, to retain the filename, as + // Gecko doesn't support the filename option for FormData.append: + if (data.canvas.mozGetAsFile) { + callback(data.canvas.mozGetAsFile( + (/^image\/(jpeg|png)$/.test(file.type) && name) || + ((name && name.replace(/\..+$/, '')) || + 'blob') + '.png', + file.type + )); + } else { + data.canvas.toBlob(callback, file.type); + } + return dfd.promise(); + } + }, + + // Resizes the file at the given index and stores the created blob at + // the original position of the files list, returns a Promise object: + _processFile: function (files, index, options) { + var that = this, + dfd = $.Deferred().resolveWith(that, [{ + files: files, + index: index + }]), + chain = dfd.promise(); + that._processing += 1; + $.each(options.process, function (i, settings) { + chain = chain.pipe(function (data) { + return that.processActions[settings.action] + .call(this, data, settings); + }); + }); + chain.always(function () { + that._processing -= 1; + if (that._processing === 0) { + that.element + .removeClass('fileupload-processing'); + } + }); + if (that._processing === 1) { + that.element.addClass('fileupload-processing'); + } + return chain; + }, + + // Processes the files 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 files (inplace) is done: + process: function (data) { + var that = this, + options = $.extend({}, this.options, data); + if (options.process && options.process.length && + this._isXHRUpload(options)) { + $.each(data.files, function (index, file) { + that._processingQueue = that._processingQueue.pipe( + function () { + var dfd = $.Deferred(); + that._processFile(data.files, index, options) + .always(function () { + dfd.resolveWith(that); + }); + return dfd.promise(); + } + ); + }); + } + return this._processingQueue; + }, + + _create: function () { + $.blueimp.fileupload.prototype._create.call(this); + this._processing = 0; + this._processingQueue = $.Deferred().resolveWith(this) + .promise(); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload-ui.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,702 @@ +/* + * jQuery File Upload User Interface Plugin 6.9.1 + * 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-fp' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.tmpl, + window.loadImage + ); + } +}(function ($, tmpl, loadImage) { + 'use strict'; + + // The UI version extends the FP (file processing) version or the basic + // file upload widget and adds complete user interface interaction: + var parentWidget = ($.blueimpFP || $.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 container for the list of files. If undefined, it is set to + // an element with class "files" inside of the widget element: + filesContainer: undefined, + // By default, files are appended to the files container. + // Set the following option to true, to prepend files instead: + prependFiles: false, + // 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('process', data).done(function () { + that._adjustMaxNumberOfFiles(-files.length); + data.isAdjusted = true; + data.files.valid = data.isValidated = that._validate(files); + data.context = that._renderUpload(files).data('data', data); + options.filesContainer[ + options.prependFiles ? 'prepend' : 'append' + ](data.context); + 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' + ) + .attr('aria-valuenow', 100) + .find('.bar').css( + 'width', + '100%' + ); + } + return that._trigger('sent', e, data); + }, + // Callback for successful uploads: + done: function (e, data) { + var that = $(this).data('fileupload'), + template; + if (data.context) { + data.context.each(function (index) { + var file = ($.isArray(data.result) && + data.result[index]) || {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) { + var progress = parseInt(data.loaded / data.total * 100, 10); + data.context.find('.progress') + .attr('aria-valuenow', progress) + .find('.bar').css( + 'width', + progress + '%' + ); + } + }, + // Callback for global upload progress events: + progressall: function (e, data) { + var $this = $(this), + progress = parseInt(data.loaded / data.total * 100, 10), + globalProgressNode = $this.find('.fileupload-progress'), + extendedProgressNode = globalProgressNode + .find('.progress-extended'); + if (extendedProgressNode.length) { + extendedProgressNode.html( + $this.data('fileupload')._renderExtendedProgress(data) + ); + } + globalProgressNode + .find('.progress') + .attr('aria-valuenow', progress) + .find('.bar').css( + 'width', + progress + '%' + ); + }, + // Callback for uploads start, equivalent to the global ajaxStart event: + start: function (e) { + var that = $(this).data('fileupload'); + that._transition($(this).find('.fileupload-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-progress')).done( + function () { + $(this).find('.progress') + .attr('aria-valuenow', '0') + .find('.bar').css('width', '0%'); + $(this).find('.progress-extended').html(' '); + 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'; + }, + + _formatBitrate: function (bits) { + if (typeof bits !== 'number') { + return ''; + } + if (bits >= 1000000000) { + return (bits / 1000000000).toFixed(2) + ' Gbit/s'; + } + if (bits >= 1000000) { + return (bits / 1000000).toFixed(2) + ' Mbit/s'; + } + if (bits >= 1000) { + return (bits / 1000).toFixed(2) + ' kbit/s'; + } + return bits + ' bit/s'; + }, + + _formatTime: function (seconds) { + var date = new Date(seconds * 1000), + days = parseInt(seconds / 86400, 10); + days = days ? days + 'd ' : ''; + return days + + ('0' + date.getUTCHours()).slice(-2) + ':' + + ('0' + date.getUTCMinutes()).slice(-2) + ':' + + ('0' + date.getUTCSeconds()).slice(-2); + }, + + _formatPercentage: function (floatValue) { + return (floatValue * 100).toFixed(2) + ' %'; + }, + + _renderExtendedProgress: function (data) { + return this._formatBitrate(data.bitrate) + ' | ' + + this._formatTime( + (data.total - data.loaded) * 8 / data.bitrate + ) + ' | ' + + this._formatPercentage( + data.loaded / data.total + ) + ' | ' + + this._formatFileSize(data.loaded) + ' / ' + + this._formatFileSize(data.total); + }, + + _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, + dfd = $.Deferred(); + return ((loadImage && loadImage( + file, + function (img) { + node.append(img); + that._forceReflow(node); + that._transition(node).done(function () { + dfd.resolveWith(node); + }); + if (!$.contains(document.body, node[0])) { + // If the element is not part of the DOM, + // transition events are not triggered, + // so we have to resolve manually: + dfd.resolveWith(node); + } + }, + { + maxWidth: options.previewMaxWidth, + maxHeight: options.previewMaxHeight, + canvas: options.previewAsCanvas + } + )) || dfd.resolveWith(node)) && dfd; + }, + + _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 dfd = $.Deferred(); + that._renderPreview(file, $(element)).done( + function () { + dfd.resolveWith(that); + } + ); + return dfd.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) { + return $.support.transition && node.length && + node[0].offsetWidth; + }, + + _transition: function (node) { + var dfd = $.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); + dfd.resolveWith(node); + } + } + ).toggleClass('in'); + } else { + node.toggleClass('in'); + dfd.resolveWith(node); + } + return dfd; + }, + + _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 (!$.blueimpFP) { + this._processingQueue = $.Deferred().resolveWith(this).promise(); + this.process = 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); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/jquery.fileupload.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,968 @@ +/* + * jQuery File Upload Plugin 5.12 + * 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, + // Interval in milliseconds to calculate and trigger progress events: + progressInterval: 100, + // Interval in milliseconds to calculate progress bitrate: + bitrateInterval: 500, + + // 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' + ], + + _BitrateTimer: function () { + this.timestamp = +(new Date()); + this.loaded = 0; + this.bitrate = 0; + this.getBitrate = function (now, loaded, interval) { + var timeDiff = now - this.timestamp; + if (!this.bitrate || !interval || timeDiff > interval) { + this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; + this.loaded = loaded; + this.timestamp = now; + } + return this.bitrate; + }; + }, + + _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); + } + if ($.isArray(options.formData)) { + return options.formData; + } + 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 now = +(new Date()), + total, + loaded; + if (data._time && data.progressInterval && + (now - data._time < data.progressInterval) && + e.loaded !== e.total) { + return; + } + data._time = now; + 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; + data.bitrate = data._bitrateTimer.getBitrate( + now, + loaded, + data.bitrateInterval + ); + // 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, + bitrate: this._bitrateTimer.getBitrate( + now, + this._loaded, + data.bitrateInterval + ) + }); + } + }, + + _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'); + // Set timer for global bitrate progress calculation: + this._bitrateTimer = new this._BitrateTimer(); + } + 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; + this._bitrateTimer = null; + } + }, + + _onSend: function (e, data) { + var that = this, + jqXHR, + slot, + pipe, + options = that._getAJAXSettings(data), + send = function (resolve, args) { + that._sending += 1; + // Set timer for bitrate progress calculation: + options._bitrateTimer = new that._BitrateTimer(); + 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; + } + }, + + _getFileInputFiles: function (fileInput) { + fileInput = $(fileInput); + var files = $.each($.makeArray(fileInput.prop('files')), this._normalizeFile), + value; + if (!files.length) { + value = fileInput.prop('value'); + if (!value) { + return []; + } + // 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: + files = [{name: value.replace(/^.*\\/, '')}]; + } + return files; + }, + + _onChange: function (e) { + var that = e.data.fileupload, + data = { + fileInput: $(e.target), + form: $(e.target.form) + }; + data.files = that._getFileInputFiles(data.fileInput); + 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 = '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; + // Initialize options set via HTML5 data-attributes: + $.extend(options, $(this.element[0].cloneNode(false)).data()); + 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; + } + if (data.fileInput && !data.files) { + data.files = this._getFileInputFiles(data.fileInput); + } else { + 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) { + if (data.fileInput && !data.files) { + data.files = this._getFileInputFiles(data.fileInput); + } else { + data.files = $.each($.makeArray(data.files), this._normalizeFile); + } + if (data.files.length) { + return this._onSend(null, data); + } + } + return this._getXHRPromise(false, data && data.context); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/jquery.iframe-transport.js Sun Sep 16 09:22:48 2012 +0200 @@ -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()); + } + } + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/locale.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,29 @@ +/* + * jQuery File Upload Plugin Localization Example 6.5.1 + * 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 + */ + +/*global window */ + +window.locale = { + "fileupload": { + "errors": { + "maxFileSize": "File is too big", + "minFileSize": "File is too small", + "acceptFileTypes": "Filetype not allowed", + "maxNumberOfFiles": "Max number of files exceeded", + "uploadedBytes": "Uploaded bytes exceed file size", + "emptyResult": "Empty file upload result" + }, + "error": "Error", + "start": "Start", + "cancel": "Cancel", + "destroy": "Delete" + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery-file-upload/js/vendor/jquery.ui.widget.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,282 @@ +/* + * jQuery UI Widget 1.8.18+amd + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ + +(function (factory) { + if (typeof define === "function" && define.amd) { + // Register as an anonymous AMD module: + define(["jquery"], factory); + } else { + // Browser globals: + factory(jQuery); + } +}(function( $, undefined ) { + +// jQuery 1.4+ +if ( $.cleanData ) { + var _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 ); + }; +} else { + var _remove = $.fn.remove; + $.fn.remove = function( selector, keepData ) { + return this.each(function() { + if ( !keepData ) { + if ( !selector || $.filter( selector, [ this ] ).length ) { + $( "*", this ).add( [ this ] ).each(function() { + try { + $( this ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + }); + } + } + return _remove.call( $(this), selector, keepData ); + }); + }; +} + +$.widget = function( name, base, prototype ) { + var namespace = name.split( "." )[ 0 ], + fullName; + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName ] = function( elem ) { + return !!$.data( elem, name ); + }; + + $[ namespace ] = $[ namespace ] || {}; + $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + var 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 +// $.each( basePrototype, function( key, val ) { +// if ( $.isPlainObject(val) ) { +// basePrototype[ key ] = $.extend( {}, val ); +// } +// }); + basePrototype.options = $.extend( true, {}, basePrototype.options ); + $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { + namespace: namespace, + widgetName: name, + widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, + widgetBaseClass: fullName + }, prototype ); + + $.widget.bridge( name, $[ namespace ][ name ] ); +}; + +$.widget.bridge = function( name, object ) { + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = Array.prototype.slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.extend.apply( null, [ true, options ].concat(args) ) : + options; + + // prevent calls to internal methods + if ( isMethodCall && options.charAt( 0 ) === "_" ) { + return returnValue; + } + + if ( isMethodCall ) { + this.each(function() { + var instance = $.data( this, name ), + methodValue = instance && $.isFunction( instance[options] ) ? + instance[ options ].apply( instance, args ) : + instance; + // TODO: add this back in 1.9 and use $.error() (see #5972) +// if ( !instance ) { +// throw "cannot call methods on " + name + " prior to initialization; " + +// "attempted to call method '" + options + "'"; +// } +// if ( !$.isFunction( instance[options] ) ) { +// throw "no such method '" + options + "' for " + name + " widget instance"; +// } +// var methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, name ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, name, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } +}; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + options: { + disabled: false + }, + _createWidget: function( options, element ) { + // $.widget.bridge stores the plugin instance, but we do it anyway + // so that it's stored even before the _create function runs + $.data( element, this.widgetName, this ); + this.element = $( element ); + this.options = $.extend( true, {}, + this.options, + this._getCreateOptions(), + options ); + + var self = this; + this.element.bind( "remove." + this.widgetName, function() { + self.destroy(); + }); + + this._create(); + this._trigger( "create" ); + this._init(); + }, + _getCreateOptions: function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }, + _create: function() {}, + _init: function() {}, + + destroy: function() { + this.element + .unbind( "." + this.widgetName ) + .removeData( this.widgetName ); + this.widget() + .unbind( "." + this.widgetName ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetBaseClass + "-disabled " + + "ui-state-disabled" ); + }, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.extend( {}, this.options ); + } + + if (typeof key === "string" ) { + if ( value === undefined ) { + return this.options[ key ]; + } + options = {}; + options[ key ] = value; + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var self = this; + $.each( options, function( key, value ) { + self._setOption( key, value ); + }); + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + [ value ? "addClass" : "removeClass"]( + this.widgetBaseClass + "-disabled" + " " + + "ui-state-disabled" ) + .attr( "aria-disabled", value ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _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.call( this.element[0], event, data ) === false || + event.isDefaultPrevented() ); + } +}; + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.blockUI.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,499 @@ +/*! + * jQuery blockUI plugin + * Version 2.39 (23-MAY-2011) + * @requires jQuery v1.2.3 or later + * + * Examples at: http://malsup.com/jquery/block/ + * Copyright (c) 2007-2010 M. Alsup + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Thanks to Amir-Hossein Sobhi for some excellent contributions! + */ + +;(function($) { + +if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) { + alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery); + return; +} + +$.fn._fadeIn = $.fn.fadeIn; + +var noOp = function() {}; + +// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle +// retarded userAgent strings on Vista) +var mode = document.documentMode || 0; +var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8); +var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode; + +// global $ methods for blocking/unblocking the entire page +$.blockUI = function(opts) { install(window, opts); }; +$.unblockUI = function(opts) { remove(window, opts); }; + +// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) +$.growlUI = function(title, message, timeout, onClose) { + var $m = $('<div class="growlUI"></div>'); + if (title) $m.append('<h1>'+title+'</h1>'); + if (message) $m.append('<h2>'+message+'</h2>'); + if (timeout == undefined) timeout = 3000; + $.blockUI({ + message: $m, fadeIn: 700, fadeOut: 1000, centerY: false, + timeout: timeout, showOverlay: false, + onUnblock: onClose, + css: $.blockUI.defaults.growlCSS + }); +}; + +// plugin method for blocking element content +$.fn.block = function(opts) { + return this.unblock({ fadeOut: 0 }).each(function() { + if ($.css(this,'position') == 'static') + this.style.position = 'relative'; + if ($.browser.msie) + this.style.zoom = 1; // force 'hasLayout' + install(this, opts); + }); +}; + +// plugin method for unblocking element content +$.fn.unblock = function(opts) { + return this.each(function() { + remove(this, opts); + }); +}; + +$.blockUI.version = 2.39; // 2nd generation blocking at no extra cost! + +// override these in your code to change the default behavior and style +$.blockUI.defaults = { + // message displayed when blocking (use null for no message) + message: '<h1>Please wait...</h1>', + + title: null, // title string; only used when theme == true + draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) + + theme: false, // set to true to use with jQuery UI themes + + // styles for the message when blocking; if you wish to disable + // these and use an external stylesheet then do this in your code: + // $.blockUI.defaults.css = {}; + css: { + padding: 0, + margin: 0, + width: '30%', + top: '40%', + left: '35%', + textAlign: 'center', + color: '#000', + border: '3px solid #aaa', + backgroundColor:'#fff', + cursor: 'wait' + }, + + // minimal style set used when themes are used + themedCSS: { + width: '30%', + top: '40%', + left: '35%' + }, + + // styles for the overlay + overlayCSS: { + backgroundColor: '#000', + opacity: 0.6, + cursor: 'wait' + }, + + // styles applied when using $.growlUI + growlCSS: { + width: '350px', + top: '10px', + left: '', + right: '10px', + border: 'none', + padding: '5px', + opacity: 0.6, + cursor: 'default', + color: '#fff', + backgroundColor: '#000', + '-webkit-border-radius': '10px', + '-moz-border-radius': '10px', + 'border-radius': '10px' + }, + + // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w + // (hat tip to Jorge H. N. de Vasconcelos) + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', + + // force usage of iframe in non-IE browsers (handy for blocking applets) + forceIframe: false, + + // z-index for the blocking overlay + baseZ: 1000, + + // set these to true to have the message automatically centered + centerX: true, // <-- only effects element blocking (page block controlled via css above) + centerY: true, + + // allow body element to be stetched in ie6; this makes blocking look better + // on "short" pages. disable if you wish to prevent changes to the body height + allowBodyStretch: true, + + // enable if you want key and mouse events to be disabled for content that is blocked + bindEvents: true, + + // be default blockUI will supress tab navigation from leaving blocking content + // (if bindEvents is true) + constrainTabKey: true, + + // fadeIn time in millis; set to 0 to disable fadeIn on block + fadeIn: 200, + + // fadeOut time in millis; set to 0 to disable fadeOut on unblock + fadeOut: 400, + + // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock + timeout: 0, + + // disable if you don't want to show the overlay + showOverlay: true, + + // if true, focus will be placed in the first available input field when + // page blocking + focusInput: true, + + // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) + applyPlatformOpacityRules: true, + + // callback method invoked when fadeIn has completed and blocking message is visible + onBlock: null, + + // callback method invoked when unblocking has completed; the callback is + // passed the element that has been unblocked (which is the window object for page + // blocks) and the options that were passed to the unblock call: + // onUnblock(element, options) + onUnblock: null, + + // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 + quirksmodeOffsetHack: 4, + + // class name of the message block + blockMsgClass: 'blockMsg' +}; + +// private data and functions follow... + +var pageBlock = null; +var pageBlockEls = []; + +function install(el, opts) { + var full = (el == window); + var msg = opts && opts.message !== undefined ? opts.message : undefined; + opts = $.extend({}, $.blockUI.defaults, opts || {}); + opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); + var css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); + var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); + msg = msg === undefined ? opts.message : msg; + + // remove the current block (if there is one) + if (full && pageBlock) + remove(window, {fadeOut:0}); + + // if an existing element is being used as the blocking content then we capture + // its current place in the DOM (and current display style) so we can restore + // it when we unblock + if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { + var node = msg.jquery ? msg[0] : msg; + var data = {}; + $(el).data('blockUI.history', data); + data.el = node; + data.parent = node.parentNode; + data.display = node.style.display; + data.position = node.style.position; + if (data.parent) + data.parent.removeChild(node); + } + + $(el).data('blockUI.onUnblock', opts.onUnblock); + var z = opts.baseZ; + + // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; + // layer1 is the iframe layer which is used to supress bleed through of underlying content + // layer2 is the overlay layer which has opacity and a wait cursor (by default) + // layer3 is the message content that is displayed while blocking + + var lyr1 = ($.browser.msie || opts.forceIframe) + ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>') + : $('<div class="blockUI" style="display:none"></div>'); + + var lyr2 = opts.theme + ? $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>') + : $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'); + + var lyr3, s; + if (opts.theme && full) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">' + + '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + + '<div class="ui-widget-content ui-dialog-content"></div>' + + '</div>'; + } + else if (opts.theme) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">' + + '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + + '<div class="ui-widget-content ui-dialog-content"></div>' + + '</div>'; + } + else if (full) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>'; + } + else { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>'; + } + lyr3 = $(s); + + // if we have a message, style it + if (msg) { + if (opts.theme) { + lyr3.css(themedCSS); + lyr3.addClass('ui-widget-content'); + } + else + lyr3.css(css); + } + + // style the overlay + if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))) + lyr2.css(opts.overlayCSS); + lyr2.css('position', full ? 'fixed' : 'absolute'); + + // make iframe layer transparent in IE + if ($.browser.msie || opts.forceIframe) + lyr1.css('opacity',0.0); + + //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); + var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); + $.each(layers, function() { + this.appendTo($par); + }); + + if (opts.theme && opts.draggable && $.fn.draggable) { + lyr3.draggable({ + handle: '.ui-dialog-titlebar', + cancel: 'li' + }); + } + + // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) + var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0); + if (ie6 || expr) { + // give body 100% height + if (full && opts.allowBodyStretch && $.boxModel) + $('html,body').css('height','100%'); + + // fix ie6 issue when blocked element has a border width + if ((ie6 || !$.boxModel) && !full) { + var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); + var fixT = t ? '(0 - '+t+')' : 0; + var fixL = l ? '(0 - '+l+')' : 0; + } + + // simulate fixed position + $.each([lyr1,lyr2,lyr3], function(i,o) { + var s = o[0].style; + s.position = 'absolute'; + if (i < 2) { + full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"') + : s.setExpression('height','this.parentNode.offsetHeight + "px"'); + full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"') + : s.setExpression('width','this.parentNode.offsetWidth + "px"'); + if (fixL) s.setExpression('left', fixL); + if (fixT) s.setExpression('top', fixT); + } + else if (opts.centerY) { + if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); + s.marginTop = 0; + } + else if (!opts.centerY && full) { + var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0; + var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; + s.setExpression('top',expression); + } + }); + } + + // show the message + if (msg) { + if (opts.theme) + lyr3.find('.ui-widget-content').append(msg); + else + lyr3.append(msg); + if (msg.jquery || msg.nodeType) + $(msg).show(); + } + + if (($.browser.msie || opts.forceIframe) && opts.showOverlay) + lyr1.show(); // opacity is zero + if (opts.fadeIn) { + var cb = opts.onBlock ? opts.onBlock : noOp; + var cb1 = (opts.showOverlay && !msg) ? cb : noOp; + var cb2 = msg ? cb : noOp; + if (opts.showOverlay) + lyr2._fadeIn(opts.fadeIn, cb1); + if (msg) + lyr3._fadeIn(opts.fadeIn, cb2); + } + else { + if (opts.showOverlay) + lyr2.show(); + if (msg) + lyr3.show(); + if (opts.onBlock) + opts.onBlock(); + } + + // bind key and mouse events + bind(1, el, opts); + + if (full) { + pageBlock = lyr3[0]; + pageBlockEls = $(':input:enabled:visible',pageBlock); + if (opts.focusInput) + setTimeout(focus, 20); + } + else + center(lyr3[0], opts.centerX, opts.centerY); + + if (opts.timeout) { + // auto-unblock + var to = setTimeout(function() { + full ? $.unblockUI(opts) : $(el).unblock(opts); + }, opts.timeout); + $(el).data('blockUI.timeout', to); + } +}; + +// remove the block +function remove(el, opts) { + var full = (el == window); + var $el = $(el); + var data = $el.data('blockUI.history'); + var to = $el.data('blockUI.timeout'); + if (to) { + clearTimeout(to); + $el.removeData('blockUI.timeout'); + } + opts = $.extend({}, $.blockUI.defaults, opts || {}); + bind(0, el, opts); // unbind events + + if (opts.onUnblock === null) { + opts.onUnblock = $el.data('blockUI.onUnblock'); + $el.removeData('blockUI.onUnblock'); + } + + var els; + if (full) // crazy selector to handle odd field errors in ie6/7 + els = $('body').children().filter('.blockUI').add('body > .blockUI'); + else + els = $('.blockUI', el); + + if (full) + pageBlock = pageBlockEls = null; + + if (opts.fadeOut) { + els.fadeOut(opts.fadeOut); + setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut); + } + else + reset(els, data, opts, el); +}; + +// move blocking element back into the DOM where it started +function reset(els,data,opts,el) { + els.each(function(i,o) { + // remove via DOM calls so we don't lose event handlers + if (this.parentNode) + this.parentNode.removeChild(this); + }); + + if (data && data.el) { + data.el.style.display = data.display; + data.el.style.position = data.position; + if (data.parent) + data.parent.appendChild(data.el); + $(el).removeData('blockUI.history'); + } + + if (typeof opts.onUnblock == 'function') + opts.onUnblock(el,opts); +}; + +// bind/unbind the handler +function bind(b, el, opts) { + var full = el == window, $el = $(el); + + // don't bother unbinding if there is nothing to unbind + if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) + return; + if (!full) + $el.data('blockUI.isBlocked', b); + + // don't bind events when overlay is not in use or if bindEvents is false + if (!opts.bindEvents || (b && !opts.showOverlay)) + return; + + // bind anchors and inputs for mouse and key events + var events = 'mousedown mouseup keydown keypress'; + b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler); + +// former impl... +// var $e = $('a,:input'); +// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); +}; + +// event handler to suppress keyboard/mouse events when blocking +function handler(e) { + // allow tab navigation (conditionally) + if (e.keyCode && e.keyCode == 9) { + if (pageBlock && e.data.constrainTabKey) { + var els = pageBlockEls; + var fwd = !e.shiftKey && e.target === els[els.length-1]; + var back = e.shiftKey && e.target === els[0]; + if (fwd || back) { + setTimeout(function(){focus(back)},10); + return false; + } + } + } + var opts = e.data; + // allow events within the message content + if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0) + return true; + + // allow events for content that is not being blocked + return $(e.target).parents().children().filter('div.blockUI').length == 0; +}; + +function focus(back) { + if (!pageBlockEls) + return; + var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; + if (e) + e.focus(); +}; + +function center(el, x, y) { + var p = el.parentNode, s = el.style; + var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); + var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); + if (x) s.left = l > 0 ? (l+'px') : '0'; + if (y) s.top = t > 0 ? (t+'px') : '0'; +}; + +function sz(el, p) { + return parseInt($.css(el,p))||0; +}; + +})(jQuery);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile-1.1.0.min.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted}.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile-1.1.0.min.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,177 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +(function(D,s,k){typeof define==="function"&&define.amd?define(["jquery"],function(a){k(a,D,s);return a.mobile}):k(D.jQuery,D,s)})(this,document,function(D,s,k){(function(a,c,b,e){function f(a){for(;a&&typeof a.originalEvent!=="undefined";)a=a.originalEvent;return a}function d(b){for(var d={},f,g;b;){f=a.data(b,t);for(g in f)if(f[g])d[g]=d.hasVirtualBinding=true;b=b.parentNode}return d}function g(){y&&(clearTimeout(y),y=0);y=setTimeout(function(){F=y=0;C.length=0;z=false;G=true},a.vmouse.resetTimerDuration)} +function h(b,d,g){var c,h;if(!(h=g&&g[b])){if(g=!g)a:{for(g=d.target;g;){if((h=a.data(g,t))&&(!b||h[b]))break a;g=g.parentNode}g=null}h=g}if(h){c=d;var g=c.type,z,j;c=a.Event(c);c.type=b;h=c.originalEvent;z=a.event.props;g.search(/^(mouse|click)/)>-1&&(z=w);if(h)for(j=z.length;j;)b=z[--j],c[b]=h[b];if(g.search(/mouse(down|up)|click/)>-1&&!c.which)c.which=1;if(g.search(/^touch/)!==-1&&(b=f(h),g=b.touches,b=b.changedTouches,g=g&&g.length?g[0]:b&&b.length?b[0]:e))for(h=0,len=u.length;h<len;h++)b=u[h], +c[b]=g[b];a(d.target).trigger(c)}return c}function j(b){var d=a.data(b.target,x);if(!z&&(!F||F!==d))if(d=h("v"+b.type,b))d.isDefaultPrevented()&&b.preventDefault(),d.isPropagationStopped()&&b.stopPropagation(),d.isImmediatePropagationStopped()&&b.stopImmediatePropagation()}function o(b){var g=f(b).touches,c;if(g&&g.length===1&&(c=b.target,g=d(c),g.hasVirtualBinding))F=L++,a.data(c,x,F),y&&(clearTimeout(y),y=0),A=G=false,c=f(b).touches[0],s=c.pageX,E=c.pageY,h("vmouseover",b,g),h("vmousedown",b,g)} +function m(a){G||(A||h("vmousecancel",a,d(a.target)),A=true,g())}function p(b){if(!G){var c=f(b).touches[0],e=A,z=a.vmouse.moveDistanceThreshold;A=A||Math.abs(c.pageX-s)>z||Math.abs(c.pageY-E)>z;flags=d(b.target);A&&!e&&h("vmousecancel",b,flags);h("vmousemove",b,flags);g()}}function l(a){if(!G){G=true;var b=d(a.target),c;h("vmouseup",a,b);if(!A&&(c=h("vclick",a,b))&&c.isDefaultPrevented())c=f(a).changedTouches[0],C.push({touchID:F,x:c.clientX,y:c.clientY}),z=true;h("vmouseout",a,b);A=false;g()}}function r(b){var b= +a.data(b,t),d;if(b)for(d in b)if(b[d])return true;return false}function n(){}function k(b){var d=b.substr(1);return{setup:function(){r(this)||a.data(this,t,{});a.data(this,t)[b]=true;v[b]=(v[b]||0)+1;v[b]===1&&H.bind(d,j);a(this).bind(d,n);if(K)v.touchstart=(v.touchstart||0)+1,v.touchstart===1&&H.bind("touchstart",o).bind("touchend",l).bind("touchmove",p).bind("scroll",m)},teardown:function(){--v[b];v[b]||H.unbind(d,j);K&&(--v.touchstart,v.touchstart||H.unbind("touchstart",o).unbind("touchmove",p).unbind("touchend", +l).unbind("scroll",m));var f=a(this),g=a.data(this,t);g&&(g[b]=false);f.unbind(d,n);r(this)||f.removeData(t)}}}var t="virtualMouseBindings",x="virtualTouchID",c="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),u="clientX clientY pageX pageY screenX screenY".split(" "),w=a.event.props.concat(a.event.mouseHooks?a.event.mouseHooks.props:[]),v={},y=0,s=0,E=0,A=false,C=[],z=false,G=false,K="addEventListener"in b,H=a(b),L=1,F=0;a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10, +resetTimerDuration:1500};for(var I=0;I<c.length;I++)a.event.special[c[I]]=k(c[I]);K&&b.addEventListener("click",function(b){var d=C.length,f=b.target,g,c,e,h,z;if(d){g=b.clientX;c=b.clientY;threshold=a.vmouse.clickDistanceThreshold;for(e=f;e;){for(h=0;h<d;h++)if(z=C[h],e===f&&Math.abs(z.x-g)<threshold&&Math.abs(z.y-c)<threshold||a.data(e,x)===z.touchID){b.preventDefault();b.stopPropagation();return}e=e.parentNode}}},true)})(jQuery,s,k);(function(a,c,b){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/, +"$1")}var f="hashchange",d=k,g,h=a.event.special,j=d.documentMode,o="on"+f in c&&(j===b||j>7);a.fn[f]=function(a){return a?this.bind(f,a):this.trigger(f)};a.fn[f].delay=50;h[f]=a.extend(h[f],{setup:function(){if(o)return false;a(g.start)},teardown:function(){if(o)return false;a(g.stop)}});g=function(){function g(){var b=e(),d=t(r);if(b!==r)k(r=b,d),a(c).trigger(f);else if(d!==r)location.href=location.href.replace(/#.*/,"")+d;j=setTimeout(g,a.fn[f].delay)}var h={},j,r=e(),n=function(a){return a},k= +n,t=n;h.start=function(){j||g()};h.stop=function(){j&&clearTimeout(j);j=b};a.browser.msie&&!o&&function(){var b,c;h.start=function(){if(!b)c=(c=a.fn[f].src)&&c+e(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){c||k(e());g()}).attr("src",c||"javascript:0").insertAfter("body")[0].contentWindow,d.onpropertychange=function(){try{if(event.propertyName==="title")b.document.title=d.title}catch(a){}}};h.stop=n;t=function(){return e(b.location.href)};k=function(g,c){var e=b.document, +h=a.fn[f].domain;if(g!==c)e.title=d.title,e.open(),h&&e.write('<script>document.domain="'+h+'"<\/script>'),e.close(),b.location.hash=g}}();return h}()})(jQuery,this);(function(a,c){if(a.cleanData){var b=a.cleanData;a.cleanData=function(f){for(var d=0,g;(g=f[d])!=null;d++)a(g).triggerHandler("remove");b(f)}}else{var e=a.fn.remove;a.fn.remove=function(b,d){return this.each(function(){d||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){a(this).triggerHandler("remove")});return e.call(a(this), +b,d)})}}a.widget=function(b,d,g){var c=b.split(".")[0],e,b=b.split(".")[1];e=c+"-"+b;if(!g)g=d,d=a.Widget;a.expr[":"][e]=function(d){return!!a.data(d,b)};a[c]=a[c]||{};a[c][b]=function(a,b){arguments.length&&this._createWidget(a,b)};d=new d;d.options=a.extend(true,{},d.options);a[c][b].prototype=a.extend(true,d,{namespace:c,widgetName:b,widgetEventPrefix:a[c][b].prototype.widgetEventPrefix||b,widgetBaseClass:e},g);a.widget.bridge(b,a[c][b])};a.widget.bridge=function(b,d){a.fn[b]=function(g){var e= +typeof g==="string",j=Array.prototype.slice.call(arguments,1),o=this,g=!e&&j.length?a.extend.apply(null,[true,g].concat(j)):g;if(e&&g.charAt(0)==="_")return o;e?this.each(function(){var d=a.data(this,b);if(!d)throw"cannot call methods on "+b+" prior to initialization; attempted to call method '"+g+"'";if(!a.isFunction(d[g]))throw"no such method '"+g+"' for "+b+" widget instance";var e=d[g].apply(d,j);if(e!==d&&e!==c)return o=e,false}):this.each(function(){var c=a.data(this,b);c?c.option(g||{})._init(): +a.data(this,b,new d(g,this))});return o}};a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)};a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(b,d){a.data(d,this.widgetName,this);this.element=a(d);this.options=a.extend(true,{},this.options,this._getCreateOptions(),b);var g=this;this.element.bind("remove."+this.widgetName,function(){g.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){var b= +{};a.metadata&&(b=a.metadata.get(element)[this.widgetName]);return b},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(b,d){var g=b;if(arguments.length===0)return a.extend({},this.options);if(typeof b==="string"){if(d===c)return this.options[b]; +g={};g[b]=d}this._setOptions(g);return this},_setOptions:function(b){var d=this;a.each(b,function(a,b){d._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b;a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(b,d,g){var c=this.options[b],d=a.Event(d); +d.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase();g=g||{};if(d.originalEvent)for(var b=a.event.props.length,e;b;)e=a.event.props[--b],d[e]=d.originalEvent[e];this.element.trigger(d,g);return!(a.isFunction(c)&&c.call(this.element[0],d,g)===false||d.isDefaultPrevented())}}})(jQuery);(function(a,c){a.widget("mobile.widget",{_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments);this._trigger("init")},_getCreateOptions:function(){var b=this.element, +e={};a.each(this.options,function(a){var d=b.jqmData(a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()}));d!==c&&(e[a]=d)});return e},enhanceWithin:function(b,c){this.enhance(a(this.options.initSelector,a(b)),c)},enhance:function(b,c){var f,d=a(b),d=a.mobile.enhanceable(d);c&&d.length&&(f=(f=a.mobile.closestPageData(d))&&f.keepNativeSelector()||"",d=d.not(f));d[this.widgetName]()},raise:function(a){throw"Widget ["+this.widgetName+"]: "+a;}})})(jQuery);(function(a,c){var b={};a.mobile=a.extend({}, +{version:"1.1.0",ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:true,hashListeningEnabled:true,linkBindingEnabled:true,defaultPageTransition:"fade",maxTransitionWidth:false,minScrollBack:250,touchOverflowEnabled:false,defaultDialogTransition:"pop",loadingMessage:"loading",pageLoadErrorMessage:"Error Loading Page",loadingMessageTextVisible:false,loadingMessageTheme:"a",pageLoadErrorMessageTheme:"e",autoInitializePage:true, +pushStateEnabled:true,ignoreContentEnabled:false,orientationChangeEnabled:true,buttonMarkup:{hoverDelay:200},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,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,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},silentScroll:function(b){if(a.type(b)!== +"number")b=a.mobile.defaultHomeScroll;a.event.special.scrollstart.enabled=false;setTimeout(function(){c.scrollTo(0,b);a(k).trigger("silentscroll",{x:0,y:b})},20);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},nsNormalizeDict:b,nsNormalize:function(d){return!d?void 0:b[d]||(b[d]=a.camelCase(a.mobile.ns+d))},getInheritedTheme:function(a,b){for(var c=a[0],e="",f=/ui-(bar|body|overlay)-([a-z])\b/,m,p;c;){m=c.className||"";if((p=f.exec(m))&&(e=p[2]))break;c=c.parentNode}return e|| +b||"a"},closestPageData:function(a){return a.closest(':jqmData(role="page"), :jqmData(role="dialog")').data("page")},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;for(var e=b.length,f=a(),o,m,p,l=0;l<e;l++){m=b.eq(l);p=false;for(o=b[l];o;){if((o.getAttribute?o.getAttribute("data-"+a.mobile.ns+c):"")==="false"){p=true;break}o=o.parentNode}p||(f=f.add(m))}return f}}, +a.mobile);a.fn.jqmData=function(b,c){var f;typeof b!="undefined"&&(b&&(b=a.mobile.nsNormalize(b)),f=this.data.apply(this,arguments.length<2?[b]:[b,c]));return f};a.jqmData=function(b,c,f){var e;typeof c!="undefined"&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,f));return e};a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))};a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))};a.fn.removeWithDependents=function(){a.removeWithDependents(this)};a.removeWithDependents= +function(b){b=a(b);(b.jqmData("dependents")||a()).remove();b.remove()};a.fn.addDependents=function(b){a.addDependents(a(this),b)};a.addDependents=function(b,c){var f=a(b).jqmData("dependents")||a();a(b).jqmData("dependents",a.merge(f,c))};a.fn.getEncodedText=function(){return a("<div/>").text(a(this).text()).html()};a.fn.jqmEnhanceable=function(){return a.mobile.enhanceable(this)};a.fn.jqmHijackable=function(){return a.mobile.hijackable(this)};var e=a.find,f=/:jqmData\(([^)]*)\)/g;a.find=function(b, +c,h,j){b=b.replace(f,"[data-"+(a.mobile.ns||"")+"$1]");return e.call(this,b,c,h,j)};a.extend(a.find,e);a.find.matches=function(b,c){return a.find(b,null,null,c)};a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}})(jQuery,this);(function(a){a(s);var c=a("html");a.mobile.media=function(){var b={},e=a("<div id='jquery-mediatest'>"),f=a("<body>").append(e);return function(a){if(!(a in b)){var g=k.createElement("style"),h="@media "+a+" { #jquery-mediatest { position:absolute; } }"; +g.type="text/css";g.styleSheet?g.styleSheet.cssText=h:g.appendChild(k.createTextNode(h));c.prepend(f).prepend(g);b[a]=e.css("position")==="absolute";f.add(g).remove()}return b[a]}}()})(jQuery);(function(a,c){function b(a){var b=a.charAt(0).toUpperCase()+a.substr(1),a=(a+" "+g.join(b+" ")+b).split(" "),f;for(f in a)if(d[a[f]]!==c)return true}function e(a,b,c){var d=k.createElement("div"),c=c?[c]:g,f;for(i=0;i<c.length;i++){var e=c[i],h="-"+e.charAt(0).toLowerCase()+e.substr(1)+"-"+a+": "+b+";",e=e.charAt(0).toUpperCase()+ +e.substr(1)+(a.charAt(0).toUpperCase()+a.substr(1));d.setAttribute("style",h);d.style[e]&&(f=true)}return!!f}var f=a("<body>").prependTo("html"),d=f[0].style,g=["Webkit","Moz","O"],h="palmGetResource"in s,j=s.operamini&&{}.toString.call(s.operamini)==="[object OperaMini]",o=s.blackberry;a.extend(a.mobile,{browser:{}});a.mobile.browser.ie=function(){for(var a=3,b=k.createElement("div"),c=b.all||[];b.innerHTML="<\!--[if gt IE "+ ++a+"]><br><![endif]--\>",c[0];);return a>4?a:!a}();a.extend(a.support, +{orientation:"orientation"in s&&"onorientationchange"in s,touch:"ontouchend"in k,cssTransitions:"WebKitTransitionEvent"in s||e("transition","height 100ms linear"),pushState:"pushState"in history&&"replaceState"in history,mediaquery:a.mobile.media("only all"),cssPseudoElement:!!b("content"),touchOverflow:!!b("overflowScrolling"),cssTransform3d:e("perspective","10px","moz")||a.mobile.media("(-"+g.join("-transform-3d),(-")+"-transform-3d),(transform-3d)"),boxShadow:!!b("boxShadow")&&!o,scrollTop:("pageXOffset"in +s||"scrollTop"in k.documentElement||"scrollTop"in f[0])&&!h&&!j,dynamicBaseTag:function(){var b=location.protocol+"//"+location.host+location.pathname+"ui-dir/",c=a("head base"),d=null,e="",g;c.length?e=c.attr("href"):c=d=a("<base>",{href:b}).appendTo("head");g=a("<a href='testurl' />").prependTo(f)[0].href;c[0].href=e||location.pathname;d&&d.remove();return g.indexOf(b)===0}()});f.remove();h=function(){var a=s.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")> +-1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}();a.mobile.gradeA=function(){return a.support.mediaquery||a.mobile.browser.ie&&a.mobile.browser.ie>=7};a.mobile.ajaxBlacklist=s.blackberry&&!s.WebKitPoint||j||h;h&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")});a.support.boxShadow||a("html").addClass("ui-mobile-nosupport-boxshadow")})(jQuery);(function(a,c,b){function e(b,c,d){var f=d.type;d.type=c;a.event.handle.call(b, +d);d.type=f}a.each("touchstart touchmove touchend orientationchange throttledresize tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(b,c){a.fn[c]=function(a){return a?this.bind(c,a):this.trigger(c)};a.attrFn[c]=true});var f=a.support.touch,d=f?"touchstart":"mousedown",g=f?"touchend":"mouseup",h=f?"touchmove":"mousemove";a.event.special.scrollstart={enabled:true,setup:function(){function b(a,f){d=f;e(c,d?"scrollstart":"scrollstop",a)}var c=this,d,f;a(c).bind("touchmove scroll", +function(c){a.event.special.scrollstart.enabled&&(d||b(c,true),clearTimeout(f),f=setTimeout(function(){b(c,false)},50))})}};a.event.special.tap={setup:function(){var b=this,c=a(b);c.bind("vmousedown",function(d){function f(){clearTimeout(q)}function g(){f();c.unbind("vclick",h).unbind("vmouseup",f);a(k).unbind("vmousecancel",g)}function h(a){g();n==a.target&&e(b,"tap",a)}if(d.which&&d.which!==1)return false;var n=d.target,q;c.bind("vmouseup",f).bind("vclick",h);a(k).bind("vmousecancel",g);q=setTimeout(function(){e(b, +"taphold",a.Event("taphold",{target:n}))},750)})}};a.event.special.swipe={scrollSupressionThreshold:10,durationThreshold:1E3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,setup:function(){var c=a(this);c.bind(d,function(d){function f(b){if(l){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b;k={time:(new Date).getTime(),coords:[c.pageX,c.pageY]};Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault()}}var e=d.originalEvent.touches? +d.originalEvent.touches[0]:d,l={time:(new Date).getTime(),coords:[e.pageX,e.pageY],origin:a(d.target)},k;c.bind(h,f).one(g,function(){c.unbind(h,f);l&&k&&k.time-l.time<a.event.special.swipe.durationThreshold&&Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(l.coords[1]-k.coords[1])<a.event.special.swipe.verticalDistanceThreshold&&l.origin.trigger("swipe").trigger(l.coords[0]>k.coords[0]?"swipeleft":"swiperight");l=k=b})})}};(function(a,b){function c(){var a= +f();a!==e&&(e=a,d.trigger("orientationchange"))}var d=a(b),f,e,g,h,t={0:true,180:true};if(a.support.orientation&&(g=b.innerWidth||a(b).width(),h=b.innerHeight||a(b).height(),g=g>h&&g-h>50,h=t[b.orientation],g&&h||!g&&!h))t={"-90":true,90:true};a.event.special.orientationchange={setup:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;e=f();d.bind("throttledresize",c)},teardown:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;d.unbind("throttledresize", +c)},add:function(a){var b=a.handler;a.handler=function(a){a.orientation=f();return b.apply(this,arguments)}}};a.event.special.orientationchange.orientation=f=function(){var c=true,c=k.documentElement;return(c=a.support.orientation?t[b.orientation]:c&&c.clientWidth/c.clientHeight<1.1)?"portrait":"landscape"}})(jQuery,c);(function(){a.event.special.throttledresize={setup:function(){a(this).bind("resize",b)},teardown:function(){a(this).unbind("resize",b)}};var b=function(){f=(new Date).getTime();g=f- +c;g>=250?(c=f,a(this).trigger("throttledresize")):(d&&clearTimeout(d),d=setTimeout(b,250-g))},c=0,d,f,g})();a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe",swiperight:"swipe"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)}}})})(jQuery,this);(function(a){a.widget("mobile.page",a.mobile.widget,{options:{theme:"c",domCache:false,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){var a=this;if(a._trigger("beforecreate")=== +false)return false;a.element.attr("tabindex","0").addClass("ui-page ui-body-"+a.options.theme).bind("pagebeforehide",function(){a.removeContainerBackground()}).bind("pagebeforeshow",function(){a.setContainerBackground()})},removeContainerBackground:function(){a.mobile.pageContainer.removeClass("ui-overlay-"+a.mobile.getInheritedTheme(this.element.parent()))},setContainerBackground:function(c){this.options.theme&&a.mobile.pageContainer.addClass("ui-overlay-"+(c||this.options.theme))},keepNativeSelector:function(){var c= +this.options;return c.keepNative&&a.trim(c.keepNative)&&c.keepNative!==c.keepNativeDefault?[c.keepNative,c.keepNativeDefault].join(", "):c.keepNativeDefault}})})(jQuery);(function(a,c,b){var e=function(d){d===b&&(d=true);return function(b,f,e,o){var k=new a.Deferred,p=f?" reverse":"",l=a.mobile.urlHistory.getActive().lastScroll||a.mobile.defaultHomeScroll,r=a.mobile.getScreenHeight(),n=a.mobile.maxTransitionWidth!==false&&a(c).width()>a.mobile.maxTransitionWidth,q=!a.support.cssTransitions||n||!b|| +b==="none",t=function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+b)},x=function(){a.event.special.scrollstart.enabled=false;c.scrollTo(0,l);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},u=function(){o.removeClass(a.mobile.activePageClass+" out in reverse "+b).height("")},n=function(){o&&d&&u();e.addClass(a.mobile.activePageClass);a.mobile.focusPage(e);e.height(r+l);x();q||e.animationComplete(w);e.addClass(b+" in"+p);q&&w()},w=function(){d|| +o&&u();e.removeClass("out in reverse "+b).height("");t();a(c).scrollTop()!==l&&x();k.resolve(b,f,e,o,true)};t();o&&!q?(d?o.animationComplete(n):n(),o.height(r+a(c).scrollTop()).addClass(b+" out"+p)):n();return k.promise()}},f=e(),e=e(false);a.mobile.defaultTransitionHandler=f;a.mobile.transitionHandlers={"default":a.mobile.defaultTransitionHandler,sequential:f,simultaneous:e};a.mobile.transitionFallbacks={}})(jQuery,this);(function(a,c){function b(b){r&&(!r.closest(".ui-page-active").length||b)&& +r.removeClass(a.mobile.activeBtnClass);r=null}function e(){t=false;q.length>0&&a.mobile.changePage.apply(null,q.pop())}function f(b,c,d,f){c&&c.data("page")._trigger("beforehide",null,{nextPage:b});b.data("page")._trigger("beforeshow",null,{prevPage:c||a("")});a.mobile.hidePageLoadingMsg();d&&!a.support.cssTransform3d&&a.mobile.transitionFallbacks[d]&&(d=a.mobile.transitionFallbacks[d]);d=(a.mobile.transitionHandlers[d||"default"]||a.mobile.defaultTransitionHandler)(d,f,b,c);d.done(function(){c&& +c.data("page")._trigger("hide",null,{nextPage:b});b.data("page")._trigger("show",null,{prevPage:c||a("")})});return d}function d(){return s.innerHeight||a(s).height()}function g(){var b=a("."+a.mobile.activePageClass),c=parseFloat(b.css("padding-top")),f=parseFloat(b.css("padding-bottom"));b.css("min-height",d()-c-f)}function h(b,c){c&&b.attr("data-"+a.mobile.ns+"role",c);b.page()}function j(a){for(;a;){if(typeof a.nodeName==="string"&&a.nodeName.toLowerCase()=="a")break;a=a.parentNode}return a}function o(b){var b= +a(b).closest(".ui-page").jqmData("url"),c=v.hrefNoHash;if(!b||!l.isPath(b))b=c;return l.makeUrlAbsolute(b,c)}var m=a(s);a("html");var p=a("head"),l={urlParseRE:/^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,parseUrl:function(b){if(a.type(b)==="object")return b;b=l.urlParseRE.exec(b||"")||[];return{href:b[0]||"",hrefNoHash:b[1]||"",hrefNoSearch:b[2]||"",domain:b[3]||"", +protocol:b[4]||"",doubleSlash:b[5]||"",authority:b[6]||"",username:b[8]||"",password:b[9]||"",host:b[10]||"",hostname:b[11]||"",port:b[12]||"",pathname:b[13]||"",directory:b[14]||"",filename:b[15]||"",search:b[16]||"",hash:b[17]||""}},makePathAbsolute:function(a,b){if(a&&a.charAt(0)==="/")return a;for(var a=a||"",c=(b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"")?b.split("/"):[],d=a.split("/"),f=0;f<d.length;f++){var e=d[f];switch(e){case ".":break;case "..":c.length&&c.pop();break;default:c.push(e)}}return"/"+ +c.join("/")},isSameDomain:function(a,b){return l.parseUrl(a).domain===l.parseUrl(b).domain},isRelativeUrl:function(a){return l.parseUrl(a).protocol===""},isAbsoluteUrl:function(a){return l.parseUrl(a).protocol!==""},makeUrlAbsolute:function(a,b){if(!l.isRelativeUrl(a))return a;var c=l.parseUrl(a),d=l.parseUrl(b),f=c.protocol||d.protocol,e=c.protocol?c.doubleSlash:c.doubleSlash||d.doubleSlash,g=c.authority||d.authority,h=c.pathname!=="",j=l.makePathAbsolute(c.pathname||d.filename,d.pathname);return f+ +e+g+j+(c.search||!h&&d.search||"")+c.hash},addSearchParams:function(b,c){var d=l.parseUrl(b),f=typeof c==="object"?a.param(c):c,e=d.search||"?";return d.hrefNoSearch+e+(e.charAt(e.length-1)!=="?"?"&":"")+f+(d.hash||"")},convertUrlToDataUrl:function(a){var b=l.parseUrl(a);if(l.isEmbeddedPage(b))return b.hash.split(x)[0].replace(/^#/,"");else if(l.isSameDomain(b,v))return b.hrefNoHash.replace(v.domain,"");return a},get:function(a){if(a===c)a=location.hash;return l.stripHash(a).replace(/[^\/]*\.[^\/*]+$/, +"")},getFilePath:function(b){var c="&"+a.mobile.subPageUrlKey;return b&&b.split(c)[0].split(x)[0]},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(v.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},cleanHash:function(a){return l.stripHash(a.replace(/\?.*$/,"").replace(x,""))},isExternal:function(a){a=l.parseUrl(a);return a.protocol&&a.domain!==w.domain?true:false},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isFirstPageUrl:function(b){var b= +l.parseUrl(l.makeUrlAbsolute(b,v)),d=a.mobile.firstPage,d=d&&d[0]?d[0].id:c;return(b.hrefNoHash===w.hrefNoHash||y&&b.hrefNoHash===v.hrefNoHash)&&(!b.hash||b.hash==="#"||d&&b.hash.replace(/^#/,"")===d)},isEmbeddedPage:function(a){a=l.parseUrl(a);return a.protocol!==""?a.hash&&(a.hrefNoHash===w.hrefNoHash||y&&a.hrefNoHash===v.hrefNoHash):/^#/.test(a.href)}},r=null,n={stack:[],activeIndex:0,getActive:function(){return n.stack[n.activeIndex]},getPrev:function(){return n.stack[n.activeIndex-1]},getNext:function(){return n.stack[n.activeIndex+ +1]},addNew:function(a,b,c,d,f){n.getNext()&&n.clearForward();n.stack.push({url:a,transition:b,title:c,pageUrl:d,role:f});n.activeIndex=n.stack.length-1},clearForward:function(){n.stack=n.stack.slice(0,n.activeIndex+1)},directHashChange:function(b){var d,f,e;this.getActive();a.each(n.stack,function(a,c){b.currentUrl===c.url&&(d=a<n.activeIndex,f=!d,e=a)});this.activeIndex=e!==c?e:this.activeIndex;d?(b.either||b.isBack)(true):f&&(b.either||b.isForward)(false)},ignoreNextHashChange:false},q=[],t=false, +x="&ui-state=dialog",u=p.children("base"),w=l.parseUrl(location.href),v=u.length?l.parseUrl(l.makeUrlAbsolute(u.attr("href"),w.href)):w,y=w.hrefNoHash!==v.hrefNoHash,B=a.support.dynamicBaseTag?{element:u.length?u:a("<base>",{href:v.hrefNoHash}).prependTo(p),set:function(a){B.element.attr("href",l.makeUrlAbsolute(a,v))},reset:function(){B.element.attr("href",v.hrefNoHash)}}:c;a.mobile.focusPage=function(a){var b=a.find("[autofocus]"),c=a.find(".ui-title:eq(0)");b.length?b.focus():c.length?c.focus(): +a.focus()};var E=true,A,C;A=function(){if(E){var b=a.mobile.urlHistory.getActive();if(b){var c=m.scrollTop();b.lastScroll=c<a.mobile.minScrollBack?a.mobile.defaultHomeScroll:c}}};C=function(){setTimeout(A,100)};m.bind(a.support.pushState?"popstate":"hashchange",function(){E=false});m.one(a.support.pushState?"popstate":"hashchange",function(){E=true});m.one("pagecontainercreate",function(){a.mobile.pageContainer.bind("pagechange",function(){E=true;m.unbind("scrollstop",C);m.bind("scrollstop",C)})}); +m.bind("scrollstop",C);a.mobile.getScreenHeight=d;a.fn.animationComplete=function(b){return a.support.cssTransitions?a(this).one("webkitAnimationEnd animationend",b):(setTimeout(b,0),a(this))};a.mobile.path=l;a.mobile.base=B;a.mobile.urlHistory=n;a.mobile.dialogHashKey=x;a.mobile.allowCrossDomainPages=false;a.mobile.getDocumentUrl=function(b){return b?a.extend({},w):w.href};a.mobile.getDocumentBase=function(b){return b?a.extend({},v):v.href};a.mobile._bindPageRemove=function(){var b=a(this);!b.data("page").options.domCache&& +b.is(":jqmData(external-page='true')")&&b.bind("pagehide.remove",function(){var b=a(this),c=new a.Event("pageremove");b.trigger(c);c.isDefaultPrevented()||b.removeWithDependents()})};a.mobile.loadPage=function(b,d){var f=a.Deferred(),e=a.extend({},a.mobile.loadPage.defaults,d),g=null,j=null,k=l.makeUrlAbsolute(b,a.mobile.activePage&&o(a.mobile.activePage)||v.hrefNoHash);if(e.data&&e.type==="get")k=l.addSearchParams(k,e.data),e.data=c;if(e.data&&e.type==="post")e.reloadPage=true;var u=l.getFilePath(k), +n=l.convertUrlToDataUrl(k);e.pageContainer=e.pageContainer||a.mobile.pageContainer;g=e.pageContainer.children(":jqmData(url='"+n+"')");g.length===0&&n&&!l.isPath(n)&&(g=e.pageContainer.children("#"+n).attr("data-"+a.mobile.ns+"url",n));if(g.length===0)if(a.mobile.firstPage&&l.isFirstPageUrl(u))a.mobile.firstPage.parent().length&&(g=a(a.mobile.firstPage));else if(l.isEmbeddedPage(u))return f.reject(k,d),f.promise();B&&B.reset();if(g.length){if(!e.reloadPage)return h(g,e.role),f.resolve(k,d,g),f.promise(); +j=g}var m=e.pageContainer,x=new a.Event("pagebeforeload"),p={url:b,absUrl:k,dataUrl:n,deferred:f,options:e};m.trigger(x,p);if(x.isDefaultPrevented())return f.promise();if(e.showLoadMsg)var r=setTimeout(function(){a.mobile.showPageLoadingMsg()},e.loadMsgDelay);!a.mobile.allowCrossDomainPages&&!l.isSameDomain(w,k)?f.reject(k,d):a.ajax({url:u,type:e.type,data:e.data,dataType:"html",success:function(c,o,m){var x=a("<div></div>"),v=c.match(/<title[^>]*>([^<]*)/)&&RegExp.$1,w=RegExp("\\bdata-"+a.mobile.ns+ +"url=[\"']?([^\"'>]*)[\"']?");RegExp("(<[^>]+\\bdata-"+a.mobile.ns+"role=[\"']?page[\"']?[^>]*>)").test(c)&&RegExp.$1&&w.test(RegExp.$1)&&RegExp.$1&&(b=u=l.getFilePath(RegExp.$1));B&&B.set(u);x.get(0).innerHTML=c;g=x.find(":jqmData(role='page'), :jqmData(role='dialog')").first();g.length||(g=a("<div data-"+a.mobile.ns+"role='page'>"+c.split(/<\/?body[^>]*>/gmi)[1]+"</div>"));v&&!g.jqmData("title")&&(~v.indexOf("&")&&(v=a("<div>"+v+"</div>").text()),g.jqmData("title",v));if(!a.support.dynamicBaseTag){var q= +l.get(u);g.find("[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]").each(function(){var b=a(this).is("[href]")?"href":a(this).is("[src]")?"src":"action",c=a(this).attr(b),c=c.replace(location.protocol+"//"+location.host+location.pathname,"");/^(\w+:|#|\/)/.test(c)||a(this).attr(b,q+c)})}g.attr("data-"+a.mobile.ns+"url",l.convertUrlToDataUrl(u)).attr("data-"+a.mobile.ns+"external-page",true).appendTo(e.pageContainer);g.one("pagecreate",a.mobile._bindPageRemove);h(g,e.role);k.indexOf("&"+ +a.mobile.subPageUrlKey)>-1&&(g=e.pageContainer.children(":jqmData(url='"+n+"')"));e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg());p.xhr=m;p.textStatus=o;p.page=g;e.pageContainer.trigger("pageload",p);f.resolve(k,d,g,j)},error:function(b,c,g){B&&B.set(l.get());p.xhr=b;p.textStatus=c;p.errorThrown=g;b=new a.Event("pageloadfailed");e.pageContainer.trigger(b,p);b.isDefaultPrevented()||(e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg(),a.mobile.showPageLoadingMsg(a.mobile.pageLoadErrorMessageTheme, +a.mobile.pageLoadErrorMessage,true),setTimeout(a.mobile.hidePageLoadingMsg,1500)),f.reject(k,d))}});return f.promise()};a.mobile.loadPage.defaults={type:"get",data:c,reloadPage:false,role:c,showLoadMsg:false,pageContainer:c,loadMsgDelay:50};a.mobile.changePage=function(d,g){if(t)q.unshift(arguments);else{var j=a.extend({},a.mobile.changePage.defaults,g);j.pageContainer=j.pageContainer||a.mobile.pageContainer;j.fromPage=j.fromPage||a.mobile.activePage;var u=j.pageContainer,o=new a.Event("pagebeforechange"), +m={toPage:d,options:j};u.trigger(o,m);if(!o.isDefaultPrevented())if(d=m.toPage,t=true,typeof d=="string")a.mobile.loadPage(d,j).done(function(b,c,d,e){t=false;c.duplicateCachedPage=e;a.mobile.changePage(d,c)}).fail(function(){t=false;b(true);e();j.pageContainer.trigger("pagechangefailed",m)});else{if(d[0]===a.mobile.firstPage[0]&&!j.dataUrl)j.dataUrl=w.hrefNoHash;var o=j.fromPage,p=j.dataUrl&&l.convertUrlToDataUrl(j.dataUrl)||d.jqmData("url"),v=p;l.getFilePath(p);var r=n.getActive(),s=n.activeIndex=== +0,y=0,B=k.title,A=j.role==="dialog"||d.jqmData("role")==="dialog";if(o&&o[0]===d[0]&&!j.allowSamePageTransition)t=false,u.trigger("pagechange",m);else{h(d,j.role);j.fromHashChange&&n.directHashChange({currentUrl:p,isBack:function(){y=-1},isForward:function(){y=1}});try{k.activeElement&&k.activeElement.nodeName.toLowerCase()!="body"?a(k.activeElement).blur():a("input:focus, textarea:focus, select:focus").blur()}catch(E){}A&&r&&(p=(r.url||"")+x);if(j.changeHash!==false&&p)n.ignoreNextHashChange=true, +l.set(p);var C=!r?B:d.jqmData("title")||d.children(":jqmData(role='header')").find(".ui-title").getEncodedText();C&&B==k.title&&(B=C);d.jqmData("title")||d.jqmData("title",B);j.transition=j.transition||(y&&!s?r.transition:c)||(A?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition);y||n.addNew(p,j.transition,B,v,j.role);k.title=n.getActive().title;a.mobile.activePage=d;j.reverse=j.reverse||y<0;f(d,o,j.transition,j.reverse).done(function(c,f,g,h,l){b();j.duplicateCachedPage&&j.duplicateCachedPage.remove(); +l||a.mobile.focusPage(d);e();u.trigger("pagechange",m)})}}}};a.mobile.changePage.defaults={transition:c,reverse:false,changeHash:true,fromHashChange:false,role:c,duplicateCachedPage:c,pageContainer:c,showLoadMsg:true,dataUrl:c,fromPage:c,allowSamePageTransition:false};a.mobile._registerInternalEvents=function(){a(k).delegate("form","submit",function(b){var c=a(this);if(a.mobile.ajaxEnabled&&!c.is(":jqmData(ajax='false')")&&c.jqmHijackable().length){var d=c.attr("method"),e=c.attr("target"),f=c.attr("action"); +if(!f&&(f=o(c),f===v.hrefNoHash))f=w.hrefNoSearch;f=l.makeUrlAbsolute(f,o(c));!l.isExternal(f)&&!e&&(a.mobile.changePage(f,{type:d&&d.length&&d.toLowerCase()||"get",data:c.serialize(),transition:c.jqmData("transition"),direction:c.jqmData("direction"),reloadPage:true}),b.preventDefault())}});a(k).bind("vclick",function(c){if(!(c.which>1)&&a.mobile.linkBindingEnabled&&(c=j(c.target),a(c).jqmHijackable().length&&c&&l.parseUrl(c.getAttribute("href")||"#").hash!=="#"))b(true),r=a(c).closest(".ui-btn").not(".ui-disabled"), +r.addClass(a.mobile.activeBtnClass),a("."+a.mobile.activePageClass+" .ui-btn").not(c).blur(),a(c).jqmData("href",a(c).attr("href")).attr("href","#")});a(k).bind("click",function(d){if(a.mobile.linkBindingEnabled){var f=j(d.target),e=a(f),g;if(f&&!(d.which>1)&&e.jqmHijackable().length){g=function(){s.setTimeout(function(){b(true)},200)};e.jqmData("href")&&e.attr("href",e.jqmData("href"));if(e.is(":jqmData(rel='back')"))return s.history.back(),false;var h=o(e),f=l.makeUrlAbsolute(e.attr("href")||"#", +h);if(!a.mobile.ajaxEnabled&&!l.isEmbeddedPage(f))g();else{if(f.search("#")!=-1)if(f=f.replace(/[^#]*#/,""))f=l.isPath(f)?l.makeUrlAbsolute(f,h):l.makeUrlAbsolute("#"+f,w.hrefNoHash);else{d.preventDefault();return}var h=e.is("[rel='external']")||e.is(":jqmData(ajax='false')")||e.is("[target]"),k=a.mobile.allowCrossDomainPages&&w.protocol==="file:"&&f.search(/^https?:/)!=-1;h||l.isExternal(f)&&!k?g():(g=e.jqmData("transition"),h=(h=e.jqmData("direction"))&&h==="reverse"||e.jqmData("back"),e=e.attr("data-"+ +a.mobile.ns+"rel")||c,a.mobile.changePage(f,{transition:g,reverse:h,role:e}),d.preventDefault())}}}});a(k).delegate(".ui-page","pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),d=c.attr("href");d&&a.inArray(d,b)===-1&&(b.push(d),a.mobile.loadPage(d,{role:c.attr("data-"+a.mobile.ns+"rel")}))})});a.mobile._handleHashChange=function(b){var d=l.stripHash(b),f={transition:a.mobile.urlHistory.stack.length===0?"none":c,changeHash:false,fromHashChange:true}; +if(!a.mobile.hashListeningEnabled||n.ignoreNextHashChange)n.ignoreNextHashChange=false;else{if(n.stack.length>1&&d.indexOf(x)>-1)if(a.mobile.activePage.is(".ui-dialog"))n.directHashChange({currentUrl:d,either:function(b){var c=a.mobile.urlHistory.getActive();d=c.pageUrl;a.extend(f,{role:c.role,transition:c.transition,reverse:b})}});else{n.directHashChange({currentUrl:d,isBack:function(){s.history.back()},isForward:function(){s.history.forward()}});return}d?(d=typeof d==="string"&&!l.isPath(d)?l.makeUrlAbsolute("#"+ +d,v):d,a.mobile.changePage(d,f)):a.mobile.changePage(a.mobile.firstPage,f)}};m.bind("hashchange",function(){a.mobile._handleHashChange(location.hash)});a(k).bind("pageshow",g);a(s).bind("throttledresize",g)}})(jQuery);(function(a,c){var b={},e=a(c),f=a.mobile.path.parseUrl(location.href);a.extend(b,{initialFilePath:f.pathname+f.search,initialHref:f.hrefNoHash,state:function(){return{hash:location.hash||"#"+b.initialFilePath,title:k.title,initialHref:b.initialHref}},resetUIKeys:function(b){var c="&"+ +a.mobile.subPageUrlKey,f=b.indexOf(a.mobile.dialogHashKey);f>-1?b=b.slice(0,f)+"#"+b.slice(f):b.indexOf(c)>-1&&(b=b.split(c).join("#"+c));return b},hashValueAfterReset:function(c){c=b.resetUIKeys(c);return a.mobile.path.parseUrl(c).hash},nextHashChangePrevented:function(c){a.mobile.urlHistory.ignoreNextHashChange=c;b.onHashChangeDisabled=c},onHashChange:function(){if(!b.onHashChangeDisabled){var c,f;c=location.hash;var e=a.mobile.path.isPath(c),j=e?location.href:a.mobile.getDocumentUrl();c=e?c.replace("#", +""):c;f=b.state();c=a.mobile.path.makeUrlAbsolute(c,j);e&&(c=b.resetUIKeys(c));history.replaceState(f,k.title,c)}},onPopState:function(c){var c=c.originalEvent.state,f,h;if(c){f=b.hashValueAfterReset(a.mobile.urlHistory.getActive().url);h=b.hashValueAfterReset(c.hash.replace("#",""));if(f=f!==h)e.one("hashchange.pushstate",function(){b.nextHashChangePrevented(false)});b.nextHashChangePrevented(false);a.mobile._handleHashChange(c.hash);f&&b.nextHashChangePrevented(true)}},init:function(){e.bind("hashchange", +b.onHashChange);e.bind("popstate",b.onPopState);location.hash===""&&history.replaceState(b.state(),k.title,location.href)}});a(function(){a.mobile.pushStateEnabled&&a.support.pushState&&b.init()})})(jQuery,this);jQuery.mobile.transitionFallbacks.pop="fade";(function(a){a.mobile.transitionHandlers.slide=a.mobile.transitionHandlers.simultaneous;a.mobile.transitionFallbacks.slide="fade"})(jQuery,this);jQuery.mobile.transitionFallbacks.slidedown="fade";jQuery.mobile.transitionFallbacks.slideup="fade"; +jQuery.mobile.transitionFallbacks.flip="fade";jQuery.mobile.transitionFallbacks.flow="fade";jQuery.mobile.transitionFallbacks.turn="fade";(function(a){a.mobile.page.prototype.options.degradeInputs={color:false,date:false,datetime:false,"datetime-local":false,email:false,month:false,number:false,range:"number",search:"text",tel:false,time:false,url:false,week:false};a(k).bind("pagecreate create",function(c){var b=a.mobile.closestPageData(a(c.target)),e;if(b)e=b.options,a(c.target).find("input").not(b.keepNativeSelector()).each(function(){var b= +a(this),c=this.getAttribute("type"),g=e.degradeInputs[c]||"text";if(e.degradeInputs[c]){var h=a("<div>").html(b.clone()).html(),j=h.indexOf(" type=")>-1;b.replaceWith(h.replace(j?/\s+type=["']?\w+['"]?/:/\/?>/,' type="'+g+'" data-'+a.mobile.ns+'type="'+c+'"'+(j?"":">")))}})})})(jQuery);(function(a,c){a.widget("mobile.dialog",a.mobile.widget,{options:{closeBtnText:"Close",overlayTheme:"a",initSelector:":jqmData(role='dialog')"},_create:function(){var b=this,c=this.element,f=a("<a href='#' data-"+a.mobile.ns+ +"icon='delete' data-"+a.mobile.ns+"iconpos='notext'>"+this.options.closeBtnText+"</a>"),d=a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-corner-all ui-overlay-shadow"});c.addClass("ui-dialog ui-overlay-"+this.options.overlayTheme);c.wrapInner(d).children().find(":jqmData(role='header')").prepend(f).end().children(":first-child").addClass("ui-corner-top").end().children(":last-child").addClass("ui-corner-bottom");f.bind("click",function(){b.close()});c.bind("vclick submit",function(b){var b= +a(b.target).closest(b.type==="vclick"?"a":"form"),c;b.length&&!b.jqmData("transition")&&(c=a.mobile.urlHistory.getActive()||{},b.attr("data-"+a.mobile.ns+"transition",c.transition||a.mobile.defaultDialogTransition).attr("data-"+a.mobile.ns+"direction","reverse"))}).bind("pagehide",function(){a(this).find("."+a.mobile.activeBtnClass).removeClass(a.mobile.activeBtnClass)}).bind("pagebeforeshow",function(){b.options.overlayTheme&&b.element.page("removeContainerBackground").page("setContainerBackground", +b.options.overlayTheme)})},close:function(){c.history.back()}});a(k).delegate(a.mobile.dialog.prototype.options.initSelector,"pagecreate",function(){a.mobile.dialog.prototype.enhance(this)})})(jQuery,this);(function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain ui-body ui-br")};a(k).bind("pagecreate create",function(c){a(":jqmData(role='fieldcontain')",c.target).jqmEnhanceable().fieldcontain()})})(jQuery);(function(a){a.fn.grid=function(c){return this.each(function(){var b= +a(this),e=a.extend({grid:null},c),f=b.children(),d={solo:1,a:2,b:3,c:4,d:5},e=e.grid;if(!e)if(f.length<=5)for(var g in d)d[g]===f.length&&(e=g);else e="a";d=d[e];b.addClass("ui-grid-"+e);f.filter(":nth-child("+d+"n+1)").addClass("ui-block-a");d>1&&f.filter(":nth-child("+d+"n+2)").addClass("ui-block-b");d>2&&f.filter(":nth-child(3n+3)").addClass("ui-block-c");d>3&&f.filter(":nth-child(4n+4)").addClass("ui-block-d");d>4&&f.filter(":nth-child(5n+5)").addClass("ui-block-e")})}})(jQuery);(function(a){a(k).bind("pagecreate create", +function(c){a(":jqmData(role='nojs')",c.target).addClass("ui-nojs")})})(jQuery);(function(a,c){function b(a){for(var b;a;){if((b=typeof a.className==="string"&&a.className+" ")&&b.indexOf("ui-btn ")>-1&&b.indexOf("ui-disabled ")<0)break;a=a.parentNode}return a}a.fn.buttonMarkup=function(b){for(var b=b&&a.type(b)=="object"?b:{},d=0;d<this.length;d++){var g=this.eq(d),h=g[0],j=a.extend({},a.fn.buttonMarkup.defaults,{icon:b.icon!==c?b.icon:g.jqmData("icon"),iconpos:b.iconpos!==c?b.iconpos:g.jqmData("iconpos"), +theme:b.theme!==c?b.theme:g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c"),inline:b.inline!==c?b.inline:g.jqmData("inline"),shadow:b.shadow!==c?b.shadow:g.jqmData("shadow"),corners:b.corners!==c?b.corners:g.jqmData("corners"),iconshadow:b.iconshadow!==c?b.iconshadow:g.jqmData("iconshadow"),mini:b.mini!==c?b.mini:g.jqmData("mini")},b),o="ui-btn-inner",m,p,l,r,n,q;a.each(j,function(b,c){h.setAttribute("data-"+a.mobile.ns+b,c);g.jqmData(b,c)});(q=a.data(h.tagName==="INPUT"||h.tagName==="BUTTON"? +h.parentNode:h,"buttonElements"))?(h=q.outer,g=a(h),l=q.inner,r=q.text,a(q.icon).remove(),q.icon=null):(l=k.createElement(j.wrapperEls),r=k.createElement(j.wrapperEls));n=j.icon?k.createElement("span"):null;e&&!q&&e();if(!j.theme)j.theme=a.mobile.getInheritedTheme(g,"c");m="ui-btn ui-btn-up-"+j.theme;m+=j.inline?" ui-btn-inline":"";m+=j.shadow?" ui-shadow":"";m+=j.corners?" ui-btn-corner-all":"";j.mini!==c&&(m+=j.mini?" ui-mini":" ui-fullsize");j.inline!==c&&(m+=j.inline===false?" ui-btn-block":" ui-btn-inline"); +if(j.icon)j.icon="ui-icon-"+j.icon,j.iconpos=j.iconpos||"left",p="ui-icon "+j.icon,j.iconshadow&&(p+=" ui-icon-shadow");j.iconpos&&(m+=" ui-btn-icon-"+j.iconpos,j.iconpos=="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText()));o+=j.corners?" ui-btn-corner-all":"";j.iconpos&&j.iconpos==="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText());q&&g.removeClass(q.bcls||"");g.removeClass("ui-link").addClass(m);l.className=o;r.className="ui-btn-text";q||l.appendChild(r);if(n&&(n.className= +p,!q||!q.icon))n.appendChild(k.createTextNode("\u00a0")),l.appendChild(n);for(;h.firstChild&&!q;)r.appendChild(h.firstChild);q||h.appendChild(l);q={bcls:m,outer:h,inner:l,text:r,icon:n};a.data(h,"buttonElements",q);a.data(l,"buttonElements",q);a.data(r,"buttonElements",q);n&&a.data(n,"buttonElements",q)}return this};a.fn.buttonMarkup.defaults={corners:true,shadow:true,iconshadow:true,wrapperEls:"span"};var e=function(){var c=a.mobile.buttonMarkup.hoverDelay,d,g;a(k).bind({"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart":function(e){var j, +k=a(b(e.target)),e=e.type;if(k.length)if(j=k.attr("data-"+a.mobile.ns+"theme"),e==="vmousedown")a.support.touch?d=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j)},c):k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j);else if(e==="vmousecancel"||e==="vmouseup")k.removeClass("ui-btn-down-"+j).addClass("ui-btn-up-"+j);else if(e==="vmouseover"||e==="focus")a.support.touch?g=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-hover-"+j)},c):k.removeClass("ui-btn-up-"+ +j).addClass("ui-btn-hover-"+j);else if(e==="vmouseout"||e==="blur"||e==="scrollstart")k.removeClass("ui-btn-hover-"+j+" ui-btn-down-"+j).addClass("ui-btn-up-"+j),d&&clearTimeout(d),g&&clearTimeout(g)},"focusin focus":function(c){a(b(c.target)).addClass(a.mobile.focusClass)},"focusout blur":function(c){a(b(c.target)).removeClass(a.mobile.focusClass)}});e=null};a(k).bind("pagecreate create",function(b){a(":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", +b.target).not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").buttonMarkup()})})(jQuery);(function(a){a.mobile.page.prototype.options.backBtnText="Back";a.mobile.page.prototype.options.addBackBtn=false;a.mobile.page.prototype.options.backBtnTheme=null;a.mobile.page.prototype.options.headerTheme="a";a.mobile.page.prototype.options.footerTheme="a";a.mobile.page.prototype.options.contentTheme=null;a(k).delegate(":jqmData(role='page'), :jqmData(role='dialog')","pagecreate",function(){var c=a(this), +b=c.data("page").options,e=c.jqmData("role"),f=b.theme;a(":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')",this).jqmEnhanceable().each(function(){var d=a(this),g=d.jqmData("role"),h=d.jqmData("theme"),j=h||b.contentTheme||e==="dialog"&&f,k;d.addClass("ui-"+g);if(g==="header"||g==="footer"){var m=h||(g==="header"?b.headerTheme:b.footerTheme)||f;d.addClass("ui-bar-"+m).attr("role",g==="header"?"banner":"contentinfo");g==="header"&&(h=d.children("a"),k=h.hasClass("ui-btn-left"), +j=h.hasClass("ui-btn-right"),k=k||h.eq(0).not(".ui-btn-right").addClass("ui-btn-left").length,j||h.eq(1).addClass("ui-btn-right"));b.addBackBtn&&g==="header"&&a(".ui-page").length>1&&c.jqmData("url")!==a.mobile.path.stripHash(location.hash)&&!k&&a("<a href='#' class='ui-btn-left' data-"+a.mobile.ns+"rel='back' data-"+a.mobile.ns+"icon='arrow-l'>"+b.backBtnText+"</a>").attr("data-"+a.mobile.ns+"theme",b.backBtnTheme||m).prependTo(d);d.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({role:"heading", +"aria-level":"1"})}else g==="content"&&(j&&d.addClass("ui-body-"+j),d.attr("role","main"))})})})(jQuery);(function(a){a.widget("mobile.collapsible",a.mobile.widget,{options:{expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsed:true,heading:"h1,h2,h3,h4,h5,h6,legend",theme:null,contentTheme:null,iconTheme:"d",mini:false,initSelector:":jqmData(role='collapsible')"},_create:function(){var c=this.element,b=this.options,e=c.addClass("ui-collapsible"),f=c.children(b.heading).first(), +d=e.wrapInner("<div class='ui-collapsible-content'></div>").find(".ui-collapsible-content"),g=c.closest(":jqmData(role='collapsible-set')").addClass("ui-collapsible-set");f.is("legend")&&(f=a("<div role='heading'>"+f.html()+"</div>").insertBefore(f),f.next().remove());if(g.length){if(!b.theme)b.theme=g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c");if(!b.contentTheme)b.contentTheme=g.jqmData("content-theme");if(!b.iconPos)b.iconPos=g.jqmData("iconpos");if(!b.mini)b.mini=g.jqmData("mini")}d.addClass(b.contentTheme? +"ui-body-"+b.contentTheme:"");f.insertBefore(d).addClass("ui-collapsible-heading").append("<span class='ui-collapsible-heading-status'></span>").wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().buttonMarkup({shadow:false,corners:false,iconpos:c.jqmData("iconpos")||b.iconPos||"left",icon:"plus",mini:b.mini,theme:b.theme}).add(".ui-btn-inner",c).addClass("ui-corner-top ui-corner-bottom");e.bind("expand collapse",function(c){if(!c.isDefaultPrevented()){c.preventDefault(); +var j=a(this),c=c.type==="collapse",k=b.contentTheme;f.toggleClass("ui-collapsible-heading-collapsed",c).find(".ui-collapsible-heading-status").text(c?b.expandCueText:b.collapseCueText).end().find(".ui-icon").toggleClass("ui-icon-minus",!c).toggleClass("ui-icon-plus",c);j.toggleClass("ui-collapsible-collapsed",c);d.toggleClass("ui-collapsible-content-collapsed",c).attr("aria-hidden",c);if(k&&(!g.length||e.jqmData("collapsible-last")))f.find("a").first().add(f.find(".ui-btn-inner")).toggleClass("ui-corner-bottom", +c),d.toggleClass("ui-corner-bottom",!c);d.trigger("updatelayout")}}).trigger(b.collapsed?"collapse":"expand");f.bind("click",function(a){var b=f.is(".ui-collapsible-heading-collapsed")?"expand":"collapse";e.trigger(b);a.preventDefault()})}});a(k).bind("pagecreate create",function(c){a.mobile.collapsible.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){a.widget("mobile.collapsibleset",a.mobile.widget,{options:{initSelector:":jqmData(role='collapsible-set')"},_create:function(){var b=this.element.addClass("ui-collapsible-set"), +e=this.options;if(!e.theme)e.theme=a.mobile.getInheritedTheme(b,"c");if(!e.contentTheme)e.contentTheme=b.jqmData("content-theme");if(!e.corners)e.corners=b.jqmData("corners")===c?true:false;b.jqmData("collapsiblebound")||b.jqmData("collapsiblebound",true).bind("expand collapse",function(b){var c=b.type==="collapse",b=a(b.target).closest(".ui-collapsible"),e=b.data("collapsible");e.options.contentTheme&&b.jqmData("collapsible-last")&&(b.find(e.options.heading).first().find("a").first().add(".ui-btn-inner").toggleClass("ui-corner-bottom", +c),b.find(".ui-collapsible-content").toggleClass("ui-corner-bottom",!c))}).bind("expand",function(b){a(b.target).closest(".ui-collapsible").siblings(".ui-collapsible").trigger("collapse")})},_init:function(){this.refresh()},refresh:function(){var b=this.options,c=this.element.children(":jqmData(role='collapsible')");a.mobile.collapsible.prototype.enhance(c.not(".ui-collapsible"));c.each(function(){a(this).find(a.mobile.collapsible.prototype.options.heading).find("a").first().add(".ui-btn-inner").removeClass("ui-corner-top ui-corner-bottom")}); +c.first().find("a").first().addClass(b.corners?"ui-corner-top":"").find(".ui-btn-inner").addClass("ui-corner-top");c.last().jqmData("collapsible-last",true).find("a").first().addClass(b.corners?"ui-corner-bottom":"").find(".ui-btn-inner").addClass("ui-corner-bottom")}});a(k).bind("pagecreate create",function(b){a.mobile.collapsibleset.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.navbar",a.mobile.widget,{options:{iconpos:"top",grid:null,initSelector:":jqmData(role='navbar')"}, +_create:function(){var b=this.element,e=b.find("a"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:c;b.addClass("ui-navbar").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid});f||b.addClass("ui-navbar-noicons");e.buttonMarkup({corners:false,shadow:false,inline:true,iconpos:f});b.delegate("a","vclick",function(b){a(b.target).hasClass("ui-disabled")||(e.removeClass(a.mobile.activeBtnClass),a(this).addClass(a.mobile.activeBtnClass))});b.closest(".ui-page").bind("pagebeforeshow", +function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}});a(k).bind("pagecreate create",function(b){a.mobile.navbar.prototype.enhanceWithin(b.target)})})(jQuery);(function(a){var c={};a.widget("mobile.listview",a.mobile.widget,{options:{theme:null,countTheme:"c",headerTheme:"b",dividerTheme:"b",splitIcon:"arrow-r",splitTheme:"b",mini:false,inset:false,initSelector:":jqmData(role='listview')"},_create:function(){var a="";a+=this.options.inset?" ui-listview-inset ui-corner-all ui-shadow ": +"";a+=this.element.jqmData("mini")||this.options.mini===true?" ui-mini":"";this.element.addClass(function(c,f){return f+" ui-listview "+a});this.refresh(true)},_removeCorners:function(a,c){a=a.add(a.find(".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb"));c==="top"?a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl"):c==="bottom"?a.removeClass("ui-corner-bottom ui-corner-br ui-corner-bl"):a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl ui-corner-bottom ui-corner-br ui-corner-bl")},_refreshCorners:function(a){var c, +f;this.options.inset&&(c=this.element.children("li"),f=a?c.not(".ui-screen-hidden"):c.filter(":visible"),this._removeCorners(c),c=f.first().addClass("ui-corner-top"),c.add(c.find(".ui-btn-inner").not(".ui-li-link-alt span:first-child")).addClass("ui-corner-top").end().find(".ui-li-link-alt, .ui-li-link-alt span:first-child").addClass("ui-corner-tr").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-tl"),f=f.last().addClass("ui-corner-bottom"),f.add(f.find(".ui-btn-inner")).find(".ui-li-link-alt").addClass("ui-corner-br").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-bl")); +a||this.element.trigger("updatelayout")},_findFirstElementByTagName:function(a,c,f,d){var g={};for(g[f]=g[d]=true;a;){if(g[a.nodeName])return a;a=a[c]}return null},_getChildrenByTagName:function(b,c,f){var d=[],g={};g[c]=g[f]=true;for(b=b.firstChild;b;)g[b.nodeName]&&d.push(b),b=b.nextSibling;return a(d)},_addThumbClasses:function(b){var c,f,d=b.length;for(c=0;c<d;c++)f=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),f.length&&(f.addClass("ui-li-thumb"),a(this._findFirstElementByTagName(f[0].parentNode, +"parentNode","li","LI")).addClass(f.is(".ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb"))},refresh:function(b){this.parentPage=this.element.closest(".ui-page");this._createSubPages();var c=this.options,f=this.element,d=f.jqmData("dividertheme")||c.dividerTheme,g=f.jqmData("splittheme"),h=f.jqmData("spliticon"),j=this._getChildrenByTagName(f[0],"li","LI"),o=a.support.cssPseudoElement||!a.nodeName(f[0],"ol")?0:1,m={},p,l,r,n,q,t,x;o&&f.find(".ui-li-dec").remove();if(!c.theme)c.theme=a.mobile.getInheritedTheme(this.element, +"c");for(var u=0,w=j.length;u<w;u++){p=j.eq(u);l="ui-li";if(b||!p.hasClass("ui-li"))r=p.jqmData("theme")||c.theme,n=this._getChildrenByTagName(p[0],"a","A"),n.length?(t=p.jqmData("icon"),p.buttonMarkup({wrapperEls:"div",shadow:false,corners:false,iconpos:"right",icon:n.length>1||t===false?false:t||"arrow-r",theme:r}),t!=false&&n.length==1&&p.addClass("ui-li-has-arrow"),n.first().removeClass("ui-link").addClass("ui-link-inherit"),n.length>1&&(l+=" ui-li-has-alt",n=n.last(),q=g||n.jqmData("theme")|| +c.splitTheme,x=n.jqmData("icon"),n.appendTo(p).attr("title",n.getEncodedText()).addClass("ui-li-link-alt").empty().buttonMarkup({shadow:false,corners:false,theme:r,icon:false,iconpos:false}).find(".ui-btn-inner").append(a(k.createElement("span")).buttonMarkup({shadow:true,corners:true,theme:q,iconpos:"notext",icon:x||t||h||c.splitIcon})))):p.jqmData("role")==="list-divider"?(l+=" ui-li-divider ui-bar-"+d,p.attr("role","heading"),o&&(o=1)):l+=" ui-li-static ui-body-"+r;o&&l.indexOf("ui-li-divider")< +0&&(r=p.is(".ui-li-static:first")?p:p.find(".ui-link-inherit"),r.addClass("ui-li-jsnumbering").prepend("<span class='ui-li-dec'>"+o++ +". </span>"));m[l]||(m[l]=[]);m[l].push(p[0])}for(l in m)a(m[l]).addClass(l).children(".ui-btn-inner").addClass(l);f.find("h1, h2, h3, h4, h5, h6").addClass("ui-li-heading").end().find("p, dl").addClass("ui-li-desc").end().find(".ui-li-aside").each(function(){var b=a(this);b.prependTo(b.parent())}).end().find(".ui-li-count").each(function(){a(this).closest("li").addClass("ui-li-has-count")}).addClass("ui-btn-up-"+ +(f.jqmData("counttheme")||this.options.countTheme)+" ui-btn-corner-all");this._addThumbClasses(j);this._addThumbClasses(f.find(".ui-link-inherit"));this._refreshCorners(b)},_idStringEscape:function(a){return a.replace(/[^a-zA-Z0-9]/g,"-")},_createSubPages:function(){var b=this.element,e=b.closest(".ui-page"),f=e.jqmData("url"),d=f||e[0][a.expando],g=b.attr("id"),h=this.options,j="data-"+a.mobile.ns,k=this,m=e.find(":jqmData(role='footer')").jqmData("id"),p;typeof c[d]==="undefined"&&(c[d]=-1);g=g|| +++c[d];a(b.find("li>ul, li>ol").toArray().reverse()).each(function(c){var d=a(this),e=d.attr("id")||g+"-"+c,c=d.parent(),k=a(d.prevAll().toArray().reverse()),k=k.length?k:a("<span>"+a.trim(c.contents()[0].nodeValue)+"</span>"),o=k.first().getEncodedText(),e=(f||"")+"&"+a.mobile.subPageUrlKey+"="+e,x=d.jqmData("theme")||h.theme,u=d.jqmData("counttheme")||b.jqmData("counttheme")||h.countTheme;p=true;d.detach().wrap("<div "+j+"role='page' "+j+"url='"+e+"' "+j+"theme='"+x+"' "+j+"count-theme='"+u+"'><div "+ +j+"role='content'></div></div>").parent().before("<div "+j+"role='header' "+j+"theme='"+h.headerTheme+"'><div class='ui-title'>"+o+"</div></div>").after(m?a("<div "+j+"role='footer' "+j+"id='"+m+"'>"):"").parent().appendTo(a.mobile.pageContainer).page();d=c.find("a:first");d.length||(d=a("<a/>").html(k||o).prependTo(c.empty()));d.attr("href","#"+e)}).listview();p&&e.is(":jqmData(external-page='true')")&&e.data("page").options.domCache===false&&e.unbind("pagehide.remove").bind("pagehide.remove",function(b, +c){var d=c.nextPage;c.nextPage&&(d=d.jqmData("url"),d.indexOf(f+"&"+a.mobile.subPageUrlKey)!==0&&(k.childPages().remove(),e.remove()))})},childPages:function(){var b=this.parentPage.jqmData("url");return a(":jqmData(url^='"+b+"&"+a.mobile.subPageUrlKey+"')")}});a(k).bind("pagecreate create",function(b){a.mobile.listview.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.checkboxradio",a.mobile.widget,{options:{theme:null,initSelector:"input[type='checkbox'],input[type='radio']"}, +_create:function(){var b=this,e=this.element,f=a(e).closest("label"),d=f.length?f:a(e).closest("form,fieldset,:jqmData(role='page'),:jqmData(role='dialog')").find("label").filter("[for='"+e[0].id+"']"),g=e[0].type,f=e.jqmData("mini")||e.closest("form,fieldset").jqmData("mini"),h=g+"-on",j=g+"-off",o=e.parents(":jqmData(type='horizontal')").length?c:j,m=e.jqmData("iconpos")||e.closest("form,fieldset").jqmData("iconpos");if(!(g!=="checkbox"&&g!=="radio")){a.extend(this,{label:d,inputtype:g,checkedClass:"ui-"+ +h+(o?"":" "+a.mobile.activeBtnClass),uncheckedClass:"ui-"+j,checkedicon:"ui-icon-"+h,uncheckedicon:"ui-icon-"+j});if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");d.buttonMarkup({theme:this.options.theme,icon:o,shadow:false,mini:f,iconpos:m});f=k.createElement("div");f.className="ui-"+g;e.add(d).wrapAll(f);d.bind({vmouseover:function(b){a(this).parent().is(".ui-disabled")&&b.stopPropagation()},vclick:function(a){if(e.is(":disabled"))a.preventDefault();else return b._cacheVals(), +e.prop("checked",g==="radio"&&true||!e.prop("checked")),e.triggerHandler("click"),b._getInputSet().not(e).prop("checked",false),b._updateAll(),false}});e.bind({vmousedown:function(){b._cacheVals()},vclick:function(){var c=a(this);c.is(":checked")?(c.prop("checked",true),b._getInputSet().not(c).prop("checked",false)):c.prop("checked",false);b._updateAll()},focus:function(){d.addClass(a.mobile.focusClass)},blur:function(){d.removeClass(a.mobile.focusClass)}});this.refresh()}},_cacheVals:function(){this._getInputSet().each(function(){a(this).jqmData("cacheVal", +this.checked)})},_getInputSet:function(){return this.inputtype==="checkbox"?this.element:this.element.closest("form,fieldset,:jqmData(role='page')").find("input[name='"+this.element[0].name+"'][type='"+this.inputtype+"']")},_updateAll:function(){var b=this;this._getInputSet().each(function(){var c=a(this);(this.checked||b.inputtype==="checkbox")&&c.trigger("change")}).checkboxradio("refresh")},refresh:function(){var a=this.element[0],c=this.label,f=c.find(".ui-icon");a.checked?(c.addClass(this.checkedClass).removeClass(this.uncheckedClass), +f.addClass(this.checkedicon).removeClass(this.uncheckedicon)):(c.removeClass(this.checkedClass).addClass(this.uncheckedClass),f.removeClass(this.checkedicon).addClass(this.uncheckedicon));a.disabled?this.disable():this.enable()},disable:function(){this.element.prop("disabled",true).parent().addClass("ui-disabled")},enable:function(){this.element.prop("disabled",false).parent().removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(b){a.mobile.checkboxradio.prototype.enhanceWithin(b.target, +true)})})(jQuery);(function(a,c){a.widget("mobile.button",a.mobile.widget,{options:{theme:null,icon:null,iconpos:null,inline:false,corners:true,shadow:true,iconshadow:true,initSelector:"button, [type='button'], [type='submit'], [type='reset'], [type='image']",mini:false},_create:function(){var b=this.element,e,f=this.options,d;d="";var g;if(b[0].tagName==="A")!b.hasClass("ui-btn")&&b.buttonMarkup();else{if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");~b[0].className.indexOf("ui-btn-left")&& +(d="ui-btn-left");~b[0].className.indexOf("ui-btn-right")&&(d="ui-btn-right");e=this.button=a("<div></div>").text(b.text()||b.val()).insertBefore(b).buttonMarkup({theme:f.theme,icon:f.icon,iconpos:f.iconpos,inline:f.inline,corners:f.corners,shadow:f.shadow,iconshadow:f.iconshadow,mini:f.mini}).addClass(d).append(b.addClass("ui-btn-hidden"));f=b.attr("type");d=b.attr("name");f!=="button"&&f!=="reset"&&d&&b.bind("vclick",function(){g===c&&(g=a("<input>",{type:"hidden",name:b.attr("name"),value:b.attr("value")}).insertBefore(b), +a(k).one("submit",function(){g.remove();g=c}))});b.bind({focus:function(){e.addClass(a.mobile.focusClass)},blur:function(){e.removeClass(a.mobile.focusClass)}});this.refresh()}},enable:function(){this.element.attr("disabled",false);this.button.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.button.addClass("ui-disabled").attr("aria-disabled",true);return this._setOption("disabled",true)},refresh:function(){var b= +this.element;b.prop("disabled")?this.disable():this.enable();a(this.button.data("buttonElements").text).text(b.text()||b.val())}});a(k).bind("pagecreate create",function(b){a.mobile.button.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.fn.controlgroup=function(c){function b(a,b){a.removeClass("ui-btn-corner-all ui-shadow").eq(0).addClass(b[0]).end().last().addClass(b[1]).addClass("ui-controlgroup-last")}return this.each(function(){var e=a(this),f=a.extend({direction:e.jqmData("type")|| +"vertical",shadow:false,excludeInvisible:true,mini:e.jqmData("mini")},c),d=e.children("legend"),g=f.direction=="horizontal"?["ui-corner-left","ui-corner-right"]:["ui-corner-top","ui-corner-bottom"];e.find("input").first().attr("type");d.length&&(e.wrapInner("<div class='ui-controlgroup-controls'></div>"),a("<div role='heading' class='ui-controlgroup-label'>"+d.html()+"</div>").insertBefore(e.children(0)),d.remove());e.addClass("ui-corner-all ui-controlgroup ui-controlgroup-"+f.direction);b(e.find(".ui-btn"+ +(f.excludeInvisible?":visible":"")).not(".ui-slider-handle"),g);b(e.find(".ui-btn-inner"),g);f.shadow&&e.addClass("ui-shadow");f.mini&&e.addClass("ui-mini")})}})(jQuery);(function(a){a(k).bind("pagecreate create",function(c){a(c.target).find("a").jqmEnhanceable().not(".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")})})(jQuery);(function(a){var c=a("meta[name=viewport]"),b=c.attr("content"),e=b+",maximum-scale=1, user-scalable=no",f=b+",maximum-scale=10, user-scalable=yes", +d=/(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(b);a.mobile.zoom=a.extend({},{enabled:!d,locked:false,disable:function(b){if(!d&&!a.mobile.zoom.locked)c.attr("content",e),a.mobile.zoom.enabled=false,a.mobile.zoom.locked=b||false},enable:function(b){if(!d&&(!a.mobile.zoom.locked||b===true))c.attr("content",f),a.mobile.zoom.enabled=true,a.mobile.zoom.locked=false},restore:function(){if(!d)c.attr("content",b),a.mobile.zoom.enabled=true}})})(jQuery);(function(a){a.widget("mobile.textinput", +a.mobile.widget,{options:{theme:null,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,initSelector:"input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type])", +clearSearchButtonText:"clear text"},_create:function(){var c=this.element,b=this.options,e=b.theme||a.mobile.getInheritedTheme(this.element,"c"),f=" ui-body-"+e,d=c.jqmData("mini")==true,g=d?" ui-mini":"",h,j;a("label[for='"+c.attr("id")+"']").addClass("ui-input-text");h=c.addClass("ui-input-text ui-body-"+e);typeof c[0].autocorrect!=="undefined"&&!a.support.touchOverflow&&(c[0].setAttribute("autocorrect","off"),c[0].setAttribute("autocomplete","off"));c.is("[type='search'],:jqmData(type='search')")? +(h=c.wrap("<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield"+f+g+"'></div>").parent(),j=a("<a href='#' class='ui-input-clear' title='"+b.clearSearchButtonText+"'>"+b.clearSearchButtonText+"</a>").bind("click",function(a){c.val("").focus().trigger("change");j.addClass("ui-input-clear-hidden");a.preventDefault()}).appendTo(h).buttonMarkup({icon:"delete",iconpos:"notext",corners:true,shadow:true,mini:d}),e=function(){setTimeout(function(){j.toggleClass("ui-input-clear-hidden", +!c.val())},0)},e(),c.bind("paste cut keyup focus change blur",e)):c.addClass("ui-corner-all ui-shadow-inset"+f+g);c.focus(function(){h.addClass(a.mobile.focusClass)}).blur(function(){h.removeClass(a.mobile.focusClass)}).bind("focus",function(){b.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("blur",function(){b.preventFocusZoom&&a.mobile.zoom.enable(true)});if(c.is("textarea")){var o=function(){var a=c[0].scrollHeight;c[0].clientHeight<a&&c.height(a+15)},m;c.keyup(function(){clearTimeout(m); +m=setTimeout(o,100)});a(k).one("pagechange",o);a.trim(c.val())&&a(s).load(o)}},disable:function(){(this.element.attr("disabled",true).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).addClass("ui-disabled")},enable:function(){(this.element.attr("disabled",false).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(c){a.mobile.textinput.prototype.enhanceWithin(c.target, +true)})})(jQuery);(function(a){a.mobile.listview.prototype.options.filter=false;a.mobile.listview.prototype.options.filterPlaceholder="Filter items...";a.mobile.listview.prototype.options.filterTheme="c";a.mobile.listview.prototype.options.filterCallback=function(a,b){return a.toLowerCase().indexOf(b)===-1};a(k).delegate(":jqmData(role='listview')","listviewcreate",function(){var c=a(this),b=c.data("listview");if(b.options.filter){var e=a("<form>",{"class":"ui-listview-filter ui-bar-"+b.options.filterTheme, +role:"search"});a("<input>",{placeholder:b.options.filterPlaceholder}).attr("data-"+a.mobile.ns+"type","search").jqmData("lastval","").bind("keyup change",function(){var e=a(this),d=this.value.toLowerCase(),g=null,g=e.jqmData("lastval")+"",h=false,j="";e.jqmData("lastval",d);g=d.length<g.length||d.indexOf(g)!==0?c.children():c.children(":not(.ui-screen-hidden)");if(d){for(var k=g.length-1;k>=0;k--)e=a(g[k]),j=e.jqmData("filtertext")||e.text(),e.is("li:jqmData(role=list-divider)")?(e.toggleClass("ui-filter-hidequeue", +!h),h=false):b.options.filterCallback(j,d)?e.toggleClass("ui-filter-hidequeue",true):h=true;g.filter(":not(.ui-filter-hidequeue)").toggleClass("ui-screen-hidden",false);g.filter(".ui-filter-hidequeue").toggleClass("ui-screen-hidden",true).toggleClass("ui-filter-hidequeue",false)}else g.toggleClass("ui-screen-hidden",false);b._refreshCorners()}).appendTo(e).textinput();b.options.inset&&e.addClass("ui-listview-filter-inset");e.bind("submit",function(){return false}).insertBefore(c)}})})(jQuery);(function(a, +c){a.widget("mobile.slider",a.mobile.widget,{options:{theme:null,trackTheme:null,disabled:false,initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",mini:false},_create:function(){var b=this,e=this.element,f=a.mobile.getInheritedTheme(e,"c"),d=this.options.theme||f,f=this.options.trackTheme||f,g=e[0].nodeName.toLowerCase(),h=g=="select"?"ui-slider-switch":"",j=e.attr("id"),o=j+"-label",j=a("[for='"+j+"']").attr("id",o),m=function(){return g=="input"?parseFloat(e.val()): +e[0].selectedIndex},p=g=="input"?parseFloat(e.attr("min")):0,l=g=="input"?parseFloat(e.attr("max")):e.find("option").length-1,r=s.parseFloat(e.attr("step")||1),n=this.options.inline||e.jqmData("inline")==true?" ui-slider-inline":"",q=this.options.mini||e.jqmData("mini")?" ui-slider-mini":"",t=k.createElement("a"),x=a(t),u=k.createElement("div"),w=a(u),v=e.jqmData("highlight")&&g!="select"?function(){var b=k.createElement("div");b.className="ui-slider-bg ui-btn-active ui-btn-corner-all";return a(b).prependTo(w)}(): +false;t.setAttribute("href","#");u.setAttribute("role","application");u.className=["ui-slider ",h," ui-btn-down-",f," ui-btn-corner-all",n,q].join("");t.className="ui-slider-handle";u.appendChild(t);x.buttonMarkup({corners:true,theme:d,shadow:true}).attr({role:"slider","aria-valuemin":p,"aria-valuemax":l,"aria-valuenow":m(),"aria-valuetext":m(),title:m(),"aria-labelledby":o});a.extend(this,{slider:w,handle:x,valuebg:v,dragging:false,beforeStart:null,userModified:false,mouseMoved:false});if(g=="select"){d= +k.createElement("div");d.className="ui-slider-inneroffset";h=0;for(o=u.childNodes.length;h<o;h++)d.appendChild(u.childNodes[h]);u.appendChild(d);x.addClass("ui-slider-handle-snapping");u=e.find("option");d=0;for(h=u.length;d<h;d++)o=!d?"b":"a",n=!d?" ui-btn-down-"+f:" "+a.mobile.activeBtnClass,k.createElement("div"),q=k.createElement("span"),q.className=["ui-slider-label ui-slider-label-",o,n," ui-btn-corner-all"].join(""),q.setAttribute("role","img"),q.appendChild(k.createTextNode(u[d].innerHTML)), +a(q).prependTo(w);b._labels=a(".ui-slider-label",w)}j.addClass("ui-slider");e.addClass(g==="input"?"ui-slider-input":"ui-slider-switch").change(function(){b.mouseMoved||b.refresh(m(),true)}).keyup(function(){b.refresh(m(),true,true)}).blur(function(){b.refresh(m(),true)});a(k).bind("vmousemove",function(a){if(b.dragging)return b.mouseMoved=true,g==="select"&&x.removeClass("ui-slider-handle-snapping"),b.refresh(a),b.userModified=b.beforeStart!==e[0].selectedIndex,false});w.bind("vmousedown",function(a){b.dragging= +true;b.userModified=false;b.mouseMoved=false;if(g==="select")b.beforeStart=e[0].selectedIndex;b.refresh(a);return false}).bind("vclick",false);w.add(k).bind("vmouseup",function(){if(b.dragging)return b.dragging=false,g==="select"&&(x.addClass("ui-slider-handle-snapping"),b.mouseMoved?b.userModified?b.refresh(b.beforeStart==0?1:0):b.refresh(b.beforeStart):b.refresh(b.beforeStart==0?1:0)),b.mouseMoved=false});w.insertAfter(e);g=="select"&&this.handle.bind({focus:function(){w.addClass(a.mobile.focusClass)}, +blur:function(){w.removeClass(a.mobile.focusClass)}});this.handle.bind({vmousedown:function(){a(this).focus()},vclick:false,keydown:function(c){var d=m();if(!b.options.disabled){switch(c.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:if(c.preventDefault(),!b._keySliding)b._keySliding=true,a(this).addClass("ui-state-active")}switch(c.keyCode){case a.mobile.keyCode.HOME:b.refresh(p); +break;case a.mobile.keyCode.END:b.refresh(l);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:b.refresh(d+r);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.refresh(d-r)}}},keyup:function(){if(b._keySliding)b._keySliding=false,a(this).removeClass("ui-state-active")}});this.refresh(c,c,true)},refresh:function(b,c,f){(this.options.disabled||this.element.attr("disabled"))&&this.disable();var d=this.element,g=d[0].nodeName.toLowerCase(), +h=g==="input"?parseFloat(d.attr("min")):0,j=g==="input"?parseFloat(d.attr("max")):d.find("option").length-1,k=g==="input"&&parseFloat(d.attr("step"))>0?parseFloat(d.attr("step")):1;if(typeof b==="object"){if(!this.dragging||b.pageX<this.slider.offset().left-8||b.pageX>this.slider.offset().left+this.slider.width()+8)return;b=Math.round((b.pageX-this.slider.offset().left)/this.slider.width()*100)}else b==null&&(b=g==="input"?parseFloat(d.val()||0):d[0].selectedIndex),b=(parseFloat(b)-h)/(j-h)*100;if(!isNaN(b)){b< +0&&(b=0);b>100&&(b=100);var m=b/100*(j-h)+h,p=(m-h)%k;m-=p;Math.abs(p)*2>=k&&(m+=p>0?k:-k);m=parseFloat(m.toFixed(5));m<h&&(m=h);m>j&&(m=j);this.handle.css("left",b+"%");this.handle.attr({"aria-valuenow":g==="input"?m:d.find("option").eq(m).attr("value"),"aria-valuetext":g==="input"?m:d.find("option").eq(m).getEncodedText(),title:g==="input"?m:d.find("option").eq(m).getEncodedText()});this.valuebg&&this.valuebg.css("width",b+"%");if(this._labels){var h=this.handle.width()/this.slider.width()*100, +l=b&&h+(100-h)*b/100,r=b===100?0:Math.min(h+100-l,100);this._labels.each(function(){var b=a(this).is(".ui-slider-label-a");a(this).width((b?l:r)+"%")})}if(!f)f=false,g==="input"?(f=d.val()!==m,d.val(m)):(f=d[0].selectedIndex!==m,d[0].selectedIndex=m),!c&&f&&d.trigger("change")}},enable:function(){this.element.attr("disabled",false);this.slider.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.slider.addClass("ui-disabled").attr("aria-disabled", +true);return this._setOption("disabled",true)}});a(k).bind("pagecreate create",function(b){a.mobile.slider.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.widget("mobile.selectmenu",a.mobile.widget,{options:{theme:null,disabled:false,icon:"arrow-d",iconpos:"right",inline:false,corners:true,shadow:true,iconshadow:true,overlayTheme:"a",hidePlaceholderMenuItems:true,closeText:"Close",nativeMenu:true,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")> +-1,initSelector:"select:not(:jqmData(role='slider'))",mini:false},_button:function(){return a("<div/>")},_setDisabled:function(a){this.element.attr("disabled",a);this.button.attr("aria-disabled",a);return this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var c="";~this.element[0].className.indexOf("ui-btn-left")&&(c=" ui-btn-left");~this.element[0].className.indexOf("ui-btn-right")&& +(c=" ui-btn-right");this.select=this.element.wrap("<div class='ui-select"+c+"'>");this.selectID=this.select.attr("id");this.label=a("label[for='"+this.selectID+"']").addClass("ui-select");this.isMultiple=this.select[0].multiple;if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.select,"c")},_create:function(){this._preExtension();this._trigger("beforeCreate");this.button=this._button();var c=this,b=this.options,e=this.button.text(a(this.select[0].options.item(this.select[0].selectedIndex== +-1?0:this.select[0].selectedIndex)).text()).insertBefore(this.select).buttonMarkup({theme:b.theme,icon:b.icon,iconpos:b.iconpos,inline:b.inline,corners:b.corners,shadow:b.shadow,iconshadow:b.iconshadow,mini:b.mini});b.nativeMenu&&s.opera&&s.opera.version&&this.select.addClass("ui-select-nativeonly");if(this.isMultiple)this.buttonCount=a("<span>").addClass("ui-li-count ui-btn-up-c ui-btn-corner-all").hide().appendTo(e.addClass("ui-li-has-count"));(b.disabled||this.element.attr("disabled"))&&this.disable(); +this.select.change(function(){c.refresh()});this.build()},build:function(){var c=this;this.select.appendTo(c.button).bind("vmousedown",function(){c.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){c.button.addClass(a.mobile.focusClass)}).bind("blur",function(){c.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){c.button.trigger("vmouseover")}).bind("vmousemove",function(){c.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){c.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}).bind("change blur", +function(){c.button.removeClass("ui-btn-down-"+c.options.theme)});c.button.bind("vmousedown",function(){c.options.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("mouseup",function(){c.options.preventFocusZoom&&a.mobile.zoom.enable(true)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var c=this,b=this.selected();this.button.find(".ui-btn-text").text(function(){return!c.isMultiple? +b.text():b.length?b.map(function(){return a(this).text()}).get().join(", "):c.placeholder})},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},refresh:function(){this.setButtonText();this.setButtonCount()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(true);this.button.addClass("ui-disabled")},enable:function(){this._setDisabled(false);this.button.removeClass("ui-disabled")}});a(k).bind("pagecreate create", +function(c){a.mobile.selectmenu.prototype.enhanceWithin(c.target,true)})})(jQuery);(function(a){var c=function(b){var c=b.selectID,f=b.label,d=b.select.closest(".ui-page"),g=a("<div>",{"class":"ui-selectmenu-screen ui-screen-hidden"}).appendTo(d),h=b._selectOptions(),j=b.isMultiple=b.select[0].multiple,o=c+"-button",m=c+"-menu",p=a("<div data-"+a.mobile.ns+"role='dialog' data-"+a.mobile.ns+"theme='"+b.options.theme+"' data-"+a.mobile.ns+"overlay-theme='"+b.options.overlayTheme+"'><div data-"+a.mobile.ns+ +"role='header'><div class='ui-title'>"+f.getEncodedText()+"</div></div><div data-"+a.mobile.ns+"role='content'></div></div>"),l=a("<div>",{"class":"ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-"+b.options.overlayTheme+" "+a.mobile.defaultDialogTransition}).insertAfter(g),r=a("<ul>",{"class":"ui-selectmenu-list",id:m,role:"listbox","aria-labelledby":o}).attr("data-"+a.mobile.ns+"theme",b.options.theme).appendTo(l),n=a("<div>",{"class":"ui-header ui-bar-"+b.options.theme}).prependTo(l), +q=a("<h1>",{"class":"ui-title"}).appendTo(n),t;b.isMultiple&&(t=a("<a>",{text:b.options.closeText,href:"#","class":"ui-btn-left"}).attr("data-"+a.mobile.ns+"iconpos","notext").attr("data-"+a.mobile.ns+"icon","delete").appendTo(n).buttonMarkup());a.extend(b,{select:b.select,selectID:c,buttonId:o,menuId:m,thisPage:d,menuPage:p,label:f,screen:g,selectOptions:h,isMultiple:j,theme:b.options.theme,listbox:l,list:r,header:n,headerTitle:q,headerClose:t,menuPageContent:void 0,menuPageClose:void 0,placeholder:"", +build:function(){var c=this;c.refresh();c.select.attr("tabindex","-1").focus(function(){a(this).blur();c.button.focus()});c.button.bind("vclick keydown",function(b){if(b.type=="vclick"||b.keyCode&&(b.keyCode===a.mobile.keyCode.ENTER||b.keyCode===a.mobile.keyCode.SPACE))c.open(),b.preventDefault()});c.list.attr("role","listbox").bind("focusin",function(b){a(b.target).attr("tabindex","0").trigger("vmouseover")}).bind("focusout",function(b){a(b.target).attr("tabindex","-1").trigger("vmouseout")}).delegate("li:not(.ui-disabled, .ui-li-divider)", +"click",function(b){var d=c.select[0].selectedIndex,e=c.list.find("li:not(.ui-li-divider)").index(this),f=c._selectOptions().eq(e)[0];f.selected=c.isMultiple?!f.selected:true;c.isMultiple&&a(this).find(".ui-icon").toggleClass("ui-icon-checkbox-on",f.selected).toggleClass("ui-icon-checkbox-off",!f.selected);(c.isMultiple||d!==e)&&c.select.trigger("change");c.isMultiple||c.close();b.preventDefault()}).keydown(function(c){var d=a(c.target),e=d.closest("li");switch(c.keyCode){case 38:return c=e.prev().not(".ui-selectmenu-placeholder"), +c.is(".ui-li-divider")&&(c=c.prev()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 40:return c=e.next(),c.is(".ui-li-divider")&&(c=c.next()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 13:case 32:return d.trigger("click"),false}});c.menuPage.bind("pagehide",function(){c.list.appendTo(c.listbox);c._focusButton();a.mobile._bindPageRemove.call(c.thisPage)}); +c.screen.bind("vclick",function(){c.close()});c.isMultiple&&c.headerClose.click(function(){if(c.menuType=="overlay")return c.close(),false});c.thisPage.addDependents(this.menuPage)},_isRebuildRequired:function(){var a=this.list.find("li");return this._selectOptions().text()!==a.text()},refresh:function(b){var c=this;this._selectOptions();this.selected();var d=this.selectedIndices();(b||this._isRebuildRequired())&&c._buildList();c.setButtonText();c.setButtonCount();c.list.find("li:not(.ui-li-divider)").removeClass(a.mobile.activeBtnClass).attr("aria-selected", +false).each(function(b){a.inArray(b,d)>-1&&(b=a(this),b.attr("aria-selected",true),c.isMultiple?b.find(".ui-icon").removeClass("ui-icon-checkbox-off").addClass("ui-icon-checkbox-on"):b.is(".ui-selectmenu-placeholder")?b.next().addClass(a.mobile.activeBtnClass):b.addClass(a.mobile.activeBtnClass))})},close:function(){if(!this.options.disabled&&this.isOpen)this.menuType=="page"?s.history.back():(this.screen.addClass("ui-screen-hidden"),this.listbox.addClass("ui-selectmenu-hidden").removeAttr("style").removeClass("in"), +this.list.appendTo(this.listbox),this._focusButton()),this.isOpen=false},open:function(){function b(){c.list.find("."+a.mobile.activeBtnClass+" a").focus()}if(!this.options.disabled){var c=this,d=a(s),e=c.list.parent(),f=e.outerHeight(),e=e.outerWidth();a(".ui-page-active");var g=d.scrollTop(),j=c.button.offset().top,h=d.height(),d=d.width();c.button.addClass(a.mobile.activeBtnClass);setTimeout(function(){c.button.removeClass(a.mobile.activeBtnClass)},300);if(f>h-80||!a.support.scrollTop){c.menuPage.appendTo(a.mobile.pageContainer).page(); +c.menuPageContent=p.find(".ui-content");c.menuPageClose=p.find(".ui-header a");c.thisPage.unbind("pagehide.remove");if(g==0&&j>h)c.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",j)});c.menuPage.one("pageshow",function(){b();c.isOpen=true});c.menuType="page";c.menuPageContent.append(c.list);c.menuPage.find("div .ui-title").text(c.label.text());a.mobile.changePage(c.menuPage,{transition:a.mobile.defaultDialogTransition})}else{c.menuType="overlay";c.screen.height(a(k).height()).removeClass("ui-screen-hidden"); +var l=j-g,m=g+h-j,n=f/2,o=parseFloat(c.list.parent().css("max-width")),f=l>f/2&&m>f/2?j+c.button.outerHeight()/2-n:l>m?g+h-f-30:g+30;e<o?g=(d-e)/2:(g=c.button.offset().left+c.button.outerWidth()/2-e/2,g<30?g=30:g+e>d&&(g=d-e-30));c.listbox.append(c.list).removeClass("ui-selectmenu-hidden").css({top:f,left:g}).addClass("in");b();c.isOpen=true}}},_buildList:function(){var b=this.options,c=this.placeholder,d=true,e=this.isMultiple?"checkbox-off":"false";this.list.empty().filter(".ui-listview").listview("destroy"); +var f=this.select.find("option"),g=f.length,j=this.select[0],h="data-"+a.mobile.ns,l=h+"option-index",m=h+"icon";h+="role";for(var n=k.createDocumentFragment(),o,p=0;p<g;p++){var r=f[p],q=a(r),s=r.parentNode,t=q.text(),D=k.createElement("a"),J=[];D.setAttribute("href","#");D.appendChild(k.createTextNode(t));s!==j&&s.nodeName.toLowerCase()==="optgroup"&&(s=s.getAttribute("label"),s!=o&&(o=k.createElement("li"),o.setAttribute(h,"list-divider"),o.setAttribute("role","option"),o.setAttribute("tabindex", +"-1"),o.appendChild(k.createTextNode(s)),n.appendChild(o),o=s));if(d&&(!r.getAttribute("value")||t.length==0||q.jqmData("placeholder")))if(d=false,b.hidePlaceholderMenuItems&&J.push("ui-selectmenu-placeholder"),!c)c=this.placeholder=t;q=k.createElement("li");r.disabled&&(J.push("ui-disabled"),q.setAttribute("aria-disabled",true));q.setAttribute(l,p);q.setAttribute(m,e);q.className=J.join(" ");q.setAttribute("role","option");D.setAttribute("tabindex","-1");q.appendChild(D);n.appendChild(q)}this.list[0].appendChild(n); +!this.isMultiple&&!c.length?this.header.hide():this.headerTitle.text(this.placeholder);this.list.listview()},_button:function(){return a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})}})};a(k).bind("selectmenubeforecreate",function(b){b=a(b.target).data("selectmenu");b.options.nativeMenu||c(b)})})(jQuery);(function(a){a.widget("mobile.fixedtoolbar",a.mobile.widget,{options:{visibleOnPageShow:true,disablePageZoom:true,transition:"slide",fullscreen:false, +tapToggle:true,tapToggleBlacklist:"a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",hideDuringFocus:"input, textarea, select",updatePagePadding:true,trackPersistentToolbars:true,supportBlacklist:function(){var a=s,b=navigator.userAgent,e=navigator.platform,f=b.match(/AppleWebKit\/([0-9]+)/),f=!!f&&f[1],d=b.match(/Fennec\/([0-9]+)/),d=!!d&&d[1],g=b.match(/Opera Mobi\/([0-9]+)/),h=!!g&&g[1];return(e.indexOf("iPhone")>-1||e.indexOf("iPad")>-1||e.indexOf("iPod")>-1)&&f&&f<534||a.operamini&& +{}.toString.call(a.operamini)==="[object OperaMini]"||g&&h<7458||b.indexOf("Android")>-1&&f&&f<533||d&&d<6||"palmGetResource"in s&&f&&f<534||b.indexOf("MeeGo")>-1&&b.indexOf("NokiaBrowser/8.5.0")>-1?true:false},initSelector:":jqmData(position='fixed')"},_create:function(){var a=this.options,b=this.element,e=b.is(":jqmData(role='header')")?"header":"footer",f=b.closest(".ui-page");a.supportBlacklist()?this.destroy():(b.addClass("ui-"+e+"-fixed"),a.fullscreen?(b.addClass("ui-"+e+"-fullscreen"),f.addClass("ui-page-"+ +e+"-fullscreen")):f.addClass("ui-page-"+e+"-fixed"),this._addTransitionClass(),this._bindPageEvents(),this._bindToggleHandlers())},_addTransitionClass:function(){var a=this.options.transition;a&&a!=="none"&&(a==="slide"&&(a=this.element.is(".ui-header")?"slidedown":"slideup"),this.element.addClass(a))},_bindPageEvents:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("pagebeforeshow",function(){b.disablePageZoom&&a.mobile.zoom.disable(true);b.visibleOnPageShow||c.hide(true)}).bind("webkitAnimationStart animationstart updatelayout", +function(){b.updatePagePadding&&c.updatePagePadding()}).bind("pageshow",function(){c.updatePagePadding();b.updatePagePadding&&a(s).bind("throttledresize."+c.widgetName,function(){c.updatePagePadding()})}).bind("pagebeforehide",function(e,f){b.disablePageZoom&&a.mobile.zoom.enable(true);b.updatePagePadding&&a(s).unbind("throttledresize."+c.widgetName);if(b.trackPersistentToolbars){var d=a(".ui-footer-fixed:jqmData(id)",this),g=a(".ui-header-fixed:jqmData(id)",this),h=d.length&&f.nextPage&&a(".ui-footer-fixed:jqmData(id='"+ +d.jqmData("id")+"')",f.nextPage),j=g.length&&f.nextPage&&a(".ui-header-fixed:jqmData(id='"+g.jqmData("id")+"')",f.nextPage),h=h||a();if(h.length||j.length)h.add(j).appendTo(a.mobile.pageContainer),f.nextPage.one("pageshow",function(){h.add(j).appendTo(this)})}})},_visible:true,updatePagePadding:function(){var a=this.element,b=a.is(".ui-header");this.options.fullscreen||a.closest(".ui-page").css("padding-"+(b?"top":"bottom"),a.outerHeight())},_useTransition:function(c){var b=this.element,e=a(s).scrollTop(), +f=b.height(),d=b.closest(".ui-page").height(),g=a.mobile.getScreenHeight(),b=b.is(":jqmData(role='header')")?"header":"footer";return!c&&(this.options.transition&&this.options.transition!=="none"&&(b==="header"&&!this.options.fullscreen&&e>f||b==="footer"&&!this.options.fullscreen&&e+g<d-f)||this.options.fullscreen)},show:function(a){var b=this.element;this._useTransition(a)?b.removeClass("out ui-fixed-hidden").addClass("in"):b.removeClass("ui-fixed-hidden");this._visible=true},hide:function(a){var b= +this.element,e="out"+(this.options.transition==="slide"?" reverse":"");this._useTransition(a)?b.addClass(e).removeClass("in").animationComplete(function(){b.addClass("ui-fixed-hidden").removeClass(e)}):b.addClass("ui-fixed-hidden").removeClass(e);this._visible=false},toggle:function(){this[this._visible?"hide":"show"]()},_bindToggleHandlers:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("vclick",function(e){b.tapToggle&&!a(e.target).closest(b.tapToggleBlacklist).length&&c.toggle()}).bind("focusin focusout", +function(e){if(screen.width<500&&a(e.target).is(b.hideDuringFocus)&&!a(e.target).closest(".ui-header-fixed, .ui-footer-fixed").length)c[e.type==="focusin"&&c._visible?"hide":"show"]()})},destroy:function(){this.element.removeClass("ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden");this.element.closest(".ui-page").removeClass("ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen")}});a(k).bind("pagecreate create", +function(c){a(c.target).jqmData("fullscreen")&&a(a.mobile.fixedtoolbar.prototype.options.initSelector,c.target).not(":jqmData(fullscreen)").jqmData("fullscreen",true);a.mobile.fixedtoolbar.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){if(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1){var b=a.mobile.zoom,e,f,d,g,h;a(c).bind("orientationchange.iosorientationfix",b.enable).bind("devicemotion.iosorientationfix",function(a){e=a.originalEvent; +h=e.accelerationIncludingGravity;f=Math.abs(h.x);d=Math.abs(h.y);g=Math.abs(h.z);!c.orientation&&(f>7||(g>6&&d<8||g<8&&d>6)&&f>5)?b.enabled&&b.disable():b.enabled||b.enable()})}})(jQuery,this);(function(a,c){function b(){var b=a("."+a.mobile.activeBtnClass).first();h.css({top:a.support.scrollTop&&g.scrollTop()+g.height()/2||b.length&&b.offset().top||100})}function e(){var c=h.offset(),d=g.scrollTop(),f=a.mobile.getScreenHeight();if(c.top<d||c.top-d>f)h.addClass("ui-loader-fakefix"),b(),g.unbind("scroll", +e).bind("scroll",b)}function f(){d.removeClass("ui-mobile-rendering")}var d=a("html");a("head");var g=a(c);a(c.document).trigger("mobileinit");if(a.mobile.gradeA()){if(a.mobile.ajaxBlacklist)a.mobile.ajaxEnabled=false;d.addClass("ui-mobile ui-mobile-rendering");setTimeout(f,5E3);var h=a("<div class='ui-loader'><span class='ui-icon ui-icon-loading'></span><h1></h1></div>");a.extend(a.mobile,{showPageLoadingMsg:function(b,c,f){d.addClass("ui-loading");if(a.mobile.loadingMessage){var k=f||a.mobile.loadingMessageTextVisible; +b=b||a.mobile.loadingMessageTheme;h.attr("class","ui-loader ui-corner-all ui-body-"+(b||"a")+" ui-loader-"+(k?"verbose":"default")+(f?" ui-loader-textonly":"")).find("h1").text(c||a.mobile.loadingMessage).end().appendTo(a.mobile.pageContainer);e();g.bind("scroll",e)}},hidePageLoadingMsg:function(){d.removeClass("ui-loading");a.mobile.loadingMessage&&h.removeClass("ui-loader-fakefix");a(c).unbind("scroll",b);a(c).unbind("scroll",e)},initializePage:function(){var b=a(":jqmData(role='page'), :jqmData(role='dialog')"); +b.length||(b=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0));b.each(function(){var b=a(this);b.jqmData("url")||b.attr("data-"+a.mobile.ns+"url",b.attr("id")||location.pathname+location.search)});a.mobile.firstPage=b.first();a.mobile.pageContainer=b.first().parent().addClass("ui-mobile-viewport");g.trigger("pagecontainercreate");a.mobile.showPageLoadingMsg();f();!a.mobile.hashListeningEnabled||!a.mobile.path.stripHash(location.hash)?a.mobile.changePage(a.mobile.firstPage, +{transition:"none",reverse:true,changeHash:false,fromHashChange:true}):g.trigger("hashchange",[true])}});a.mobile._registerInternalEvents();a(function(){c.scrollTo(0,1);a.mobile.defaultHomeScroll=!a.support.scrollTop||a(c).scrollTop()===1?0:1;a.fn.controlgroup&&a(k).bind("pagecreate create",function(b){a(":jqmData(role='controlgroup')",b.target).jqmEnhanceable().controlgroup({excludeInvisible:false})});a.mobile.autoInitializePage&&a.mobile.initializePage();g.load(a.mobile.silentScroll)})}})(jQuery, +this)});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile.simpledialog.min.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,8 @@ +/* + * jQuery Mobile Framework : plugin to provide a simple Dialog widget. + * Copyright (c) JTSage + * CC 3.0 Attribution. May be relicensed without permission/notifcation. + * https://github.com/jtsage/jquery-mobile-simpledialog + */ + +.ui-simpledialog-header h4{margin-top:5px;margin-bottom:5px;text-align:center}.ui-simpledialog-container{border:5px solid #111!important;width:85%;max-width:500px}.ui-simpledialog-screen{position:absolute;top:0;left:0;width:100%;height:100%}.ui-simpledialog-hidden{display:none}.ui-simpledialog-input{width:85%!important;display:block!important;margin-left:auto;margin-right:auto}.ui-simpledialog-screen-modal{background-color:black;-moz-opacity:.8;opacity:.80;filter:alpha(opacity=80)}.ui-simpledialog-subtitle{text-align:center}.ui-simpledialog-controls .buttons-separator{min-height:.6em}.ui-simpledialog-controls .button-hidden{display:none}.ui-dialog .ui-simpledialog-container{border:none!important}.ui-dialog-simpledialog .ui-content{padding:5px!important} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile.simpledialog2.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,382 @@ +/* + * jQuery Mobile Framework : plugin to provide a dialogs Widget. ver2 + * Copyright (c) JTSage + * CC 3.0 Attribution. May be relicensed without permission/notifcation. + * https://github.com/jtsage/jquery-mobile-simpledialog + * + * Modifications by Sebastien Jodogne + */ + +(function($, undefined ) { + $.widget( "mobile.simpledialog2", $.mobile.widget, { + options: { + version: '1.0.1-2012061300', // jQueryMobile-YrMoDaySerial + mode: 'blank', // or 'button' + themeDialog: 'b', + themeInput: false, + themeButtonDefault: false, + themeHeader: 'a', + + fullScreen: false, + fullScreenForce: false, + dialogAllow: false, + dialogForce: false, + + headerText: false, + headerClose: false, + buttonPrompt: false, + buttonInput: false, + buttonInputDefault: false, + buttonPassword: false, + blankContent: false, + blankContentAdopt: false, + + resizeListener: true, + safeNuke: true, + forceInput: true, + showModal: true, + animate: true, + transition: 'pop', + clickEvent: 'click', + zindex: '500', + width: '280px', + left: false, + top: false, + + callbackOpen: false, + callbackOpenArgs: [], + callbackClose: false, + callbackCloseArgs: [] + }, + _eventHandler: function(e,p) { + // Handle the triggers + var self = e.data.widget, + o = e.data.widget.options; + + if ( ! e.isPropagationStopped() ) { + switch (p.method) { + case 'close': + self.close(); + break; + case 'html': + self.updateBlank(p.source); + break; + } + } + }, + _create: function () { + var self = this, + o = $.extend(this.options, this.element.jqmData('options')), + initDate = new Date(), + content = $("<div class='ui-simpledialog-container ui-overlay-shadow ui-corner-all ui-simpledialog-hidden " + + ((o.animate === true) ? o.transition : '') + " ui-body-" + o.themeDialog + "'></div>"); + + if ( o.themeButtonDefault === false ) { o.themeButtonDefault = o.themeDialog; } + if ( o.themeInput === false ) { o.themeInput = o.themeDialog; } + $.mobile.sdCurrentDialog = self; + if ( typeof $.mobile.sdLastInput !== 'undefined' ) { delete $.mobile.sdLastInput; } + self.internalID = initDate.getTime(); + self.displayAnchor = $.mobile.activePage.children('.ui-content').first(); + if ( self.displayAnchor.length === 0 ) { self.displayAnchor = $.mobile.activePage; } + + self.dialogPage = $("<div data-role='dialog' data-theme='" + o.themeDialog + "'><div data-role='header'></div><div data-role='content'></div></div>"); + self.sdAllContent = self.dialogPage.find('[data-role=content]'); + + content.appendTo(self.sdAllContent); + + self.sdIntContent = self.sdAllContent.find('.ui-simpledialog-container'); + self.sdIntContent.css('width', o.width); + + if ( o.headerText !== false || o.headerClose !== false ) { + self.sdHeader = $('<div style="margin-bottom: 4px;" class="ui-header ui-bar-'+o.themeHeader+'"></div>'); + if ( o.headerClose === true ) { + $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); + } + $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); + self.sdHeader.appendTo(self.sdIntContent); + } + + if ( o.mode === 'blank' ) { + if ( o.blankContent === true ) { + if ( o.blankContentAdopt === true ) { + o.blankContent = self.element.children(); + } else { + o.blankContent = self.element.html(); + } + } + $(o.blankContent).appendTo(self.sdIntContent); + } else if ( o.mode === 'button' ) { + self._makeButtons().appendTo(self.sdIntContent); + } + + self.sdIntContent.appendTo(self.displayAnchor.parent()); + + self.dialogPage.appendTo( $.mobile.pageContainer ) + .page().css('minHeight', '0px').css('zIndex', o.zindex); + + if ( o.animate === true ) { self.dialogPage.addClass(o.transition); } + + self.screen = $("<div>", {'class':'ui-simpledialog-screen ui-simpledialog-hidden'}) + .css('z-index', (o.zindex-1)) + .appendTo(self.displayAnchor.parent()) + .bind(o.clickEvent, function(event){ + if ( !o.forceInput ) { + self.close(); + } + event.preventDefault(); + }); + + if ( o.showModal ) { self.screen.addClass('ui-simpledialog-screen-modal'); } + + $(document).bind('simpledialog.'+self.internalID, {widget:self}, function(e,p) { self._eventHandler(e,p); }); + }, + _makeButtons: function () { + var self = this, + o = self.options, + buttonHTML = $('<div></div>'), + pickerInput = $("<div class='ui-simpledialog-controls'><input class='ui-simpledialog-input ui-input-text ui-shadow-inset ui-corner-all ui-body-"+o.themeInput+"' type='"+((o.buttonPassword===true)?"password":"text")+"' value='"+((o.buttonInputDefault!==false)?o.buttonInputDefault.replace( '"', """ ).replace( "'", "'" ):"")+"' name='pickin' /></div>"), + pickerChoice = $("<div>", { "class":'ui-simpledialog-controls' }); + + + if ( o.buttonPrompt !== false ) { + self.buttonPromptText = $("<p class='ui-simpledialog-subtitle'>"+o.buttonPrompt+"</p>").appendTo(buttonHTML); + } + + if ( o.buttonInput !== false ) { + $.mobile.sdLastInput = ""; + pickerInput.appendTo(buttonHTML); + pickerInput.find('input').bind('change', function () { + $.mobile.sdLastInput = pickerInput.find('input').first().val(); + self.thisInput = pickerInput.find('input').first().val(); + }); + } + + pickerChoice.appendTo(buttonHTML); + + self.butObj = []; + + $.each(o.buttons, function(name, props) { + props = $.isFunction( props ) ? { click: props } : props; + props = $.extend({ + text : name, + id : name + self.internalID, + theme : o.themeButtonDefault, + icon : 'check', + iconpos: 'left', + corners: 'true', + shadow : 'true', + args : [], + close : true + }, props); + + self.butObj.push($("<a href='#'>"+name+"</a>") + .appendTo(pickerChoice) + .attr('id', props.id) + .buttonMarkup({ + theme : props.theme, + icon : props.icon, + iconpos: props.iconpos, + corners: props.corners, + shadow : props.shadow + }).unbind("vclick click") + .bind(o.clickEvent, function() { + if ( o.buttonInput ) { self.sdIntContent.find('input [name=pickin]').trigger('change'); } + var returnValue = props.click.apply(self, $.merge(arguments, props.args)); + if ( returnValue !== false && props.close === true ) { + self.close(); + } + }) + ); + }); + + return buttonHTML; + }, + _getCoords: function(widget) { + var self = widget, + docWinWidth = $.mobile.activePage.width(), + docWinHighOff = $(window).scrollTop(), + docWinHigh = $(window).height(), + diaWinWidth = widget.sdIntContent.innerWidth(), + diaWinHigh = widget.sdIntContent.outerHeight(), + + coords = { + 'high' : $(window).height(), + 'width' : $.mobile.activePage.width(), + 'fullTop' : $(window).scrollTop(), + 'fullLeft': $(window).scrollLeft(), + 'winTop' : docWinHighOff + ((widget.options.top !== false) ? widget.options.top : (( docWinHigh / 2 ) - ( diaWinHigh / 2 ) )), + 'winLeft' : ((widget.options.left !== false) ? widget.options.left : (( docWinWidth / 2 ) - ( diaWinWidth / 2 ) )) + }; + + if ( coords.winTop < 45 ) { coords.winTop = 45; } + + return coords; + }, + _orientChange: function(e) { + var self = e.data.widget, + o = e.data.widget.options, + coords = e.data.widget._getCoords(e.data.widget); + + e.stopPropagation(); + + if ( self.isDialog === true ) { + return true; + } else { + if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { + self.sdIntContent.css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); + } else { + self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); + } + } + }, + repos: function() { + var bsEvent = { data: {widget:this}, stopPropagation: function () { return true; }}; + this._orientChange(bsEvent); + }, + open: function() { + var self = this, + o = this.options, + coords = this._getCoords(this); + + self.sdAllContent.find('.ui-btn-active').removeClass('ui-btn-active'); + self.sdIntContent.delegate('[rel=close]', o.clickEvent, function (e) { e.preventDefault(); self.close(); }); + + if ( ( o.dialogAllow === true && coords.width < 400 ) || o.dialogForce ) { + self.isDialog = true; + + if ( o.mode === 'blank' ) { // Custom selects do not play well with dialog mode - so, we turn them off. + self.sdIntContent.find('select').each(function () { + $(this).jqmData('nativeMenu', true); + }); + } + + self.displayAnchor.parent().unbind("pagehide.remove"); + self.sdAllContent.append(self.sdIntContent); + self.sdAllContent.trigger('create'); + if ( o.headerText !== false ) { + self.sdHeader.find('h1').appendTo(self.dialogPage.find('[data-role=header]')); + self.sdIntContent.find('.ui-header').empty().removeClass(); + } + if ( o.headerClose === true ) { + self.dialogPage.find('.ui-header a').bind('click', function () { + setTimeout("$.mobile.sdCurrentDialog.destroy();", 1000); + }); + } else { + self.dialogPage.find('.ui-header a').remove(); + } + + self.sdIntContent.removeClass().css({'top': 'auto', 'width': 'auto', 'left': 'auto', 'marginLeft': 'auto', 'marginRight': 'auto', 'zIndex': o.zindex}); + $.mobile.changePage(self.dialogPage, {'transition': (o.animate === true) ? o.transition : 'none'}); + } else { + self.isDialog = false; + self.selects = []; + + if ( o.fullScreen === false ) { + if ( o.showModal === true && o.animate === true ) { self.screen.fadeIn('slow'); } + else { self.screen.removeClass('ui-simpledialog-hidden'); } + } + + self.sdIntContent.addClass('ui-overlay-shadow in').css('zIndex', o.zindex).trigger('create'); + + if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { + self.sdIntContent.removeClass('ui-simpledialog-container').css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); + } else { + self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); + } + + $(document).bind('orientationchange.simpledialog', {widget:self}, function(e) { self._orientChange(e); }); + if ( o.resizeListener === true ) { + $(window).bind('resize.simpledialog', {widget:self}, function (e) { self._orientChange(e); }); + } + } + if ( $.isFunction(o.callbackOpen) ) { + o.callbackOpen.apply(self, o.callbackOpenArgs); + } + }, + close: function() { + var self = this, o = this.options, retty; + + if ( $.isFunction(self.options.callbackClose) ) { + retty = self.options.callbackClose.apply(self, self.options.callbackCloseArgs); + if ( retty === false ) { return false; } + } + + if ( self.isDialog ) { + $(self.dialogPage).dialog('close'); + self.sdIntContent.addClass('ui-simpledialog-hidden'); + self.sdIntContent.appendTo(self.displayAnchor.parent()); + if ( $.mobile.activePage.jqmData("page").options.domCache != true && $.mobile.activePage.is(":jqmData(external-page='true')") ) { + $.mobile.activePage.bind("pagehide.remove", function () { + $(this).remove(); + }); + } + } else { + if ( self.options.showModal === true && self.options.animate === true ) { + self.screen.fadeOut('slow'); + } else { + self.screen.addClass('ui-simpledialog-hidden'); + } + self.sdIntContent.addClass('ui-simpledialog-hidden').removeClass('in'); + $(document).unbind('orientationchange.simpledialog'); + if ( self.options.resizeListener === true ) { $(window).unbind('resize.simpledialog'); } + } + + if ( o.mode === 'blank' && o.blankContent !== false && o.blankContentAdopt === true ) { + self.element.append(o.blankContent); + o.blankContent = true; + } + + if ( self.isDialog === true || self.options.animate === true ) { + setTimeout(function(that) { return function () { that.destroy(); };}(self), 1000); + } else { + self.destroy(); + } + }, + destroy: function() { + var self = this, + ele = self.element; + + if ( self.options.mode === 'blank' ) { + $.mobile.sdCurrentDialog.sdIntContent.find('select').each(function() { + if ( $(this).data('nativeMenu') == false ) { + $(this).data('selectmenu').menuPage.remove(); + $(this).data('selectmenu').screen.remove(); + $(this).data('selectmenu').listbox.remove(); + } + }); + } + + $(self.sdIntContent).remove(); + $(self.dialogPage).remove(); + $(self.screen).remove(); + $(document).unbind('simpledialog.'+self.internalID); + delete $.mobile.sdCurrentDialog; + $.Widget.prototype.destroy.call(self); + if ( self.options.safeNuke === true && $(ele).parents().length === 0 && $(ele).contents().length === 0 ) { + ele.remove(); + } + }, + updateBlank: function (newHTML) { + var self = this, + o = this.options; + + self.sdIntContent.empty(); + + if ( o.headerText !== false || o.headerClose !== false ) { + self.sdHeader = $('<div class="ui-header ui-bar-'+o.themeHeader+'"></div>'); + if ( o.headerClose === true ) { + $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); + } + $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); + self.sdHeader.appendTo(self.sdIntContent); + } + + $(newHTML).appendTo(self.sdIntContent); + self.sdIntContent.trigger('create'); + $(document).trigger('orientationchange.simpledialog'); + }, + _init: function() { + this.open(); + } + }); +})( jQuery );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile.structure-1.1.0.min.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/jquery.mobile.theme-1.1.0.min.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/slimbox2.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,244 @@ +/*! + Slimbox v2.04 - The ultimate lightweight Lightbox clone for jQuery + (c) 2007-2010 Christophe Beyls <http://www.digitalia.be> + MIT-style license. +*/ + +(function($) { + + // Global variables, accessible to Slimbox only + var win = $(window), options, images, activeImage = -1, activeURL, prevImage, nextImage, compatibleOverlay, middle, centerWidth, centerHeight, + ie6 = !window.XMLHttpRequest, hiddenElements = [], documentElement = document.documentElement, + + // Preload images + preload = {}, preloadPrev = new Image(), preloadNext = new Image(), + + // DOM elements + overlay, center, image, sizer, prevLink, nextLink, bottomContainer, bottom, caption, number; + + /* + Initialization + */ + + $(function() { + // Append the Slimbox HTML code at the bottom of the document + $("body").append( + $([ + overlay = $('<div id="lbOverlay" />')[0], + center = $('<div id="lbCenter" />')[0], + bottomContainer = $('<div id="lbBottomContainer" />')[0] + ]).css("display", "none") + ); + + image = $('<div id="lbImage" />').appendTo(center).append( + sizer = $('<div style="position: relative;" />').append([ + prevLink = $('<a id="lbPrevLink" href="#" />').click(previous)[0], + nextLink = $('<a id="lbNextLink" href="#" />').click(next)[0] + ])[0] + )[0]; + + bottom = $('<div id="lbBottom" />').appendTo(bottomContainer).append([ + $('<a id="lbCloseLink" href="#" />').add(overlay).click(close)[0], + caption = $('<div id="lbCaption" />')[0], + number = $('<div id="lbNumber" />')[0], + $('<div style="clear: both;" />')[0] + ])[0]; + }); + + + /* + API + */ + + // Open Slimbox with the specified parameters + $.slimbox = function(_images, startImage, _options) { + options = $.extend({ + loop: false, // Allows to navigate between first and last images + overlayOpacity: 0.8, // 1 is opaque, 0 is completely transparent (change the color in the CSS file) + overlayFadeDuration: 400, // Duration of the overlay fade-in and fade-out animations (in milliseconds) + resizeDuration: 400, // Duration of each of the box resize animations (in milliseconds) + resizeEasing: "swing", // "swing" is jQuery's default easing + initialWidth: 250, // Initial width of the box (in pixels) + initialHeight: 250, // Initial height of the box (in pixels) + imageFadeDuration: 400, // Duration of the image fade-in animation (in milliseconds) + captionAnimationDuration: 400, // Duration of the caption animation (in milliseconds) + counterText: "Image {x} of {y}", // Translate or change as you wish, or set it to false to disable counter text for image groups + closeKeys: [27, 88, 67], // Array of keycodes to close Slimbox, default: Esc (27), 'x' (88), 'c' (67) + previousKeys: [37, 80], // Array of keycodes to navigate to the previous image, default: Left arrow (37), 'p' (80) + nextKeys: [39, 78] // Array of keycodes to navigate to the next image, default: Right arrow (39), 'n' (78) + }, _options); + + // The function is called for a single image, with URL and Title as first two arguments + if (typeof _images == "string") { + _images = [[_images, startImage]]; + startImage = 0; + } + + middle = win.scrollTop() + (win.height() / 2); + centerWidth = options.initialWidth; + centerHeight = options.initialHeight; + $(center).css({top: Math.max(0, middle - (centerHeight / 2)), width: centerWidth, height: centerHeight, marginLeft: -centerWidth/2}).show(); + compatibleOverlay = ie6 || (overlay.currentStyle && (overlay.currentStyle.position != "fixed")); + if (compatibleOverlay) overlay.style.position = "absolute"; + $(overlay).css("opacity", options.overlayOpacity).fadeIn(options.overlayFadeDuration); + position(); + setup(1); + + images = _images; + options.loop = options.loop && (images.length > 1); + return changeImage(startImage); + }; + + /* + options: Optional options object, see jQuery.slimbox() + linkMapper: Optional function taking a link DOM element and an index as arguments and returning an array containing 2 elements: + the image URL and the image caption (may contain HTML) + linksFilter: Optional function taking a link DOM element and an index as arguments and returning true if the element is part of + the image collection that will be shown on click, false if not. "this" refers to the element that was clicked. + This function must always return true when the DOM element argument is "this". + */ + $.fn.slimbox = function(_options, linkMapper, linksFilter) { + linkMapper = linkMapper || function(el) { + return [el.href, el.title]; + }; + + linksFilter = linksFilter || function() { + return true; + }; + + var links = this; + + return links.unbind("click").click(function() { + // Build the list of images that will be displayed + var link = this, startIndex = 0, filteredLinks, i = 0, length; + filteredLinks = $.grep(links, function(el, i) { + return linksFilter.call(link, el, i); + }); + + // We cannot use jQuery.map() because it flattens the returned array + for (length = filteredLinks.length; i < length; ++i) { + if (filteredLinks[i] == link) startIndex = i; + filteredLinks[i] = linkMapper(filteredLinks[i], i); + } + + return $.slimbox(filteredLinks, startIndex, _options); + }); + }; + + + /* + Internal functions + */ + + function position() { + var l = win.scrollLeft(), w = win.width(); + $([center, bottomContainer]).css("left", l + (w / 2)); + if (compatibleOverlay) $(overlay).css({left: l, top: win.scrollTop(), width: w, height: win.height()}); + } + + function setup(open) { + if (open) { + $("object").add(ie6 ? "select" : "embed").each(function(index, el) { + hiddenElements[index] = [el, el.style.visibility]; + el.style.visibility = "hidden"; + }); + } else { + $.each(hiddenElements, function(index, el) { + el[0].style.visibility = el[1]; + }); + hiddenElements = []; + } + var fn = open ? "bind" : "unbind"; + win[fn]("scroll resize", position); + $(document)[fn]("keydown", keyDown); + } + + function keyDown(event) { + var code = event.keyCode, fn = $.inArray; + // Prevent default keyboard action (like navigating inside the page) + return (fn(code, options.closeKeys) >= 0) ? close() + : (fn(code, options.nextKeys) >= 0) ? next() + : (fn(code, options.previousKeys) >= 0) ? previous() + : false; + } + + function previous() { + return changeImage(prevImage); + } + + function next() { + return changeImage(nextImage); + } + + function changeImage(imageIndex) { + if (imageIndex >= 0) { + activeImage = imageIndex; + activeURL = images[activeImage][0]; + prevImage = (activeImage || (options.loop ? images.length : 0)) - 1; + nextImage = ((activeImage + 1) % images.length) || (options.loop ? 0 : -1); + + stop(); + center.className = "lbLoading"; + + preload = new Image(); + preload.onload = animateBox; + preload.src = activeURL; + } + + return false; + } + + function animateBox() { + center.className = ""; + $(image).css({backgroundImage: "url(" + activeURL + ")", visibility: "hidden", display: "" }); + $(sizer).width(preload.width); + $([sizer, prevLink, nextLink]).height(preload.height); + + $(caption).html(images[activeImage][1] || ""); + $(number).html((((images.length > 1) && options.counterText) || "").replace(/{x}/, activeImage + 1).replace(/{y}/, images.length)); + + if (prevImage >= 0) preloadPrev.src = images[prevImage][0]; + if (nextImage >= 0) preloadNext.src = images[nextImage][0]; + + centerWidth = image.offsetWidth; + centerHeight = image.offsetHeight; + var top = Math.max(0, middle - (centerHeight / 2)); + if (center.offsetHeight != centerHeight) { + $(center).animate({height: centerHeight, top: top}, options.resizeDuration, options.resizeEasing); + } + if (center.offsetWidth != centerWidth) { + $(center).animate({width: centerWidth, marginLeft: -centerWidth/2}, options.resizeDuration, options.resizeEasing); + } + $(center).queue(function() { + $(bottomContainer).css({width: centerWidth, top: top + centerHeight, marginLeft: -centerWidth/2, visibility: "hidden", display: ""}); + animateCaption(); + $(image).css({display: "none", visibility: "", opacity: ""}).fadeIn(options.imageFadeDuration, animateCaption); + }); + } + + function animateCaption() { + if (prevImage >= 0) $(prevLink).show(); + if (nextImage >= 0) $(nextLink).show(); + $(bottom).css("marginTop", -bottom.offsetHeight).animate({marginTop: 0}, options.captionAnimationDuration); + bottomContainer.style.visibility = ""; + } + + function stop() { + preload.onload = null; + preload.src = preloadPrev.src = preloadNext.src = activeURL; + $([center, image, bottom]).stop(true); + $([prevLink, nextLink, image, bottomContainer]).hide(); + } + + function close() { + if (activeImage >= 0) { + stop(); + activeImage = prevImage = nextImage = -1; + $(center).hide(); + $(overlay).stop().fadeOut(options.overlayFadeDuration, setup); + } + + return false; + } + +})(jQuery); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/slimbox2/slimbox2-rtl.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,84 @@ +/* SLIMBOX */ + +#lbOverlay { + position: fixed; + z-index: 9999; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + cursor: pointer; +} + +#lbCenter, #lbBottomContainer { + position: absolute; + z-index: 9999; + overflow: hidden; + background-color: #fff; +} + +.lbLoading { + background: #fff url(loading.gif) no-repeat center; +} + +#lbImage { + position: absolute; + left: 0; + top: 0; + border: 10px solid #fff; + background-repeat: no-repeat; +} + +#lbPrevLink, #lbNextLink { + display: block; + position: absolute; + top: 0; + width: 50%; + outline: none; +} + +#lbPrevLink { + right: 0; +} + +#lbPrevLink:hover { + background: transparent url(prevlabel.gif) no-repeat 100% 15%; +} + +#lbNextLink { + left: 0; +} + +#lbNextLink:hover { + background: transparent url(nextlabel.gif) no-repeat 0 15%; +} + +#lbBottom { + font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; + font-size: 10px; + color: #666; + line-height: 1.4em; + text-align: right; + border: 10px solid #fff; + border-top-style: none; + direction: rtl; +} + +#lbCloseLink { + display: block; + float: left; + width: 66px; + height: 22px; + background: transparent url(closelabel.gif) no-repeat center; + margin: 5px 0; + outline: none; +} + +#lbCaption, #lbNumber { + margin-left: 71px; +} + +#lbCaption { + font-weight: bold; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/slimbox2/slimbox2.css Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,83 @@ +/* SLIMBOX */ + +#lbOverlay { + position: fixed; + z-index: 9999; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + cursor: pointer; +} + +#lbCenter, #lbBottomContainer { + position: absolute; + z-index: 9999; + overflow: hidden; + background-color: #fff; +} + +.lbLoading { + background: #fff url(loading.gif) no-repeat center; +} + +#lbImage { + position: absolute; + left: 0; + top: 0; + border: 10px solid #fff; + background-repeat: no-repeat; +} + +#lbPrevLink, #lbNextLink { + display: block; + position: absolute; + top: 0; + width: 50%; + outline: none; +} + +#lbPrevLink { + left: 0; +} + +#lbPrevLink:hover { + background: transparent url(prevlabel.gif) no-repeat 0 15%; +} + +#lbNextLink { + right: 0; +} + +#lbNextLink:hover { + background: transparent url(nextlabel.gif) no-repeat 100% 15%; +} + +#lbBottom { + font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; + font-size: 10px; + color: #666; + line-height: 1.4em; + text-align: left; + border: 10px solid #fff; + border-top-style: none; +} + +#lbCloseLink { + display: block; + float: right; + width: 66px; + height: 22px; + background: transparent url(closelabel.gif) no-repeat center; + margin: 5px 0; + outline: none; +} + +#lbCaption, #lbNumber { + margin-right: 71px; +} + +#lbCaption { + font-weight: bold; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancExplorer/libs/tree.jquery.js Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,1837 @@ +// Generated by CoffeeScript 1.3.3 + +/* +Copyright 2012 Marco Braak + +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() { + var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, Json, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, Tree, html_escape, indexOf, toJson, + __slice = [].slice, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + $ = this.jQuery; + + SimpleWidget = (function() { + + SimpleWidget.prototype.defaults = {}; + + function SimpleWidget(el, options) { + this.$el = $(el); + this.options = $.extend({}, this.defaults, options); + this._init(); + } + + SimpleWidget.prototype.destroy = function() { + return this._deinit(); + }; + + SimpleWidget.prototype._init = function() { + return null; + }; + + SimpleWidget.prototype._deinit = function() { + return null; + }; + + SimpleWidget.register = function(widget_class, widget_name) { + var callFunction, createWidget, destroyWidget, getDataKey; + getDataKey = function() { + return "simple_widget_" + widget_name; + }; + createWidget = function($el, options) { + var data_key; + data_key = getDataKey(); + $el.each(function() { + var widget; + widget = new widget_class(this, options); + if (!$.data(this, data_key)) { + return $.data(this, data_key, widget); + } + }); + return $el; + }; + destroyWidget = function($el) { + var data_key; + data_key = getDataKey(); + return $el.each(function() { + var widget; + widget = $.data(this, data_key); + if (widget && (widget instanceof SimpleWidget)) { + widget.destroy(); + } + return $.removeData(this, data_key); + }); + }; + callFunction = function($el, function_name, args) { + var result; + result = null; + $el.each(function() { + var widget, widget_function; + widget = $.data(this, getDataKey()); + if (widget && (widget instanceof SimpleWidget)) { + widget_function = widget[function_name]; + if (widget_function && (typeof widget_function === 'function')) { + return result = widget_function.apply(widget, args); + } + } + }); + return result; + }; + return $.fn[widget_name] = function() { + var $el, args, argument1, function_name, options; + argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + $el = this; + if (argument1 === void 0 || typeof argument1 === 'object') { + options = argument1; + return createWidget($el, options); + } else if (typeof argument1 === 'string' && argument1[0] !== '_') { + function_name = argument1; + if (function_name === 'destroy') { + return destroyWidget($el); + } else { + return callFunction($el, function_name, args); + } + } + }; + }; + + return SimpleWidget; + + })(); + + this.SimpleWidget = SimpleWidget; + + /* + This widget does the same a the mouse widget in jqueryui. + */ + + + MouseWidget = (function(_super) { + + __extends(MouseWidget, _super); + + function MouseWidget() { + return MouseWidget.__super__.constructor.apply(this, arguments); + } + + MouseWidget.is_mouse_handled = false; + + MouseWidget.prototype._init = function() { + this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this)); + return this.is_mouse_started = false; + }; + + MouseWidget.prototype._deinit = function() { + var $document; + this.$el.unbind('mousedown.mousewidget'); + $document = $(document); + $document.unbind('mousemove.mousewidget'); + return $document.unbind('mouseup.mousewidget'); + }; + + MouseWidget.prototype._mouseDown = function(e) { + var $document; + if (MouseWidget.is_mouse_handled) { + return; + } + if (!this.is_mouse_started) { + this._mouseUp(e); + } + if (e.which !== 1) { + return; + } + if (!this._mouseCapture(e)) { + return; + } + this.mouse_down_event = e; + $document = $(document); + $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this)); + $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this)); + e.preventDefault(); + this.is_mouse_handled = true; + return true; + }; + + MouseWidget.prototype._mouseMove = function(e) { + if (this.is_mouse_started) { + this._mouseDrag(e); + return e.preventDefault(); + } + this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false; + if (this.is_mouse_started) { + this._mouseDrag(e); + } else { + this._mouseUp(e); + } + return !this.is_mouse_started; + }; + + MouseWidget.prototype._mouseUp = function(e) { + var $document; + $document = $(document); + $document.unbind('mousemove.mousewidget'); + $document.unbind('mouseup.mousewidget'); + if (this.is_mouse_started) { + this.is_mouse_started = false; + this._mouseStop(e); + } + return false; + }; + + MouseWidget.prototype._mouseCapture = function(e) { + return true; + }; + + MouseWidget.prototype._mouseStart = function(e) { + return null; + }; + + MouseWidget.prototype._mouseDrag = function(e) { + return null; + }; + + MouseWidget.prototype._mouseStop = function(e) { + return null; + }; + + return MouseWidget; + + })(SimpleWidget); + + /* + Copyright 2012 Marco Braak + + 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. + */ + + + this.Tree = {}; + + $ = this.jQuery; + + indexOf = function(array, item) { + var i, value, _i, _len; + if (array.indexOf) { + return array.indexOf(item); + } else { + for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) { + value = array[i]; + if (value === item) { + return i; + } + } + return -1; + } + }; + + this.Tree.indexOf = indexOf; + + Json = {}; + + Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + Json.meta = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"': '\\"', + '\\': '\\\\' + }; + + Json.quote = function(string) { + Json.escapable.lastIndex = 0; + if (Json.escapable.test(string)) { + return '"' + string.replace(Json.escapable, function(a) { + var c; + c = Json.meta[a]; + return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); + }) + '"'; + } else { + return '"' + string + '"'; + } + }; + + Json.str = function(key, holder) { + var i, k, partial, v, value, _i, _len; + value = holder[key]; + switch (typeof value) { + case 'string': + return Json.quote(value); + case 'number': + if (isFinite(value)) { + return String(value); + } else { + return 'null'; + } + case 'boolean': + case 'null': + return String(value); + case 'object': + if (!value) { + return 'null'; + } + partial = []; + if (Object.prototype.toString.apply(value) === '[object Array]') { + for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { + v = value[i]; + partial[i] = Json.str(i, value) || 'null'; + } + return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); + } + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = Json.str(k, value); + if (v) { + partial.push(Json.quote(k) + ':' + v); + } + } + } + return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); + } + }; + + toJson = function(value) { + return Json.str('', { + '': value + }); + }; + + this.Tree.toJson = toJson; + + html_escape = function(string) { + return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); + }; + + Position = { + getName: function(position) { + if (position === Position.BEFORE) { + return 'before'; + } else if (position === Position.AFTER) { + return 'after'; + } else if (position === Position.INSIDE) { + return 'inside'; + } else { + return 'none'; + } + } + }; + + Position.BEFORE = 1; + + Position.AFTER = 2; + + Position.INSIDE = 3; + + Position.NONE = 4; + + this.Tree.Position = Position; + + Node = (function() { + + function Node(o) { + this.setData(o); + } + + Node.prototype.setData = function(o) { + var key, value; + if (typeof o !== 'object') { + this.name = o; + } else { + for (key in o) { + value = o[key]; + if (key === 'label') { + this.name = value; + } else { + this[key] = value; + } + } + } + this.children = []; + return this.parent = null; + }; + + Node.prototype.initFromData = function(data) { + var addChildren, addNode, + _this = this; + addNode = function(node_data) { + _this.setData(node_data); + if (node_data.children) { + return addChildren(node_data.children); + } + }; + addChildren = function(children_data) { + var child, node, _i, _len; + for (_i = 0, _len = children_data.length; _i < _len; _i++) { + child = children_data[_i]; + node = new Node(''); + node.initFromData(child); + _this.addChild(node); + } + return null; + }; + addNode(data); + return null; + }; + + /* + Create tree from data. + + Structure of data is: + [ + { + label: 'node1', + children: [ + { label: 'child1' }, + { label: 'child2' } + ] + }, + { + label: 'node2' + } + ] + */ + + + Node.prototype.loadFromData = function(data) { + var node, o, _i, _len; + this.children = []; + for (_i = 0, _len = data.length; _i < _len; _i++) { + o = data[_i]; + node = new Node(o); + this.addChild(node); + if (typeof o === 'object' && o.children) { + node.loadFromData(o.children); + } + } + return null; + }; + + /* + Add child. + + tree.addChild( + new Node('child1') + ); + */ + + + Node.prototype.addChild = function(node) { + this.children.push(node); + return node._setParent(this); + }; + + /* + Add child at position. Index starts at 0. + + tree.addChildAtPosition( + new Node('abc'), + 1 + ); + */ + + + Node.prototype.addChildAtPosition = function(node, index) { + this.children.splice(index, 0, node); + return node._setParent(this); + }; + + Node.prototype._setParent = function(parent) { + this.parent = parent; + this.tree = parent.tree; + return this.tree.addNodeToIndex(this); + }; + + /* + Remove child. + + tree.removeChild(tree.children[0]); + */ + + + Node.prototype.removeChild = function(node) { + this.children.splice(this.getChildIndex(node), 1); + return this.tree.removeNodeFromIndex(node); + }; + + /* + Get child index. + + var index = getChildIndex(node); + */ + + + Node.prototype.getChildIndex = function(node) { + return $.inArray(node, this.children); + }; + + /* + Does the tree have children? + + if (tree.hasChildren()) { + // + } + */ + + + Node.prototype.hasChildren = function() { + return this.children.length !== 0; + }; + + /* + Iterate over all the nodes in the tree. + + Calls callback with (node, level). + + The callback must return true to continue the iteration on current node. + + tree.iterate( + function(node, level) { + console.log(node.name); + + // stop iteration after level 2 + return (level <= 2); + } + ); + */ + + + Node.prototype.iterate = function(callback) { + var _iterate, + _this = this; + _iterate = function(node, level) { + var child, result, _i, _len, _ref; + if (node.children) { + _ref = node.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + result = callback(child, level); + if (_this.hasChildren() && result) { + _iterate(child, level + 1); + } + } + return null; + } + }; + _iterate(this, 0); + return null; + }; + + /* + Move node relative to another node. + + Argument position: Position.BEFORE, Position.AFTER or Position.Inside + + // move node1 after node2 + tree.moveNode(node1, node2, Position.AFTER); + */ + + + Node.prototype.moveNode = function(moved_node, target_node, position) { + moved_node.parent.removeChild(moved_node); + if (position === Position.AFTER) { + return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); + } else if (position === Position.BEFORE) { + return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); + } else if (position === Position.INSIDE) { + return target_node.addChildAtPosition(moved_node, 0); + } + }; + + /* + Get the tree as data. + */ + + + Node.prototype.getData = function() { + var getDataFromNodes, + _this = this; + getDataFromNodes = function(nodes) { + var data, k, node, tmp_node, v, _i, _len; + data = []; + for (_i = 0, _len = nodes.length; _i < _len; _i++) { + node = nodes[_i]; + tmp_node = {}; + for (k in node) { + v = node[k]; + if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) { + tmp_node[k] = v; + } + } + if (node.hasChildren()) { + tmp_node.children = getDataFromNodes(node.children); + } + data.push(tmp_node); + } + return data; + }; + return getDataFromNodes(this.children); + }; + + Node.prototype.getNodeByName = function(name) { + var result; + result = null; + this.iterate(function(node) { + if (node.name === name) { + result = node; + return false; + } else { + return true; + } + }); + return result; + }; + + Node.prototype.addAfter = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + this.parent.addChildAtPosition(node, child_index + 1); + return node; + } + }; + + Node.prototype.addBefore = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + return this.parent.addChildAtPosition(node, child_index); + } + }; + + Node.prototype.addParent = function(node_info) { + var child, new_parent, original_parent, _i, _len, _ref; + if (!this.parent) { + return null; + } else { + new_parent = new Node(node_info); + new_parent._setParent(this.tree); + original_parent = this.parent; + _ref = original_parent.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + new_parent.addChild(child); + } + original_parent.children = []; + original_parent.addChild(new_parent); + return new_parent; + } + }; + + Node.prototype.remove = function() { + if (this.parent) { + this.parent.removeChild(this); + return this.parent = null; + } + }; + + Node.prototype.append = function(node_info) { + var node; + node = new Node(node_info); + this.addChild(node); + return node; + }; + + Node.prototype.prepend = function(node_info) { + var node; + node = new Node(node_info); + this.addChildAtPosition(node, 0); + return node; + }; + + return Node; + + })(); + + Tree = (function(_super) { + + __extends(Tree, _super); + + function Tree(o) { + Tree.__super__.constructor.call(this, o, null, true); + this.id_mapping = {}; + this.tree = this; + } + + Tree.prototype.getNodeById = function(node_id) { + return this.id_mapping[node_id]; + }; + + Tree.prototype.addNodeToIndex = function(node) { + if (node.id) { + return this.id_mapping[node.id] = node; + } + }; + + Tree.prototype.removeNodeFromIndex = function(node) { + if (node.id) { + return delete this.id_mapping[node.id]; + } + }; + + return Tree; + + })(Node); + + this.Tree.Tree = Tree; + + JqTreeWidget = (function(_super) { + + __extends(JqTreeWidget, _super); + + function JqTreeWidget() { + return JqTreeWidget.__super__.constructor.apply(this, arguments); + } + + JqTreeWidget.prototype.defaults = { + autoOpen: false, + saveState: false, + dragAndDrop: false, + selectable: false, + onCanSelectNode: null, + onSetStateFromStorage: null, + onGetStateFromStorage: null, + onCreateLi: null, + onIsMoveHandle: null, + onCanMove: null, + onCanMoveTo: null, + autoEscape: true, + dataUrl: null + }; + + JqTreeWidget.prototype.toggle = function(node) { + if (node.hasChildren()) { + new FolderElement(node, this.element).toggle(); + } + return this._saveState(); + }; + + JqTreeWidget.prototype.getTree = function() { + return this.tree; + }; + + JqTreeWidget.prototype.selectNode = function(node, must_open_parents) { + return this.select_node_handler.selectNode(node, must_open_parents); + }; + + JqTreeWidget.prototype.getSelectedNode = function() { + return this.selected_node || false; + }; + + JqTreeWidget.prototype.toJson = function() { + return toJson(this.tree.getData()); + }; + + JqTreeWidget.prototype.loadData = function(data, parent_node) { + var child, subtree, _i, _len, _ref; + if (!parent_node) { + this._initTree(data); + } else { + subtree = new Node(''); + subtree._setParent(parent_node.tree); + subtree.loadFromData(data); + _ref = subtree.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + parent_node.addChild(child); + } + this._refreshElements(parent_node.parent); + } + if (this.is_dragging) { + return this.dnd_handler.refreshHitAreas(); + } + }; + + JqTreeWidget.prototype.getNodeById = function(node_id) { + return this.tree.getNodeById(node_id); + }; + + JqTreeWidget.prototype.getNodeByName = function(name) { + return this.tree.getNodeByName(name); + }; + + JqTreeWidget.prototype.openNode = function(node, skip_slide) { + if (node.hasChildren()) { + new FolderElement(node, this.element).open(null, skip_slide); + return this._saveState(); + } + }; + + JqTreeWidget.prototype.closeNode = function(node, skip_slide) { + if (node.hasChildren()) { + new FolderElement(node, this.element).close(skip_slide); + return this._saveState(); + } + }; + + JqTreeWidget.prototype.isDragging = function() { + return this.is_dragging; + }; + + JqTreeWidget.prototype.refreshHitAreas = function() { + return this.dnd_handler.refreshHitAreas(); + }; + + JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addAfter(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addBefore(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addParent(new_node_info); + this._refreshElements(new_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.removeNode = function(node) { + var parent; + parent = node.parent; + if (parent) { + node.remove(); + return this._refreshElements(parent.parent); + } + }; + + JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { + var is_already_root_node, node; + if (!parent_node) { + parent_node = this.tree; + } + is_already_root_node = parent_node.hasChildren(); + node = parent_node.append(new_node_info); + if (is_already_root_node) { + this._refreshElements(parent_node); + } else { + this._refreshElements(parent_node.parent); + } + return node; + }; + + JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { + var node; + if (!parent_node) { + parent_node = this.tree; + } + node = parent_node.prepend(new_node_info); + this._refreshElements(parent_node); + return node; + }; + + JqTreeWidget.prototype._init = function() { + JqTreeWidget.__super__._init.call(this); + this.element = this.$el; + this._initData(); + this.element.click($.proxy(this._click, this)); + return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); + }; + + JqTreeWidget.prototype._deinit = function() { + this.element.empty(); + this.element.unbind(); + this.tree = null; + return JqTreeWidget.__super__._deinit.call(this); + }; + + JqTreeWidget.prototype._initData = function() { + var data_url, + _this = this; + if (this.options.data) { + return this._initTree(this.options.data); + } else { + data_url = this.options.dataUrl || this.element.data('url'); + if (data_url) { + return $.ajax({ + url: data_url, + cache: false, + success: function(response) { + var data; + if ($.isArray(response) || typeof response === 'object') { + data = response; + } else { + data = $.parseJSON(response); + } + return _this._initTree(data); + } + }); + } + } + }; + + JqTreeWidget.prototype._initTree = function(data) { + var event; + this.tree = new Tree(); + this.tree.loadFromData(data); + this.selected_node = null; + this.save_state_handler = new SaveStateHandler(this); + this.select_node_handler = new SelectNodeHandler(this); + this.dnd_handler = new DragAndDropHandler(this); + this._openNodes(); + this._refreshElements(); + this.select_node_handler.selectCurrentNode(); + event = $.Event('tree.init'); + return this.element.trigger(event); + }; + + JqTreeWidget.prototype._openNodes = function() { + var max_level; + if (this.options.saveState) { + if (this.save_state_handler.restoreState()) { + return; + } + } + if (this.options.autoOpen === false) { + return; + } else if (this.options.autoOpen === true) { + max_level = -1; + } else { + max_level = parseInt(this.options.autoOpen); + } + return this.tree.iterate(function(node, level) { + node.is_open = true; + return level !== max_level; + }); + }; + + JqTreeWidget.prototype._refreshElements = function(from_node) { + var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element, + _this = this; + if (from_node == null) { + from_node = null; + } + escapeIfNecessary = function(value) { + if (_this.options.autoEscape) { + return html_escape(value); + } else { + return value; + } + }; + createUl = function(is_root_node) { + var class_string; + if (is_root_node) { + class_string = ' class="tree"'; + } else { + class_string = ''; + } + return $("<ul" + class_string + "></ul>"); + }; + createLi = function(node) { + var $li; + if (node.hasChildren()) { + $li = createFolderLi(node); + } else { + $li = createNodeLi(node); + } + if (_this.options.onCreateLi) { + _this.options.onCreateLi(node, $li); + } + return $li; + }; + createNodeLi = function(node) { + var escaped_name; + escaped_name = escapeIfNecessary(node.name); + return $("<li><div><span class=\"title\">" + escaped_name + "</span></div></li>"); + }; + createFolderLi = function(node) { + var button_class, escaped_name, folder_class, getButtonClass, getFolderClass; + getButtonClass = function() { + var classes; + classes = ['toggler']; + if (!node.is_open) { + classes.push('closed'); + } + return classes.join(' '); + }; + getFolderClass = function() { + var classes; + classes = ['folder']; + if (!node.is_open) { + classes.push('closed'); + } + return classes.join(' '); + }; + button_class = getButtonClass(); + folder_class = getFolderClass(); + escaped_name = escapeIfNecessary(node.name); + return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">»</a><span class=\"title\">" + escaped_name + "</span></div></li>"); + }; + doCreateDomElements = function($element, children, is_root_node, is_open) { + var $li, $ul, child, _i, _len; + $ul = createUl(is_root_node); + $element.append($ul); + for (_i = 0, _len = children.length; _i < _len; _i++) { + child = children[_i]; + $li = createLi(child); + $ul.append($li); + child.element = $li[0]; + $li.data('node', child); + if (child.hasChildren()) { + doCreateDomElements($li, child.children, false, child.is_open); + } + } + return null; + }; + if (from_node && from_node.parent) { + is_root_node = false; + node_element = this._getNodeElementForNode(from_node); + node_element.getUl().remove(); + $element = node_element.$element; + } else { + from_node = this.tree; + $element = this.element; + $element.empty(); + is_root_node = true; + } + return doCreateDomElements($element, from_node.children, is_root_node, is_root_node); + }; + + JqTreeWidget.prototype._click = function(e) { + var $target, event, node, node_element; + if (e.ctrlKey) { + return; + } + $target = $(e.target); + if ($target.is('.toggler')) { + node_element = this._getNodeElement($target); + if (node_element && node_element.node.hasChildren()) { + node_element.toggle(); + this._saveState(); + e.preventDefault(); + return e.stopPropagation(); + } + } else if ($target.is('div') || $target.is('span')) { + node = this._getNode($target); + if (node) { + if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) { + this.selectNode(node); + event = $.Event('tree.click'); + event.node = node; + return this.element.trigger(event); + } + } + } + }; + + JqTreeWidget.prototype._getNode = function($element) { + var $li; + $li = $element.closest('li'); + if ($li.length === 0) { + return null; + } else { + return $li.data('node'); + } + }; + + JqTreeWidget.prototype._getNodeElementForNode = function(node) { + if (node.hasChildren()) { + return new FolderElement(node, this.element); + } else { + return new NodeElement(node, this.element); + } + }; + + JqTreeWidget.prototype._getNodeElement = function($element) { + var node; + node = this._getNode($element); + if (node) { + return this._getNodeElementForNode(node); + } else { + return null; + } + }; + + JqTreeWidget.prototype._contextmenu = function(e) { + var $div, event, node; + $div = $(e.target).closest('ul.tree div'); + if ($div.length) { + node = this._getNode($div); + if (node) { + e.preventDefault(); + e.stopPropagation(); + event = $.Event('tree.contextmenu'); + event.node = node; + event.click_event = e; + this.element.trigger(event); + return false; + } + } + }; + + JqTreeWidget.prototype._saveState = function() { + if (this.options.saveState) { + return this.save_state_handler.saveState(); + } + }; + + JqTreeWidget.prototype._mouseCapture = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseCapture(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseStart = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStart(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseDrag = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseDrag(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseStop = function() { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStop(); + } else { + return false; + } + }; + + JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { + this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); + this.dnd_handler.generateHitAreas(); + return this.dnd_handler.hit_areas; + }; + + return JqTreeWidget; + + })(MouseWidget); + + SimpleWidget.register(JqTreeWidget, 'tree'); + + GhostDropHint = (function() { + + function GhostDropHint(node, $element, position) { + this.$element = $element; + this.node = node; + this.$ghost = $('<li class="ghost"><span class="circle"></span><span class="line"></span></li>'); + if (position === Position.AFTER) { + this.moveAfter(); + } else if (position === Position.BEFORE) { + this.moveBefore(); + } else if (position === Position.INSIDE) { + if (node.hasChildren() && node.is_open) { + this.moveInsideOpenFolder(); + } else { + this.moveInside(); + } + } + } + + GhostDropHint.prototype.remove = function() { + return this.$ghost.remove(); + }; + + GhostDropHint.prototype.moveAfter = function() { + return this.$element.after(this.$ghost); + }; + + GhostDropHint.prototype.moveBefore = function() { + return this.$element.before(this.$ghost); + }; + + GhostDropHint.prototype.moveInsideOpenFolder = function() { + return $(this.node.children[0].element).before(this.$ghost); + }; + + GhostDropHint.prototype.moveInside = function() { + this.$element.after(this.$ghost); + return this.$ghost.addClass('inside'); + }; + + return GhostDropHint; + + })(); + + BorderDropHint = (function() { + + function BorderDropHint($element) { + var $div, width; + $div = $element.children('div'); + width = $element.width() - 4; + this.$hint = $('<span class="border"></span>'); + $div.append(this.$hint); + this.$hint.css({ + width: width, + height: $div.height() - 4 + }); + } + + BorderDropHint.prototype.remove = function() { + return this.$hint.remove(); + }; + + return BorderDropHint; + + })(); + + NodeElement = (function() { + + function NodeElement(node, tree_element) { + this.init(node, tree_element); + } + + NodeElement.prototype.init = function(node, tree_element) { + this.node = node; + this.tree_element = tree_element; + return this.$element = $(node.element); + }; + + NodeElement.prototype.getUl = function() { + return this.$element.children('ul:first'); + }; + + NodeElement.prototype.getSpan = function() { + return this.$element.children('div').find('span.title'); + }; + + NodeElement.prototype.getLi = function() { + return this.$element; + }; + + NodeElement.prototype.addDropHint = function(position) { + if (position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + NodeElement.prototype.select = function() { + return this.getLi().addClass('selected'); + }; + + NodeElement.prototype.deselect = function() { + return this.getLi().removeClass('selected'); + }; + + return NodeElement; + + })(); + + FolderElement = (function(_super) { + + __extends(FolderElement, _super); + + function FolderElement() { + return FolderElement.__super__.constructor.apply(this, arguments); + } + + FolderElement.prototype.toggle = function() { + if (this.node.is_open) { + return this.close(); + } else { + return this.open(); + } + }; + + FolderElement.prototype.open = function(on_finished, skip_slide) { + var doOpen, + _this = this; + if (!this.node.is_open) { + this.node.is_open = true; + this.getButton().removeClass('closed'); + doOpen = function() { + var event; + _this.getLi().removeClass('closed'); + if (on_finished) { + on_finished(); + } + event = $.Event('tree.open'); + event.node = _this.node; + return _this.tree_element.trigger(event); + }; + if (skip_slide) { + return doOpen(); + } else { + return this.getUl().slideDown('fast', doOpen); + } + } + }; + + FolderElement.prototype.close = function(skip_slide) { + var doClose, + _this = this; + if (this.node.is_open) { + this.node.is_open = false; + this.getButton().addClass('closed'); + doClose = function() { + var event; + _this.getLi().addClass('closed'); + event = $.Event('tree.close'); + event.node = _this.node; + return _this.tree_element.trigger(event); + }; + if (skip_slide) { + return doClose(); + } else { + return this.getUl().slideUp('fast', doClose); + } + } + }; + + FolderElement.prototype.getButton = function() { + return this.$element.children('div').find('a.toggler'); + }; + + FolderElement.prototype.addDropHint = function(position) { + if (!this.node.is_open && position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + return FolderElement; + + })(NodeElement); + + DragElement = (function() { + + function DragElement(node, offset_x, offset_y, $tree) { + this.offset_x = offset_x; + this.offset_y = offset_y; + this.$element = $("<span class=\"title tree-dragging\">" + node.name + "</span>"); + this.$element.css("position", "absolute"); + $tree.append(this.$element); + } + + DragElement.prototype.move = function(page_x, page_y) { + return this.$element.offset({ + left: page_x - this.offset_x, + top: page_y - this.offset_y + }); + }; + + DragElement.prototype.remove = function() { + return this.$element.remove(); + }; + + return DragElement; + + })(); + + SaveStateHandler = (function() { + + function SaveStateHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SaveStateHandler.prototype.saveState = function() { + if (this.tree_widget.options.onSetStateFromStorage) { + return this.tree_widget.options.onSetStateFromStorage(this.getState()); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + return localStorage.setItem(this.getCookieName(), this.getState()); + } else if ($.cookie) { + return $.cookie(this.getCookieName(), this.getState(), { + path: '/' + }); + } + }; + + SaveStateHandler.prototype.restoreState = function() { + var state; + if (this.tree_widget.options.onGetStateFromStorage) { + state = this.tree_widget.options.onGetStateFromStorage(); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + state = localStorage.getItem(this.getCookieName()); + } else if ($.cookie) { + state = $.cookie(this.getCookieName(), { + path: '/' + }); + } else { + state = null; + } + if (!state) { + return false; + } else { + this.setState(state); + return true; + } + }; + + SaveStateHandler.prototype.getState = function() { + var open_nodes, selected_node, + _this = this; + open_nodes = []; + this.tree_widget.tree.iterate(function(node) { + if (node.is_open && node.id && node.hasChildren()) { + open_nodes.push(node.id); + } + return true; + }); + selected_node = ''; + if (this.tree_widget.selected_node) { + selected_node = this.tree_widget.selected_node.id; + } + return toJson({ + open_nodes: open_nodes, + selected_node: selected_node + }); + }; + + SaveStateHandler.prototype.setState = function(state) { + var data, open_nodes, selected_node_id, + _this = this; + data = $.parseJSON(state); + if (data) { + open_nodes = data.open_nodes; + selected_node_id = data.selected_node; + return this.tree_widget.tree.iterate(function(node) { + if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { + node.is_open = true; + } + if (selected_node_id && (node.id === selected_node_id)) { + _this.tree_widget.selected_node = node; + } + return true; + }); + } + }; + + SaveStateHandler.prototype.getCookieName = function() { + if (typeof this.tree_widget.options.saveState === 'string') { + return this.tree_widget.options.saveState; + } else { + return 'tree'; + } + }; + + return SaveStateHandler; + + })(); + + SelectNodeHandler = (function() { + + function SelectNodeHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) { + var parent; + if (this.tree_widget.options.selectable) { + if (this.tree_widget.selected_node) { + this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node).deselect(); + this.tree_widget.selected_node = null; + } + if (node) { + this.tree_widget._getNodeElementForNode(node).select(); + this.tree_widget.selected_node = node; + if (must_open_parents) { + parent = this.tree_widget.selected_node.parent; + while (parent) { + if (!parent.is_open) { + this.tree_widget.openNode(parent, true); + } + parent = parent.parent; + } + } + } + if (this.tree_widget.options.saveState) { + return this.tree_widget.save_state_handler.saveState(); + } + } + }; + + SelectNodeHandler.prototype.selectCurrentNode = function() { + var node_element; + if (this.tree_widget.selected_node) { + node_element = this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node); + if (node_element) { + return node_element.select(); + } + } + }; + + return SelectNodeHandler; + + })(); + + DragAndDropHandler = (function() { + + function DragAndDropHandler(tree_widget) { + this.tree_widget = tree_widget; + this.hovered_area = null; + this.$ghost = null; + this.hit_areas = []; + this.is_dragging = false; + } + + DragAndDropHandler.prototype.mouseCapture = function(event) { + var $element, node_element; + $element = $(event.target); + if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) { + return null; + } + node_element = this.tree_widget._getNodeElement($element); + if (node_element && this.tree_widget.options.onCanMove) { + if (!this.tree_widget.options.onCanMove(node_element.node)) { + node_element = null; + } + } + this.current_item = node_element; + return this.current_item !== null; + }; + + DragAndDropHandler.prototype.mouseStart = function(event) { + var offsetX, offsetY, _ref; + this.refreshHitAreas(); + _ref = this.getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; + this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element); + this.is_dragging = true; + this.current_item.$element.addClass('moving'); + return true; + }; + + DragAndDropHandler.prototype.mouseDrag = function(event) { + var area, position_name; + this.drag_element.move(event.pageX, event.pageY); + area = this.findHoveredArea(event.pageX, event.pageY); + if (area && this.tree_widget.options.onCanMoveTo) { + position_name = Position.getName(area.position); + if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { + area = null; + } + } + if (!area) { + this.removeDropHint(); + this.removeHover(); + this.stopOpenFolderTimer(); + } else { + if (this.hovered_area !== area) { + this.hovered_area = area; + this.updateDropHint(); + } + } + return true; + }; + + DragAndDropHandler.prototype.mouseStop = function() { + this.moveItem(); + this.clear(); + this.removeHover(); + this.removeDropHint(); + this.removeHitAreas(); + this.current_item.$element.removeClass('moving'); + this.is_dragging = false; + return false; + }; + + DragAndDropHandler.prototype.getOffsetFromEvent = function(event) { + var element_offset; + element_offset = $(event.target).offset(); + return [event.pageX - element_offset.left, event.pageY - element_offset.top]; + }; + + DragAndDropHandler.prototype.refreshHitAreas = function() { + this.removeHitAreas(); + return this.generateHitAreas(); + }; + + DragAndDropHandler.prototype.removeHitAreas = function() { + return this.hit_areas = []; + }; + + DragAndDropHandler.prototype.clear = function() { + this.drag_element.remove(); + return this.drag_element = null; + }; + + DragAndDropHandler.prototype.removeDropHint = function() { + if (this.previous_ghost) { + return this.previous_ghost.remove(); + } + }; + + DragAndDropHandler.prototype.removeHover = function() { + return this.hovered_area = null; + }; + + DragAndDropHandler.prototype.generateHitAreas = function() { + var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, + _this = this; + positions = []; + last_top = 0; + getTop = function($element) { + return $element.offset().top; + }; + addPosition = function(node, position, top) { + positions.push({ + top: top, + node: node, + position: position + }); + return last_top = top; + }; + groupPositions = function(handle_group) { + var group, position, previous_top, _i, _len; + previous_top = -1; + group = []; + for (_i = 0, _len = positions.length; _i < _len; _i++) { + position = positions[_i]; + if (position.top !== previous_top) { + if (group.length) { + handle_group(group, previous_top, position.top); + } + previous_top = position.top; + group = []; + } + group.push(position); + } + return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height()); + }; + handleNode = function(node, next_node, $element) { + var top; + top = getTop($element); + if (node === _this.current_item.node) { + addPosition(node, Position.NONE, top); + } else { + addPosition(node, Position.INSIDE, top); + } + if (next_node === _this.current_item.node || node === _this.current_item.node) { + return addPosition(node, Position.NONE, top); + } else { + return addPosition(node, Position.AFTER, top); + } + }; + handleOpenFolder = function(node, $element) { + if (node === _this.current_item.node) { + return false; + } + if (node.children[0] !== _this.current_item.node) { + addPosition(node, Position.INSIDE, getTop($element)); + } + return true; + }; + handleAfterOpenFolder = function(node, next_node, $element) { + if (node === _this.current_item.node || next_node === _this.current_item.node) { + return addPosition(node, Position.NONE, last_top); + } else { + return addPosition(node, Position.AFTER, last_top); + } + }; + handleClosedFolder = function(node, next_node, $element) { + var top; + top = getTop($element); + if (node === _this.current_item.node) { + return addPosition(node, Position.NONE, top); + } else { + addPosition(node, Position.INSIDE, top); + if (next_node !== _this.current_item.node) { + return addPosition(node, Position.AFTER, top); + } + } + }; + handleFirstNode = function(node, $element) { + if (node !== _this.current_item.node) { + return addPosition(node, Position.BEFORE, getTop($(node.element))); + } + }; + this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); + hit_areas = []; + groupPositions(function(positions_in_group, top, bottom) { + var area_height, area_top, position, _i, _len; + area_height = (bottom - top) / positions_in_group.length; + area_top = top; + for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { + position = positions_in_group[_i]; + hit_areas.push({ + top: area_top, + bottom: area_top + area_height, + node: position.node, + position: position.position + }); + area_top += area_height; + } + return null; + }); + return this.hit_areas = hit_areas; + }; + + DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { + var is_first_node, iterate, + _this = this; + is_first_node = true; + iterate = function(node, next_node) { + var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref; + must_iterate_inside = (node.is_open || !node.element) && node.hasChildren(); + if (node.element) { + $element = $(node.element); + if (!$element.is(':visible')) { + return; + } + if (is_first_node) { + handle_first_node(node, $element); + is_first_node = false; + } + if (!node.hasChildren()) { + handle_node(node, next_node, $element); + } else if (node.is_open) { + if (!handle_open_folder(node, $element)) { + must_iterate_inside = false; + } + } else { + handle_closed_folder(node, next_node, $element); + } + } + if (must_iterate_inside) { + children_length = node.children.length; + _ref = node.children; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + child = _ref[i]; + if (i === (children_length - 1)) { + iterate(node.children[i], null); + } else { + iterate(node.children[i], node.children[i + 1]); + } + } + if (node.is_open) { + return handle_after_open_folder(node, next_node, $element); + } + } + }; + return iterate(this.tree_widget.tree); + }; + + DragAndDropHandler.prototype.findHoveredArea = function(x, y) { + var area, high, low, mid, tree_offset; + tree_offset = this.tree_widget.element.offset(); + if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) { + return null; + } + low = 0; + high = this.hit_areas.length; + while (low < high) { + mid = (low + high) >> 1; + area = this.hit_areas[mid]; + if (y < area.top) { + high = mid; + } else if (y > area.bottom) { + low = mid + 1; + } else { + return area; + } + } + return null; + }; + + DragAndDropHandler.prototype.updateDropHint = function() { + var node, node_element; + this.stopOpenFolderTimer(); + if (!this.hovered_area) { + return; + } + node = this.hovered_area.node; + if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) { + this.startOpenFolderTimer(node); + } + this.removeDropHint(); + node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node); + return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); + }; + + DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { + var openFolder, + _this = this; + openFolder = function() { + return _this.tree_widget._getNodeElementForNode(folder).open(function() { + _this.refreshHitAreas(); + return _this.updateDropHint(); + }); + }; + return this.open_folder_timer = setTimeout(openFolder, 500); + }; + + DragAndDropHandler.prototype.stopOpenFolderTimer = function() { + if (this.open_folder_timer) { + clearTimeout(this.open_folder_timer); + return this.open_folder_timer = null; + } + }; + + DragAndDropHandler.prototype.moveItem = function() { + var doMove, event, moved_node, position, previous_parent, target_node, + _this = this; + if (this.hovered_area && this.hovered_area.position !== Position.NONE) { + moved_node = this.current_item.node; + target_node = this.hovered_area.node; + position = this.hovered_area.position; + previous_parent = moved_node.parent; + if (position === Position.INSIDE) { + this.hovered_area.node.is_open = true; + } + doMove = function() { + _this.tree_widget.tree.moveNode(moved_node, target_node, position); + _this.tree_widget.element.empty(); + return _this.tree_widget._refreshElements(); + }; + event = $.Event('tree.move'); + event.move_info = { + moved_node: moved_node, + target_node: target_node, + position: Position.getName(position), + previous_parent: previous_parent, + do_move: doMove + }; + this.tree_widget.element.trigger(event); + if (!event.isDefaultPrevented()) { + return doMove(); + } + } + }; + + return DragAndDropHandler; + + })(); + + this.Tree.Node = Node; + +}).call(this);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomIntegerPixelAccessor.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,186 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomIntegerPixelAccessor.h" + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include "../Core/PalanthirException.h" +#include "FromDcmtkBridge.h" +#include <boost/lexical_cast.hpp> +#include <limits> + +namespace Palanthir +{ + DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values, + const void* pixelData, + size_t size) : + pixelData_(pixelData), + size_(size) + { + unsigned int bitsAllocated; + unsigned int bitsStored; + unsigned int highBit; + unsigned int pixelRepresentation; + + try + { + width_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Columns").AsString()); + height_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Rows").AsString()); + samplesPerPixel_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "SamplesPerPixel").AsString()); + bitsAllocated = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsAllocated").AsString()); + bitsStored = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsStored").AsString()); + highBit = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "HighBit").AsString()); + pixelRepresentation = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "PixelRepresentation").AsString()); + } + catch (boost::bad_lexical_cast) + { + throw PalanthirException(ErrorCode_NotImplemented); + } + + frame_ = 0; + try + { + numberOfFrames_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "NumberOfFrames").AsString()); + } + catch (PalanthirException) + { + // If the tag "NumberOfFrames" is absent, assume there is a single frame + numberOfFrames_ = 1; + } + catch (boost::bad_lexical_cast) + { + throw PalanthirException(ErrorCode_NotImplemented); + } + + if ((bitsAllocated != 8 && bitsAllocated != 16 && + bitsAllocated != 24 && bitsAllocated != 32) || + numberOfFrames_ == 0) + { + throw PalanthirException(ErrorCode_NotImplemented); + } + + if (bitsAllocated > 32 || + bitsStored >= 32) + { + // Not available, as the accessor internally uses int32_t values + throw PalanthirException(ErrorCode_NotImplemented); + } + + if (samplesPerPixel_ != 1) + { + throw PalanthirException(ErrorCode_NotImplemented); + } + + if (width_ * height_ * bitsAllocated / 8 * numberOfFrames_ != size) + { + throw PalanthirException(ErrorCode_NotImplemented); + } + + /*printf("%d %d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated, + bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/ + + bytesPerPixel_ = bitsAllocated / 8; + shift_ = highBit + 1 - bitsStored; + + if (pixelRepresentation) + { + mask_ = (1 << (bitsStored - 1)) - 1; + signMask_ = (1 << (bitsStored - 1)); + } + else + { + mask_ = (1 << bitsStored) - 1; + signMask_ = 0; + } + + rowOffset_ = width_ * bytesPerPixel_; + frameOffset_ = height_ * width_ * bytesPerPixel_; + } + + + void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min, + int32_t& max) const + { + if (height_ == 0 || width_ == 0) + { + min = max = 0; + return; + } + + min = std::numeric_limits<int32_t>::max(); + max = std::numeric_limits<int32_t>::min(); + + for (unsigned int y = 0; y < height_; y++) + { + for (unsigned int x = 0; x < width_; x++) + { + int32_t v = GetValue(x, y); + if (v < min) + min = v; + if (v > max) + max = v; + } + } + } + + + int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, unsigned int y) const + { + assert(x < width_ && y < height_); + + const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + + y * rowOffset_ + x * bytesPerPixel_ + frame_ * frameOffset_; + + int32_t v; + v = pixel[0]; + if (bytesPerPixel_ >= 2) + v = v + (static_cast<int32_t>(pixel[1]) << 8); + if (bytesPerPixel_ >= 3) + v = v + (static_cast<int32_t>(pixel[2]) << 16); + if (bytesPerPixel_ >= 4) + v = v + (static_cast<int32_t>(pixel[3]) << 24); + + v = (v >> shift_) & mask_; + + if (v & signMask_) + { + // Signed value: Not implemented yet + //throw PalanthirException(ErrorCode_NotImplemented); + v = 0; + } + + return v; + } + + + void DicomIntegerPixelAccessor::SetCurrentFrame(unsigned int frame) + { + if (frame >= numberOfFrames_) + { + throw PalanthirException(ErrorCode_ParameterOutOfRange); + } + + frame_ = frame; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomIntegerPixelAccessor.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,80 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" + +#include <stdint.h> + +namespace Palanthir +{ + class DicomIntegerPixelAccessor + { + private: + unsigned int width_; + unsigned int height_; + unsigned int samplesPerPixel_; + unsigned int numberOfFrames_; + const void* pixelData_; + size_t size_; + + uint8_t shift_; + uint32_t signMask_; + uint32_t mask_; + size_t bytesPerPixel_; + unsigned int frame_; + + size_t frameOffset_; + size_t rowOffset_; + + public: + DicomIntegerPixelAccessor(const DicomMap& values, + const void* pixelData, + size_t size); + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + unsigned int GetNumberOfFrames() const + { + return numberOfFrames_; + } + + unsigned int GetCurrentFrame() const + { + return frame_; + } + + void SetCurrentFrame(unsigned int frame); + + void GetExtremeValues(int32_t& min, + int32_t& max) const; + + int32_t GetValue(unsigned int x, unsigned int y) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomFindAnswers.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,54 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomFindAnswers.h" + +#include "../FromDcmtkBridge.h" + +namespace Palanthir +{ + void DicomFindAnswers::Clear() + { + for (size_t i = 0; i < items_.size(); i++) + { + delete items_[i]; + } + } + + void DicomFindAnswers::Reserve(size_t size) + { + if (size > items_.size()) + { + items_.reserve(size); + } + } + + void DicomFindAnswers::ToJson(Json::Value& target) const + { + target = Json::arrayValue; + + for (size_t i = 0; i < GetSize(); i++) + { + Json::Value answer(Json::objectValue); + FromDcmtkBridge::ToJson(answer, GetAnswer(i)); + target.append(answer); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomFindAnswers.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,62 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <json/json.h> + +namespace Palanthir +{ + class DicomFindAnswers + { + private: + std::vector<DicomMap*> items_; + + public: + ~DicomFindAnswers() + { + Clear(); + } + + void Clear(); + + void Reserve(size_t index); + + void Add(const DicomMap& map) + { + items_.push_back(map.Clone()); + } + + size_t GetSize() const + { + return items_.size(); + } + + const DicomMap& GetAnswer(size_t index) const + { + return *items_.at(index); + } + + void ToJson(Json::Value& target) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomServer.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,305 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomServer.h" + +#include "../../Core/PalanthirException.h" +#include "../../Core/Toolbox.h" +#include "../Internals/CommandDispatcher.h" + +#include <boost/thread.hpp> +#include <dcmtk/dcmdata/dcdict.h> + + +namespace Palanthir +{ + struct DicomServer::PImpl + { + boost::thread thread_; + + //std::set< + }; + + + namespace Internals + { + OFLogger Logger = OFLog::getLogger("dcmtk.apps.storescp"); + } + + + void DicomServer::ServerThread(DicomServer* server) + { + /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */ + dcmDisableGethostbyaddr.set(OFTrue); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(Internals::Logger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + T_ASC_Network *net; + OFCondition cond = ASC_initializeNetwork + (NET_ACCEPTOR, OFstatic_cast(int, server->port_), /*opt_acse_timeout*/ 30, &net); + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "cannot create network: " << DimseCondition::dump(temp_str, cond)); + throw PalanthirException("Cannot create network"); + } + + OFLOG_WARN(Internals::Logger, "DICOM server started"); + + server->started_ = true; + + while (server->continue_) + { + /* receive an association and acknowledge or reject it. If the association was */ + /* acknowledged, offer corresponding services and invoke one or more if required. */ + std::auto_ptr<Internals::CommandDispatcher> dispatcher(Internals::AcceptAssociation(*server, net)); + + if (dispatcher.get() != NULL) + { + if (server->isThreaded_) + { + server->bagOfDispatchers_.Add(dispatcher.release()); + } + else + { + IRunnableBySteps::RunUntilDone(*dispatcher); + } + } + } + + OFLOG_WARN(Internals::Logger, "DICOM server stopping"); + + /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ + /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ + cond = ASC_dropNetwork(&net); + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + } + + + DicomServer::DicomServer() : pimpl_(new PImpl) + { + aet_ = "ANY-SCP"; + port_ = 104; + findRequestHandlerFactory_ = NULL; + moveRequestHandlerFactory_ = NULL; + storeRequestHandlerFactory_ = NULL; + applicationEntityFilter_ = NULL; + checkCalledAet_ = true; + clientTimeout_ = 30; + isThreaded_ = true; + } + + DicomServer::~DicomServer() + { + Stop(); + } + + void DicomServer::SetPortNumber(uint16_t port) + { + Stop(); + port_ = port; + } + + uint16_t DicomServer::GetPortNumber() const + { + return port_; + } + + void DicomServer::SetThreaded(bool isThreaded) + { + Stop(); + isThreaded_ = isThreaded; + } + + bool DicomServer::IsThreaded() const + { + return isThreaded_; + } + + void DicomServer::SetClientTimeout(uint32_t timeout) + { + Stop(); + clientTimeout_ = timeout; + } + + uint32_t DicomServer::GetClientTimeout() const + { + return clientTimeout_; + } + + + void DicomServer::SetCalledApplicationEntityTitleCheck(bool check) + { + Stop(); + checkCalledAet_ = check; + } + + bool DicomServer::HasCalledApplicationEntityTitleCheck() const + { + return checkCalledAet_; + } + + void DicomServer::SetApplicationEntityTitle(const std::string& aet) + { + if (aet.size() == 0) + { + throw PalanthirException("Too short AET"); + } + + for (size_t i = 0; i < aet.size(); i++) + { + if (!isalnum(aet[i]) && aet[i] != '-') + { + throw PalanthirException("Only alphanumeric characters are allowed in AET"); + } + } + + Stop(); + aet_ = aet; + } + + const std::string& DicomServer::GetApplicationEntityTitle() const + { + return aet_; + } + + void DicomServer::SetFindRequestHandlerFactory(IFindRequestHandlerFactory& factory) + { + Stop(); + findRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasFindRequestHandlerFactory() const + { + return (findRequestHandlerFactory_ != NULL); + } + + IFindRequestHandlerFactory& DicomServer::GetFindRequestHandlerFactory() const + { + if (HasFindRequestHandlerFactory()) + { + return *findRequestHandlerFactory_; + } + else + { + throw PalanthirException("No C-FIND request handler factory"); + } + } + + void DicomServer::SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& factory) + { + Stop(); + moveRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasMoveRequestHandlerFactory() const + { + return (moveRequestHandlerFactory_ != NULL); + } + + IMoveRequestHandlerFactory& DicomServer::GetMoveRequestHandlerFactory() const + { + if (HasMoveRequestHandlerFactory()) + { + return *moveRequestHandlerFactory_; + } + else + { + throw PalanthirException("No C-MOVE request handler factory"); + } + } + + void DicomServer::SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& factory) + { + Stop(); + storeRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasStoreRequestHandlerFactory() const + { + return (storeRequestHandlerFactory_ != NULL); + } + + IStoreRequestHandlerFactory& DicomServer::GetStoreRequestHandlerFactory() const + { + if (HasStoreRequestHandlerFactory()) + { + return *storeRequestHandlerFactory_; + } + else + { + throw PalanthirException("No C-STORE request handler factory"); + } + } + + void DicomServer::SetApplicationEntityFilter(IApplicationEntityFilter& factory) + { + Stop(); + applicationEntityFilter_ = &factory; + } + + bool DicomServer::HasApplicationEntityFilter() const + { + return (applicationEntityFilter_ != NULL); + } + + IApplicationEntityFilter& DicomServer::GetApplicationEntityFilter() const + { + if (HasApplicationEntityFilter()) + { + return *applicationEntityFilter_; + } + else + { + throw PalanthirException("No application entity filter"); + } + } + + void DicomServer::Start() + { + Stop(); + continue_ = true; + started_ = false; + pimpl_->thread_ = boost::thread(ServerThread, this); + + while (!started_) + { + Toolbox::USleep(50000); // Wait 50ms + } + } + + void DicomServer::Stop() + { + continue_ = false; + pimpl_->thread_.join(); + + bagOfDispatchers_.StopAll(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomServer.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,97 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IFindRequestHandlerFactory.h" +#include "IMoveRequestHandlerFactory.h" +#include "IStoreRequestHandlerFactory.h" +#include "IApplicationEntityFilter.h" +#include "../../Core/MultiThreading/BagOfRunnablesBySteps.h" + +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +namespace Palanthir +{ + class DicomServer : public boost::noncopyable + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + bool checkCalledAet_; + std::string aet_; + uint16_t port_; + bool continue_; + bool started_; + uint32_t clientTimeout_; + bool isThreaded_; + IFindRequestHandlerFactory* findRequestHandlerFactory_; + IMoveRequestHandlerFactory* moveRequestHandlerFactory_; + IStoreRequestHandlerFactory* storeRequestHandlerFactory_; + IApplicationEntityFilter* applicationEntityFilter_; + + BagOfRunnablesBySteps bagOfDispatchers_; // This is used iff the server is threaded + + static void ServerThread(DicomServer* server); + + public: + DicomServer(); + + ~DicomServer(); + + void SetPortNumber(uint16_t port); + uint16_t GetPortNumber() const; + + void SetThreaded(bool isThreaded); + bool IsThreaded() const; + + void SetClientTimeout(uint32_t timeout); + uint32_t GetClientTimeout() const; + + void SetCalledApplicationEntityTitleCheck(bool check); + bool HasCalledApplicationEntityTitleCheck() const; + + void SetApplicationEntityTitle(const std::string& aet); + const std::string& GetApplicationEntityTitle() const; + + void SetFindRequestHandlerFactory(IFindRequestHandlerFactory& handler); + bool HasFindRequestHandlerFactory() const; + IFindRequestHandlerFactory& GetFindRequestHandlerFactory() const; + + void SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& handler); + bool HasMoveRequestHandlerFactory() const; + IMoveRequestHandlerFactory& GetMoveRequestHandlerFactory() const; + + void SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& handler); + bool HasStoreRequestHandlerFactory() const; + IStoreRequestHandlerFactory& GetStoreRequestHandlerFactory() const; + + void SetApplicationEntityFilter(IApplicationEntityFilter& handler); + bool HasApplicationEntityFilter() const; + IApplicationEntityFilter& GetApplicationEntityFilter() const; + + void Start(); + + void Stop(); + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,639 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomUserConnection.h" + +#include "../../Core/PalanthirException.h" +#include "../ToDcmtkBridge.h" +#include "../FromDcmtkBridge.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcistrmf.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmnet/diutil.h> + +#include <set> + + + +#ifdef _WIN32 +/** + * "The maximum length, in bytes, of the string returned in the buffer + * pointed to by the name parameter is dependent on the namespace provider, + * but this string must be 256 bytes or less. + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms738527(v=vs.85).aspx + **/ +#define HOST_NAME_MAX 256 +#endif + + +namespace Palanthir +{ + struct DicomUserConnection::PImpl + { + // Connection state + T_ASC_Network* net_; + T_ASC_Parameters* params_; + T_ASC_Association* assoc_; + + bool IsOpen() const + { + return assoc_ != NULL; + } + + void CheckIsOpen() const; + + void Store(DcmInputStream& is); + }; + + + static void Check(const OFCondition& cond) + { + if (cond.bad()) + { + throw PalanthirException("DicomUserConnection: " + std::string(cond.text())); + } + } + + void DicomUserConnection::PImpl::CheckIsOpen() const + { + if (!IsOpen()) + { + throw PalanthirException("DicomUserConnection: First open the connection"); + } + } + + + void DicomUserConnection::CheckIsOpen() const + { + pimpl_->CheckIsOpen(); + } + + + void DicomUserConnection::CopyParameters(const DicomUserConnection& other) + { + Close(); + localAet_ = other.localAet_; + distantAet_ = other.distantAet_; + distantHost_ = other.distantHost_; + distantPort_ = other.distantPort_; + } + + + void DicomUserConnection::SetupPresentationContexts() + { + // The preferred abstract syntax + std::string preferredSyntax = UID_LittleEndianImplicitTransferSyntax; + + // Fallback abstract syntaxes + std::set<std::string> abstractSyntaxes; + abstractSyntaxes.insert(UID_LittleEndianExplicitTransferSyntax); + abstractSyntaxes.insert(UID_BigEndianExplicitTransferSyntax); + abstractSyntaxes.insert(UID_LittleEndianImplicitTransferSyntax); + abstractSyntaxes.erase(preferredSyntax); + assert(abstractSyntaxes.size() == 2); + + // Transfer syntaxes for C-ECHO, C-FIND and C-MOVE + std::vector<std::string> transferSyntaxes; + transferSyntaxes.push_back(UID_VerificationSOPClass); + transferSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); + transferSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); + transferSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); + + // TODO: Allow the set below to be configured + std::set<std::string> uselessSyntaxes; + uselessSyntaxes.insert(UID_BlendingSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_GrayscaleSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_ColorSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_PseudoColorSoftcopyPresentationStateStorage); + + // Add the transfer syntaxes for C-STORE + for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs - 1; i++) + { + // Test to make some room to allow the ECHO and FIND requests + if (uselessSyntaxes.find(dcmShortSCUStorageSOPClassUIDs[i]) == uselessSyntaxes.end()) + { + transferSyntaxes.push_back(dcmShortSCUStorageSOPClassUIDs[i]); + } + } + + // Flatten the fallback abstract syntaxes array + const char* asPreferred[1] = { preferredSyntax.c_str() }; + const char* asFallback[2]; + std::set<std::string>::const_iterator it = abstractSyntaxes.begin(); + asFallback[0] = it->c_str(); + it++; + asFallback[1] = it->c_str(); + + unsigned int presentationContextId = 1; + for (size_t i = 0; i < transferSyntaxes.size(); i++) + { + Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, + transferSyntaxes[i].c_str(), asPreferred, 1)); + presentationContextId += 2; + + Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, + transferSyntaxes[i].c_str(), asFallback, 2)); + presentationContextId += 2; + } + } + + + void DicomUserConnection::PImpl::Store(DcmInputStream& is) + { + CheckIsOpen(); + + DcmFileFormat dcmff; + Check(dcmff.read(is, EXS_Unknown, EGL_noChange, DCM_MaxReadLength)); + + // Figure out which SOP class and SOP instance is encapsulated in the file + DIC_UI sopClass; + DIC_UI sopInstance; + if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) + { + throw PalanthirException("DicomUserConnection: Unable to find the SOP class and instance"); + } + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(assoc_, sopClass); + if (presID == 0) + { + const char *modalityName = dcmSOPClassUIDToModality(sopClass); + if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); + if (!modalityName) modalityName = "unknown SOP class"; + throw PalanthirException("DicomUserConnection: No presentation context for modality " + + std::string(modalityName)); + } + + // Prepare the transmission of data + T_DIMSE_C_StoreRQ req; + memset(&req, 0, sizeof(req)); + req.MessageID = assoc_->nextMsgID++; + strcpy(req.AffectedSOPClassUID, sopClass); + strcpy(req.AffectedSOPInstanceUID, sopInstance); + req.DataSetType = DIMSE_DATASET_PRESENT; + req.Priority = DIMSE_PRIORITY_MEDIUM; + + // Finally conduct transmission of data + T_DIMSE_C_StoreRSP rsp; + DcmDataset* statusDetail = NULL; + Check(DIMSE_storeUser(assoc_, presID, &req, + NULL, dcmff.getDataset(), /*progressCallback*/ NULL, NULL, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &rsp, &statusDetail, NULL)); + + if (statusDetail != NULL) + { + delete statusDetail; + } + } + + + static void FindCallback( + /* in */ + void *callbackData, + T_DIMSE_C_FindRQ *request, /* original find request */ + int responseCount, + T_DIMSE_C_FindRSP *response, /* pending response received */ + DcmDataset *responseIdentifiers /* pending response identifiers */ + ) + { + DicomFindAnswers& answers = *(DicomFindAnswers*) callbackData; + + if (responseIdentifiers != NULL) + { + DicomMap m; + FromDcmtkBridge::Convert(m, *responseIdentifiers); + answers.Add(m); + } + } + + void DicomUserConnection::Find(DicomFindAnswers& result, + FindRootModel model, + const DicomMap& fields) + { + CheckIsOpen(); + + const char* sopClass; + std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); + switch (model) + { + case FindRootModel_Patient: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); + sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Patient ID + if (!fields.HasTag(0x0010, 0x0020)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); + + break; + + case FindRootModel_Study: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + break; + + case FindRootModel_Series: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + // Series instance UID + if (!fields.HasTag(0x0020, 0x000e)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); + + break; + + case FindRootModel_Instance: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + // Series instance UID + if (!fields.HasTag(0x0020, 0x000e)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); + + // SOP Instance UID + if (!fields.HasTag(0x0008, 0x0018)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); + + break; + + default: + throw PalanthirException(ErrorCode_ParameterOutOfRange); + } + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); + if (presID == 0) + { + throw PalanthirException("DicomUserConnection: The C-FIND command is not supported by the distant AET"); + } + + T_DIMSE_C_FindRQ request; + memset(&request, 0, sizeof(request)); + request.MessageID = pimpl_->assoc_->nextMsgID++; + strcpy(request.AffectedSOPClassUID, sopClass); + request.DataSetType = DIMSE_DATASET_PRESENT; + request.Priority = DIMSE_PRIORITY_MEDIUM; + + T_DIMSE_C_FindRSP response; + DcmDataset* statusDetail = NULL; + OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(), + FindCallback, &result, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &response, &statusDetail); + + if (statusDetail) + { + delete statusDetail; + } + + Check(cond); + } + + + void DicomUserConnection::FindPatient(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the patient + DicomMap s; + fields.ExtractPatientInformation(s); + Find(result, FindRootModel_Patient, s); + } + + void DicomUserConnection::FindStudy(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the study + DicomMap s; + fields.ExtractStudyInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + + Find(result, FindRootModel_Study, s); + } + + void DicomUserConnection::FindSeries(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the series + DicomMap s; + fields.ExtractSeriesInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + s.CopyTagIfExists(fields, DicomTag::STUDY_UID); + + Find(result, FindRootModel_Series, s); + } + + void DicomUserConnection::FindInstance(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the instance + DicomMap s; + fields.ExtractInstanceInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + s.CopyTagIfExists(fields, DicomTag::STUDY_UID); + s.CopyTagIfExists(fields, DicomTag::SERIES_UID); + + Find(result, FindRootModel_Instance, s); + } + + + void DicomUserConnection::Move(const std::string& targetAet, + const DicomMap& fields) + { + CheckIsOpen(); + + const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; + std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); + if (presID == 0) + { + throw PalanthirException("DicomUserConnection: The C-MOVE command is not supported by the distant AET"); + } + + T_DIMSE_C_MoveRQ request; + memset(&request, 0, sizeof(request)); + request.MessageID = pimpl_->assoc_->nextMsgID++; + strcpy(request.AffectedSOPClassUID, sopClass); + request.DataSetType = DIMSE_DATASET_PRESENT; + request.Priority = DIMSE_PRIORITY_MEDIUM; + strncpy(request.MoveDestination, targetAet.c_str(), sizeof(DIC_AE) / sizeof(char)); + + T_DIMSE_C_MoveRSP response; + DcmDataset* statusDetail = NULL; + DcmDataset* responseIdentifiers = NULL; + OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset.get(), + NULL, NULL, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + pimpl_->net_, NULL, NULL, + &response, &statusDetail, &responseIdentifiers); + + if (statusDetail) + { + delete statusDetail; + } + + if (responseIdentifiers) + { + delete responseIdentifiers; + } + + Check(cond); + } + + + DicomUserConnection::DicomUserConnection() : pimpl_(new PImpl) + { + localAet_ = "STORESCU"; + distantAet_ = "ANY-SCP"; + distantPort_ = 104; + distantHost_ = "127.0.0.1"; + + pimpl_->net_ = NULL; + pimpl_->params_ = NULL; + pimpl_->assoc_ = NULL; + } + + DicomUserConnection::~DicomUserConnection() + { + Close(); + } + + void DicomUserConnection::SetLocalApplicationEntityTitle(const std::string& aet) + { + Close(); + localAet_ = aet; + } + + void DicomUserConnection::SetDistantApplicationEntityTitle(const std::string& aet) + { + Close(); + distantAet_ = aet; + } + + + void DicomUserConnection::SetDistantHost(const std::string& host) + { + if (host.size() > HOST_NAME_MAX - 10) + { + throw PalanthirException("Distant host name is too long"); + } + + Close(); + distantHost_ = host; + } + + void DicomUserConnection::SetDistantPort(uint16_t port) + { + Close(); + distantPort_ = port; + } + + void DicomUserConnection::Open() + { + Close(); + + Check(ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ 30, &pimpl_->net_)); + Check(ASC_createAssociationParameters(&pimpl_->params_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU)); + + // Set this application's title and the called application's title in the params + Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), distantAet_.c_str(), NULL)); + + // Set the network addresses of the local and distant entities + char localHost[HOST_NAME_MAX]; + gethostname(localHost, HOST_NAME_MAX - 1); + + char distantHostAndPort[HOST_NAME_MAX]; + +#ifdef _MSC_VER + _snprintf +#else + snprintf +#endif + (distantHostAndPort, HOST_NAME_MAX - 1, "%s:%d", distantHost_.c_str(), distantPort_); + + Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, distantHostAndPort)); + + // Set various options + Check(ASC_setTransportLayerType(pimpl_->params_, /*opt_secureConnection*/ false)); + + SetupPresentationContexts(); + + // Do the association + Check(ASC_requestAssociation(pimpl_->net_, pimpl_->params_, &pimpl_->assoc_)); + + if (ASC_countAcceptedPresentationContexts(pimpl_->params_) == 0) + { + throw PalanthirException("DicomUserConnection: No Acceptable Presentation Contexts"); + } + } + + void DicomUserConnection::Close() + { + if (pimpl_->assoc_ != NULL) + { + ASC_releaseAssociation(pimpl_->assoc_); + ASC_destroyAssociation(&pimpl_->assoc_); + pimpl_->assoc_ = NULL; + pimpl_->params_ = NULL; + } + else + { + if (pimpl_->params_ != NULL) + { + ASC_destroyAssociationParameters(&pimpl_->params_); + pimpl_->params_ = NULL; + } + } + + if (pimpl_->net_ != NULL) + { + ASC_dropNetwork(&pimpl_->net_); + pimpl_->net_ = NULL; + } + } + + bool DicomUserConnection::IsOpen() const + { + return pimpl_->IsOpen(); + } + + void DicomUserConnection::Store(const char* buffer, size_t size) + { + // Prepare an input stream for the memory buffer + DcmInputBufferStream is; + if (size > 0) + is.setBuffer(buffer, size); + is.setEos(); + + pimpl_->Store(is); + } + + void DicomUserConnection::Store(const std::string& buffer) + { + if (buffer.size() > 0) + Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); + else + Store(NULL, 0); + } + + void DicomUserConnection::StoreFile(const std::string& path) + { + // Prepare an input stream for the file + DcmInputFileStream is(path.c_str()); + pimpl_->Store(is); + } + + bool DicomUserConnection::Echo() + { + CheckIsOpen(); + DIC_US status; + Check(DIMSE_echoUser(pimpl_->assoc_, pimpl_->assoc_->nextMsgID++, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &status, NULL)); + return status == STATUS_Success; + } + + + void DicomUserConnection::MoveSeries(const std::string& targetAet, + const DicomMap& findResult) + { + DicomMap simplified; + simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); + simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); + Move(targetAet, simplified); + } + + void DicomUserConnection::MoveSeries(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid) + { + DicomMap map; + map.SetValue(DicomTag::STUDY_UID, studyUid); + map.SetValue(DicomTag::SERIES_UID, seriesUid); + Move(targetAet, map); + } + + void DicomUserConnection::MoveInstance(const std::string& targetAet, + const DicomMap& findResult) + { + DicomMap simplified; + simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); + simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); + simplified.SetValue(DicomTag::INSTANCE_UID, findResult.GetValue(DicomTag::INSTANCE_UID)); + Move(targetAet, simplified); + } + + void DicomUserConnection::MoveInstance(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid, + const std::string& instanceUid) + { + DicomMap map; + map.SetValue(DicomTag::STUDY_UID, studyUid); + map.SetValue(DicomTag::SERIES_UID, seriesUid); + map.SetValue(DicomTag::INSTANCE_UID, instanceUid); + Move(targetAet, map); + } + + void DicomUserConnection::SetConnectionTimeout(uint32_t seconds) + { + dcmConnectionTimeout.set(seconds); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,140 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomFindAnswers.h" + +#include <stdint.h> +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +namespace Palanthir +{ + class DicomUserConnection : public boost::noncopyable + { + private: + enum FindRootModel + { + FindRootModel_Patient, + FindRootModel_Study, + FindRootModel_Series, + FindRootModel_Instance + }; + + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + // Connection parameters + std::string localAet_; + std::string distantAet_; + std::string distantHost_; + uint16_t distantPort_; + + void CheckIsOpen() const; + + void SetupPresentationContexts(); + + void Find(DicomFindAnswers& result, + FindRootModel model, + const DicomMap& fields); + + void Move(const std::string& targetAet, + const DicomMap& fields); + + public: + DicomUserConnection(); + + ~DicomUserConnection(); + + void CopyParameters(const DicomUserConnection& other); + + void SetLocalApplicationEntityTitle(const std::string& aet); + + const std::string& GetLocalApplicationEntityTitle() const + { + return localAet_; + } + + void SetDistantApplicationEntityTitle(const std::string& aet); + + const std::string& GetDistantApplicationEntityTitle() const + { + return distantAet_; + } + + void SetDistantHost(const std::string& host); + + const std::string& GetDistantHost() const + { + return distantHost_; + } + + void SetDistantPort(uint16_t port); + + uint16_t GetDistantPort() const + { + return distantPort_; + } + + void Open(); + + void Close(); + + bool IsOpen() const; + + bool Echo(); + + void Store(const char* buffer, size_t size); + + void Store(const std::string& buffer); + + void StoreFile(const std::string& path); + + void FindPatient(DicomFindAnswers& result, + const DicomMap& fields); + + void FindStudy(DicomFindAnswers& result, + const DicomMap& fields); + + void FindSeries(DicomFindAnswers& result, + const DicomMap& fields); + + void FindInstance(DicomFindAnswers& result, + const DicomMap& fields); + + void MoveSeries(const std::string& targetAet, + const DicomMap& findResult); + + void MoveSeries(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid); + + void MoveInstance(const std::string& targetAet, + const DicomMap& findResult); + + void MoveInstance(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid, + const std::string& instanceUid); + + static void SetConnectionTimeout(uint32_t seconds); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IApplicationEntityFilter.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> + +namespace Palanthir +{ + class IApplicationEntityFilter + { + public: + virtual ~IApplicationEntityFilter() + { + } + + virtual bool IsAllowed(const std::string& callingIp, + const std::string& callingAet) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IFindRequestHandler.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,41 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomFindAnswers.h" + +#include <vector> +#include <string> + + +namespace Palanthir +{ + class IFindRequestHandler + { + public: + virtual ~IFindRequestHandler() + { + } + + virtual void Handle(const DicomMap& input, + DicomFindAnswers& answers) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IFindRequestHandlerFactory.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IFindRequestHandler.h" + +namespace Palanthir +{ + class IFindRequestHandlerFactory + { + public: + virtual ~IFindRequestHandlerFactory() + { + } + + virtual IFindRequestHandler* ConstructFindRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IMoveRequestHandler.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,62 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <string> + + +namespace Palanthir +{ + class IMoveRequestIterator + { + public: + enum Status + { + Status_Success, + Status_Failure, + Status_Warning + }; + + virtual ~IMoveRequestIterator() + { + } + + virtual unsigned int GetSubOperationCount() const = 0; + + virtual Status DoNext() = 0; + }; + + + class IMoveRequestHandler + { + public: + virtual ~IMoveRequestHandler() + { + } + + virtual IMoveRequestIterator* Handle(const std::string& target, + const DicomMap& input) = 0; + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IMoveRequestHandlerFactory.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IMoveRequestHandler.h" + +namespace Palanthir +{ + class IMoveRequestHandlerFactory + { + public: + virtual ~IMoveRequestHandlerFactory() + { + } + + virtual IMoveRequestHandler* ConstructMoveRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IStoreRequestHandler.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,43 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <string> +#include <json/json.h> + +namespace Palanthir +{ + class IStoreRequestHandler + { + public: + virtual ~IStoreRequestHandler() + { + } + + virtual void Handle(const std::vector<uint8_t>& dicomFile, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IStoreRequestHandlerFactory.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IStoreRequestHandler.h" + +namespace Palanthir +{ + class IStoreRequestHandlerFactory + { + public: + virtual ~IStoreRequestHandlerFactory() + { + } + + virtual IStoreRequestHandler* ConstructStoreRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/FromDcmtkBridge.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,599 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "FromDcmtkBridge.h" + +#include "ToDcmtkBridge.h" +#include "DicomIntegerPixelAccessor.h" +#include "../Core/PalanthirException.h" +#include "../Core/PngWriter.h" +#include "../Core/DicomFormat/DicomString.h" +#include "../Core/DicomFormat/DicomNullValue.h" + +#include <boost/locale.hpp> +#include <boost/lexical_cast.hpp> + +#include <dcmtk/dcmdata/dcdicent.h> +#include <dcmtk/dcmdata/dcdict.h> +#include <dcmtk/dcmdata/dcelem.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcsequen.h> +#include <dcmtk/dcmdata/dcvrfd.h> +#include <dcmtk/dcmdata/dcvrfl.h> +#include <dcmtk/dcmdata/dcvrsl.h> +#include <dcmtk/dcmdata/dcvrss.h> +#include <dcmtk/dcmdata/dcvrul.h> +#include <dcmtk/dcmdata/dcvrus.h> + +#include <boost/math/special_functions/round.hpp> + +namespace Palanthir +{ + void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset) + { + target.Clear(); + for (unsigned long i = 0; i < dataset.card(); i++) + { + DcmElement* element = dataset.getElement(i); + if (element && element->isLeaf()) + { + target.SetValue(element->getTag().getGTag(), + element->getTag().getETag(), + ConvertLeafElement(*element)); + } + } + } + + + DicomTag FromDcmtkBridge::GetTag(const DcmElement& element) + { + return DicomTag(element.getGTag(), element.getETag()); + } + + + DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element) + { + if (!element.isLeaf()) + { + throw PalanthirException("Only applicable to leaf elements"); + } + + if (element.isaString()) + { + char *c; + if (element.getString(c).good() && + c != NULL) + { + std::string s(c); + std::string utf8; + try + { + utf8 = boost::locale::conv::to_utf<char>(s, "ISO-8859-1"); // TODO Parameter? + } + catch (std::runtime_error&) + { + // Bad input string or bad encoding + utf8 = s; + } + + return new DicomString(utf8); + } + else + { + return new DicomNullValue; + } + } + + try + { + // http://support.dcmtk.org/docs/dcvr_8h-source.html + switch (element.getVR()) + { + + /** + * TODO. + **/ + + case EVR_DS: // decimal string + case EVR_IS: // integer string + case EVR_OB: // other byte + case EVR_OF: // other float + case EVR_OW: // other word + case EVR_AS: // age string + case EVR_AT: // attribute tag + case EVR_DA: // date string + case EVR_DT: // date time string + case EVR_TM: // time string + case EVR_UN: // unknown value representation + return new DicomNullValue(); + + + /** + * String types, should never happen at this point because of + * "element.isaString()". + **/ + + case EVR_AE: // application entity title + case EVR_CS: // code string + case EVR_SH: // short string + case EVR_LO: // long string + case EVR_ST: // short text + case EVR_LT: // long text + case EVR_UT: // unlimited text + case EVR_PN: // person name + case EVR_UI: // unique identifier + return new DicomNullValue(); + + + /** + * Numerical types + **/ + + case EVR_SL: // signed long + { + Sint32 f; + if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_SS: // signed short + { + Sint16 f; + if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_UL: // unsigned long + { + Uint32 f; + if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_US: // unsigned short + { + Uint16 f; + if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_FL: // float single-precision + { + Float32 f; + if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_FD: // float double-precision + { + Float64 f; + if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + + /** + * Sequence types, should never occur at this point because of + * "element.isLeaf()". + **/ + + case EVR_SQ: // sequence of items + return new DicomNullValue; + + + /** + * Internal to DCMTK. + **/ + + case EVR_ox: // OB or OW depending on context + case EVR_xs: // SS or US depending on context + case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) + case EVR_na: // na="not applicable", for data which has no VR + case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor + case EVR_item: // used internally for items + case EVR_metainfo: // used internally for meta info datasets + case EVR_dataset: // used internally for datasets + case EVR_fileFormat: // used internally for DICOM files + case EVR_dicomDir: // used internally for DICOMDIR objects + case EVR_dirRecord: // used internally for DICOMDIR records + case EVR_pixelSQ: // used internally for pixel sequences in a compressed image + case EVR_pixelItem: // used internally for pixel items in a compressed image + case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) + case EVR_PixelData: // used internally for uncompressed pixeld data + case EVR_OverlayData: // used internally for overlay data + case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR + return new DicomNullValue; + + + /** + * Default case. + **/ + + default: + return new DicomNullValue; + } + } + catch (boost::bad_lexical_cast) + { + return new DicomNullValue; + } + } + + + static void StoreElement(Json::Value& target, + DcmElement& element, + unsigned int maxStringLength); + + static void StoreItem(Json::Value& target, + DcmItem& item, + unsigned int maxStringLength) + { + target = Json::Value(Json::objectValue); + + for (unsigned long i = 0; i < item.card(); i++) + { + DcmElement* element = item.getElement(i); + StoreElement(target, *element, maxStringLength); + } + } + + + static void StoreElement(Json::Value& target, + DcmElement& element, + unsigned int maxStringLength) + { + assert(target.type() == Json::objectValue); + + DicomTag tag(FromDcmtkBridge::GetTag(element)); + const std::string tagName = FromDcmtkBridge::GetName(tag); + const std::string formattedTag = tag.Format(); + + if (element.isLeaf()) + { + Json::Value value(Json::objectValue); + value["Name"] = tagName; + + std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); + if (v->IsNull()) + { + value["Type"] = "Null"; + value["Value"] = Json::nullValue; + } + else + { + std::string s = v->AsString(); + if (maxStringLength == 0 || + s.size() <= maxStringLength) + { + value["Type"] = "String"; + value["Value"] = s; + } + else + { + value["Type"] = "TooLong"; + value["Value"] = Json::nullValue; + } + } + + target[formattedTag] = value; + } + else + { + Json::Value children(Json::arrayValue); + + // "All subclasses of DcmElement except for DcmSequenceOfItems + // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset + // etc. are not." The following cast is thus OK. + DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element); + + for (unsigned long i = 0; i < sequence.card(); i++) + { + DcmItem* child = sequence.getItem(i); + Json::Value& v = children.append(Json::objectValue); + StoreItem(v, *child, maxStringLength); + } + + target[formattedTag]["Name"] = tagName; + target[formattedTag]["Type"] = "Sequence"; + target[formattedTag]["Value"] = children; + } + } + + + void FromDcmtkBridge::ToJson(Json::Value& root, + DcmDataset& dataset, + unsigned int maxStringLength) + { + StoreItem(root, dataset, maxStringLength); + } + + + + void FromDcmtkBridge::ToJson(Json::Value& target, + const std::string& path, + unsigned int maxStringLength) + { + DcmFileFormat dicom; + if (!dicom.loadFile(path.c_str()).good()) + { + throw PalanthirException(ErrorCode_BadFileFormat); + } + else + { + FromDcmtkBridge::ToJson(target, *dicom.getDataset(), maxStringLength); + } + } + + + static void ExtractPngImagePreview(std::string& result, + DicomIntegerPixelAccessor& accessor) + { + PngWriter w; + + int32_t min, max; + accessor.GetExtremeValues(min, max); + + std::vector<uint8_t> image(accessor.GetWidth() * accessor.GetHeight(), 0); + if (min != max) + { + uint8_t* pixel = &image[0]; + for (unsigned int y = 0; y < accessor.GetHeight(); y++) + { + for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) + { + int32_t v = accessor.GetValue(x, y); + *pixel = static_cast<uint8_t>( + boost::math::lround(static_cast<float>(v - min) / + static_cast<float>(max - min) * 255.0f)); + } + } + } + + w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), + accessor.GetWidth(), PixelFormat_Grayscale8, &image[0]); + } + + + template <typename T> + static void ExtractPngImageTruncate(std::string& result, + DicomIntegerPixelAccessor& accessor, + PixelFormat format) + { + PngWriter w; + + std::vector<T> image(accessor.GetWidth() * accessor.GetHeight(), 0); + T* pixel = &image[0]; + for (unsigned int y = 0; y < accessor.GetHeight(); y++) + { + for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) + { + int32_t v = accessor.GetValue(x, y); + if (v < std::numeric_limits<T>::min()) + *pixel = std::numeric_limits<T>::min(); + else if (v > std::numeric_limits<T>::max()) + *pixel = std::numeric_limits<T>::max(); + else + *pixel = static_cast<T>(v); + } + } + + w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), + accessor.GetWidth() * sizeof(T), format, &image[0]); + } + + + void FromDcmtkBridge::ExtractPngImage(std::string& result, + DcmDataset& dataset, + unsigned int frame, + ImageExtractionMode mode) + { + // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data + + std::auto_ptr<DicomIntegerPixelAccessor> accessor; + + DicomMap m; + FromDcmtkBridge::Convert(m, dataset); + + DcmElement* e; + if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DicomTag::PIXEL_DATA), e).good() && + e != NULL) + { + Uint8* pixData = NULL; + if (e->getUint8Array(pixData) == EC_Normal) + { + accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); + accessor->SetCurrentFrame(frame); + } + } + + PixelFormat format; + switch (mode) + { + case ImageExtractionMode_Preview: + case ImageExtractionMode_UInt8: + format = PixelFormat_Grayscale8; + break; + + case ImageExtractionMode_UInt16: + format = PixelFormat_Grayscale16; + break; + + default: + throw PalanthirException(ErrorCode_NotImplemented); + } + + if (accessor.get() == NULL || + accessor->GetWidth() == 0 || + accessor->GetHeight() == 0) + { + PngWriter w; + w.WriteToMemory(result, 0, 0, 0, format, NULL); + } + else + { + switch (mode) + { + case ImageExtractionMode_Preview: + ExtractPngImagePreview(result, *accessor); + break; + + case ImageExtractionMode_UInt8: + ExtractPngImageTruncate<uint8_t>(result, *accessor, format); + break; + + case ImageExtractionMode_UInt16: + ExtractPngImageTruncate<uint16_t>(result, *accessor, format); + break; + + default: + throw PalanthirException(ErrorCode_NotImplemented); + } + } + } + + + void FromDcmtkBridge::ExtractPngImage(std::string& result, + const std::string& dicomContent, + unsigned int frame, + ImageExtractionMode mode) + { + DcmInputBufferStream is; + if (dicomContent.size() > 0) + { + is.setBuffer(&dicomContent[0], dicomContent.size()); + } + is.setEos(); + + DcmFileFormat dicom; + if (dicom.read(is).good()) + { + ExtractPngImage(result, *dicom.getDataset(), frame, mode); + } + else + { + throw PalanthirException(ErrorCode_BadFileFormat); + } + } + + + + std::string FromDcmtkBridge::GetName(const DicomTag& t) + { + DcmTagKey tag(t.GetGroup(), t.GetElement()); + const DcmDataDictionary& dict = dcmDataDict.rdlock(); + const DcmDictEntry* entry = dict.findEntry(tag, NULL); + + std::string s("Unknown"); + if (entry != NULL) + { + s = std::string(entry->getTagName()); + } + + dcmDataDict.unlock(); + return s; + } + + + DicomTag FromDcmtkBridge::FindTag(const char* name) + { + const DcmDataDictionary& dict = dcmDataDict.rdlock(); + const DcmDictEntry* entry = dict.findEntry(name); + + if (entry == NULL) + { + dcmDataDict.unlock(); + throw PalanthirException("Unknown DICOM tag"); + } + else + { + DcmTagKey key = entry->getKey(); + DicomTag tag(key.getGroup(), key.getElement()); + dcmDataDict.unlock(); + return tag; + } + } + + + void FromDcmtkBridge::Print(FILE* fp, const DicomMap& m) + { + for (DicomMap::Map::const_iterator + it = m.map_.begin(); it != m.map_.end(); it++) + { + DicomTag t = it->first; + std::string s = it->second->AsString(); + printf("0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); + } + } + + + void FromDcmtkBridge::ToJson(Json::Value& result, + const DicomMap& values) + { + if (result.type() != Json::objectValue) + { + throw PalanthirException(ErrorCode_BadParameterType); + } + + result.clear(); + + for (DicomMap::Map::const_iterator + it = values.map_.begin(); it != values.map_.end(); it++) + { + result[GetName(it->first)] = it->second->AsString(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/FromDcmtkBridge.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,97 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" +#include <dcmtk/dcmdata/dcdatset.h> +#include <json/json.h> + +namespace Palanthir +{ + enum ImageExtractionMode + { + ImageExtractionMode_Preview, + ImageExtractionMode_UInt8, + ImageExtractionMode_UInt16 + }; + + class FromDcmtkBridge + { + public: + static void Convert(DicomMap& target, DcmDataset& dataset); + + static DicomTag GetTag(const DcmElement& element); + + static DicomValue* ConvertLeafElement(DcmElement& element); + + static void ToJson(Json::Value& target, + DcmDataset& dataset, + unsigned int maxStringLength = 256); + + static void ToJson(Json::Value& target, + const std::string& path, + unsigned int maxStringLength = 256); + + static void ExtractPngImage(std::string& result, + DcmDataset& dataset, + unsigned int frame, + ImageExtractionMode mode); + + static void ExtractPngImage(std::string& result, + const std::string& dicomContent, + unsigned int frame, + ImageExtractionMode mode); + + static std::string GetName(const DicomTag& tag); + + static DicomTag FindTag(const char* name); + + static DicomTag FindTag(const std::string& name) + { + return FindTag(name.c_str()); + } + + static bool HasTag(const DicomMap& fields, + const std::string& tagName) + { + return fields.HasTag(FindTag(tagName)); + } + + static const DicomValue& GetValue(const DicomMap& fields, + const std::string& tagName) + { + return fields.GetValue(FindTag(tagName)); + } + + static void SetValue(DicomMap& target, + const std::string& tagName, + DicomValue* value) + { + target.SetValue(FindTag(tagName), value); + } + + static void Print(FILE* fp, + const DicomMap& m); + + static void ToJson(Json::Value& result, + const DicomMap& values); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/CommandDispatcher.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,403 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "CommandDispatcher.h" + +#include "FindScp.h" +#include "StoreScp.h" +#include "MoveScp.h" +#include "../../Core/Toolbox.h" + +#include <dcmtk/dcmnet/dcasccfg.h> /* for class DcmAssociationConfiguration */ + +static OFBool opt_rejectWithoutImplementationUID = OFFalse; + + +namespace Palanthir +{ + namespace Internals + { + extern OFLogger Logger; + + + + OFCondition AssociationCleanup(T_ASC_Association *assoc) + { + OFString temp_str; + OFCondition cond = ASC_dropSCPAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); + return cond; + } + + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) + { + OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); + return cond; + } + + return cond; + } + + + + CommandDispatcher* AcceptAssociation(const DicomServer& server, T_ASC_Network *net) + { + DcmAssociationConfiguration asccfg; + char buf[BUFSIZ]; + T_ASC_Association *assoc; + OFCondition cond; + OFString sprofile; + OFString temp_str; + + std::vector<const char*> knownAbstractSyntaxes; + + // For C-STORE + if (server.HasStoreRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_VerificationSOPClass); + } + + // For C-FIND + if (server.HasFindRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); + knownAbstractSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); + } + + // For C-MOVE + if (server.HasMoveRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); + } + + const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + int numTransferSyntaxes = 0; + + cond = ASC_receiveAssociation(net, &assoc, + /*opt_maxPDU*/ ASC_DEFAULTMAXPDU, + NULL, NULL, + /*opt_secureConnection*/ OFFalse, + DUL_NOBLOCK, 1); + + if (cond == DUL_NOASSOCIATIONREQUEST) + { + // Timeout + AssociationCleanup(assoc); + return NULL; + } + + // if some kind of error occured, take care of it + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, "Receiving Association failed: " << DimseCondition::dump(temp_str, cond)); + // no matter what kind of error occurred, we need to do a cleanup + AssociationCleanup(assoc); + return NULL; + } + + OFLOG_INFO(Internals::Logger, "Association Received"); + + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + + /* accept the Verification SOP Class if presented */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + + /* the array of Storage SOP Class UIDs comes from dcuid.h */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + + /* set our app title */ + ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); + + /* acknowledge or reject this association */ + cond = ASC_getApplicationContextName(assoc->params, buf); + if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) + { + /* reject: the application context name is not supported */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED + }; + + OFLOG_INFO(Internals::Logger, "Association Rejected: Bad Application Context Name: " << buf); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + AssociationCleanup(assoc); + return NULL; + } + + /* check the AETs */ + { + DIC_AE callingTitle_C; + DIC_AE calledTitle_C; + DIC_AE callingIP_C; + DIC_AE calledIP_C; + if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() || + ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad()) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + + std::string callingIP(OFSTRING_GUARD(callingIP_C)); + std::string callingTitle(OFSTRING_GUARD(callingTitle_C)); + std::string calledTitle(OFSTRING_GUARD(calledTitle_C)); + Toolbox::ToUpperCase(callingIP); + Toolbox::ToUpperCase(callingTitle); + Toolbox::ToUpperCase(calledTitle); + + if (server.HasCalledApplicationEntityTitleCheck() && + calledTitle != server.GetApplicationEntityTitle()) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + + if (server.HasApplicationEntityFilter() && + !server.GetApplicationEntityFilter().IsAllowed(callingIP, callingTitle)) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + } + + if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0) + { + /* reject: the no implementation Class UID provided */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + + OFLOG_INFO(Internals::Logger, "Association Rejected: No Implementation Class UID provided"); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + AssociationCleanup(assoc); + return NULL; + } + + { + cond = ASC_acknowledgeAssociation(assoc); + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + OFLOG_INFO(Internals::Logger, "Association Acknowledged (Max Send PDV: " << assoc->sendPDVLength << ")"); + if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) + OFLOG_INFO(Internals::Logger, " (but no valid presentation contexts)"); + } + + return new CommandDispatcher(server, assoc); + } + + bool CommandDispatcher::Step() + /* + * This function receives DIMSE commmands over the network connection + * and handles these commands correspondingly. Note that in case of + * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed. + */ + { + bool finished = false; + + // receive a DIMSE command over the network, with a timeout of 1 second + DcmDataset *statusDetail = NULL; + T_ASC_PresentationContextID presID = 0; + T_DIMSE_Message msg; + + OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail); + elapsedTimeSinceLastCommand_++; + + // if the command which was received has extra status + // detail information, dump this information + if (statusDetail != NULL) + { + OFLOG_WARN(Internals::Logger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + if (cond == DIMSE_OUTOFRESOURCES) + { + finished = true; + } + else if (cond == DIMSE_NODATAAVAILABLE) + { + // Timeout due to DIMSE_NONBLOCKING + if (clientTimeout_ != 0 && + elapsedTimeSinceLastCommand_ >= clientTimeout_) + { + // This timeout is actually a client timeout + finished = true; + } + } + else if (cond == EC_Normal) + { + // Reset the client timeout counter + elapsedTimeSinceLastCommand_ = 0; + + // in case we received a valid message, process this command + // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ + switch (msg.CommandField) + { + case DIMSE_C_ECHO_RQ: + // process C-ECHO-Request + cond = EchoScp(assoc_, &msg, presID); + break; + + case DIMSE_C_STORE_RQ: + // process C-STORE-Request + if (server_.HasStoreRequestHandlerFactory()) + { + std::auto_ptr<IStoreRequestHandler> handler + (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler()); + cond = Internals::storeScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + case DIMSE_C_MOVE_RQ: + // process C-MOVE-Request + if (server_.HasMoveRequestHandlerFactory()) + { + std::auto_ptr<IMoveRequestHandler> handler + (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler()); + cond = Internals::moveScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + case DIMSE_C_FIND_RQ: + // process C-FIND-Request + if (server_.HasFindRequestHandlerFactory()) + { + std::auto_ptr<IFindRequestHandler> handler + (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); + cond = Internals::findScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + default: + // we cannot handle this kind of message + cond = DIMSE_BADCOMMANDTYPE; + OFLOG_ERROR(Internals::Logger, "cannot handle command: 0x" + << STD_NAMESPACE hex << OFstatic_cast(unsigned, msg.CommandField)); + break; + } + } + else + { + // Bad status, which indicates the closing of the connection by + // the peer or a network error + finished = true; + } + + if (finished) + { + if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_INFO(Internals::Logger, "Association Release"); + ASC_acknowledgeRelease(assoc_); + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(Internals::Logger, "Association Aborted"); + } + else + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond)); + /* some kind of error so abort the association */ + ASC_abortAssociation(assoc_); + } + } + + return !finished; + } + + + OFCondition EchoScp( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID) + { + OFString temp_str; + OFLOG_INFO(Internals::Logger, "Received Echo Request"); + OFLOG_DEBUG(Internals::Logger, DIMSE_dumpMessage(temp_str, msg->msg.CEchoRQ, DIMSE_INCOMING, NULL, presID)); + + /* the echo succeeded !! */ + OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, &msg->msg.CEchoRQ, STATUS_Success, NULL); + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, "Echo SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + return cond; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/CommandDispatcher.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,68 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/DicomServer.h" +#include "../../Core/MultiThreading/IRunnableBySteps.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palanthir +{ + namespace Internals + { + OFCondition AssociationCleanup(T_ASC_Association *assoc); + + class CommandDispatcher : public IRunnableBySteps + { + private: + uint32_t clientTimeout_; + uint32_t elapsedTimeSinceLastCommand_; + const DicomServer& server_; + T_ASC_Association* assoc_; + + public: + CommandDispatcher(const DicomServer& server, + T_ASC_Association* assoc) : + server_(server), + assoc_(assoc) + { + clientTimeout_ = server.GetClientTimeout(); + elapsedTimeSinceLastCommand_ = 0; + } + + virtual ~CommandDispatcher() + { + AssociationCleanup(assoc_); + } + + virtual bool Step(); + }; + + OFCondition EchoScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID); + + CommandDispatcher* AcceptAssociation(const DicomServer& server, + T_ASC_Network *net); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/FindScp.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,133 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "FindScp.h" + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalanthirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palanthir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct FindScpData + { + IFindRequestHandler* handler_; + DicomMap input_; + DicomFindAnswers answers_; + DcmDataset* lastRequest_; + }; + + + void FindScpCallback( + /* in */ + void *callbackData, + OFBool cancelled, + T_DIMSE_C_FindRQ *request, + DcmDataset *requestIdentifiers, + int responseCount, + /* out */ + T_DIMSE_C_FindRSP *response, + DcmDataset **responseIdentifiers, + DcmDataset **statusDetail) + { + bzero(response, sizeof(T_DIMSE_C_FindRSP)); + *statusDetail = NULL; + + FindScpData& data = *(FindScpData*) callbackData; + if (data.lastRequest_ == NULL) + { + FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + + try + { + data.handler_->Handle(data.input_, data.answers_); + } + catch (PalanthirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IFindRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; + *responseIdentifiers = NULL; + return; + } + + data.lastRequest_ = requestIdentifiers; + } + else if (data.lastRequest_ != requestIdentifiers) + { + // Internal error! + response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; + *responseIdentifiers = NULL; + return; + } + + if (responseCount <= static_cast<int>(data.answers_.GetSize())) + { + response->DimseStatus = STATUS_Pending; + *responseIdentifiers = ToDcmtkBridge::Convert(data.answers_.GetAnswer(responseCount - 1)); + } + else + { + response->DimseStatus = STATUS_Success; + *responseIdentifiers = NULL; + } + } + } + + + OFCondition Internals::findScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IFindRequestHandler& handler) + { + FindScpData data; + data.lastRequest_ = NULL; + data.handler_ = &handler; + + OFCondition cond = DIMSE_findProvider(assoc, presID, &msg->msg.CFindRQ, + FindScpCallback, &data, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "Find SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/FindScp.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IFindRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palanthir +{ + namespace Internals + { + OFCondition findScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IFindRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/MoveScp.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,175 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "MoveScp.h" + +#include <memory> + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalanthirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palanthir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct MoveScpData + { + std::string target_; + IMoveRequestHandler* handler_; + DicomMap input_; + DcmDataset* lastRequest_; + unsigned int subOperationCount_; + unsigned int failureCount_; + unsigned int warningCount_; + std::auto_ptr<IMoveRequestIterator> iterator_; + }; + + + void MoveScpCallback( + /* in */ + void *callbackData, + OFBool cancelled, + T_DIMSE_C_MoveRQ *request, + DcmDataset *requestIdentifiers, + int responseCount, + /* out */ + T_DIMSE_C_MoveRSP *response, + DcmDataset **responseIdentifiers, + DcmDataset **statusDetail) + { + bzero(response, sizeof(T_DIMSE_C_MoveRSP)); + *statusDetail = NULL; + *responseIdentifiers = NULL; + + MoveScpData& data = *(MoveScpData*) callbackData; + if (data.lastRequest_ == NULL) + { + FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + + try + { + data.iterator_.reset(data.handler_->Handle(data.target_, data.input_)); + data.subOperationCount_ = data.iterator_->GetSubOperationCount(); + data.failureCount_ = 0; + data.warningCount_ = 0; + } + catch (PalanthirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + data.lastRequest_ = requestIdentifiers; + } + else if (data.lastRequest_ != requestIdentifiers) + { + // Internal error! + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + if (data.subOperationCount_ == 0) + { + response->DimseStatus = STATUS_Success; + } + else + { + IMoveRequestIterator::Status status; + + try + { + status = data.iterator_->DoNext(); + } + catch (PalanthirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + if (status == IMoveRequestIterator::Status_Failure) + { + data.failureCount_++; + } + else if (status == IMoveRequestIterator::Status_Warning) + { + data.warningCount_++; + } + + if (responseCount < static_cast<int>(data.subOperationCount_)) + { + response->DimseStatus = STATUS_Pending; + } + else + { + response->DimseStatus = STATUS_Success; + } + } + + response->NumberOfRemainingSubOperations = data.subOperationCount_ - responseCount; + response->NumberOfCompletedSubOperations = responseCount; + response->NumberOfFailedSubOperations = data.failureCount_; + response->NumberOfWarningSubOperations = data.warningCount_; + } + } + + + OFCondition Internals::moveScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IMoveRequestHandler& handler) + { + MoveScpData data; + data.target_ = std::string(msg->msg.CMoveRQ.MoveDestination); + data.lastRequest_ = NULL; + data.handler_ = &handler; + + OFCondition cond = DIMSE_moveProvider(assoc, presID, &msg->msg.CMoveRQ, + MoveScpCallback, &data, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "Move SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/MoveScp.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IMoveRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palanthir +{ + namespace Internals + { + OFCondition moveScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IMoveRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/StoreScp.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,266 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "StoreScp.h" + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalanthirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palanthir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct StoreCallbackData + { + IStoreRequestHandler* handler; + const char* distantAET; + const char* modality; + const char* affectedSOPInstanceUID; + uint32_t messageID; + }; + + + static int SaveToMemoryBuffer(DcmDataset* dataSet, + std::vector<uint8_t>& buffer) + { + // Determine the transfer syntax which shall be used to write the + // information to the file. We always switch to the Little Endian + // syntax, with explicit length. + + // http://support.dcmtk.org/docs/dcxfer_8h-source.html + E_TransferSyntax xfer = EXS_LittleEndianExplicit; + E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; + + uint32_t s = dataSet->getLength(xfer, encodingType); + + buffer.resize(s); + DcmOutputBufferStream ob(&buffer[0], s); + + dataSet->transferInit(); + OFCondition c = dataSet->write(ob, xfer, encodingType, NULL, + /*opt_groupLength*/ EGL_recalcGL, + /*opt_paddingType*/ EPD_withoutPadding); + dataSet->transferEnd(); + if (c.good()) + { + return 0; + } + else + { + buffer.clear(); + return -1; + } + +#if 0 + OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, + encodingType, + /*opt_groupLength*/ EGL_recalcGL, + /*opt_paddingType*/ EPD_withoutPadding, + OFstatic_cast(Uint32, /*opt_filepad*/ 0), + OFstatic_cast(Uint32, /*opt_itempad*/ 0), + (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); +#endif + } + + + static void + storeScpCallback( + void *callbackData, + T_DIMSE_StoreProgress *progress, + T_DIMSE_C_StoreRQ *req, + char * /*imageFileName*/, DcmDataset **imageDataSet, + T_DIMSE_C_StoreRSP *rsp, + DcmDataset **statusDetail) + /* + * This function.is used to indicate progress when storescp receives instance data over the + * network. On the final call to this function (identified by progress->state == DIMSE_StoreEnd) + * this function will store the data set which was received over the network to a file. + * Earlier calls to this function will simply cause some information to be dumped to stdout. + * + * Parameters: + * callbackData - [in] data for this callback function + * progress - [in] The state of progress. (identifies if this is the initial or final call + * to this function, or a call in between these two calls. + * req - [in] The original store request message. + * imageFileName - [in] The path to and name of the file the information shall be written to. + * imageDataSet - [in] The data set which shall be stored in the image file + * rsp - [inout] the C-STORE-RSP message (will be sent after the call to this function) + * statusDetail - [inout] This variable can be used to capture detailed information with regard to + * the status information which is captured in the status element (0000,0900). Note + * that this function does specify any such information, the pointer will be set to NULL. + */ + { + StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData); + + DIC_UI sopClass; + DIC_UI sopInstance; + + // if this is the final call of this function, save the data which was received to a file + // (note that we could also save the image somewhere else, put it in database, etc.) + if (progress->state == DIMSE_StoreEnd) + { + OFString tmpStr; + + // do not send status detail information + *statusDetail = NULL; + + // Concerning the following line: an appropriate status code is already set in the resp structure, + // it need not be success. For example, if the caller has already detected an out of resources problem + // then the status will reflect this. The callback function is still called to allow cleanup. + //rsp->DimseStatus = STATUS_Success; + + // we want to write the received information to a file only if this information + // is present and the options opt_bitPreserving and opt_ignore are not set. + if ((imageDataSet != NULL) && (*imageDataSet != NULL)) + { + DicomMap summary; + Json::Value dicomJson; + std::vector<uint8_t> buffer; + + try + { + FromDcmtkBridge::Convert(summary, **imageDataSet); + FromDcmtkBridge::ToJson(dicomJson, **imageDataSet); + + if (SaveToMemoryBuffer(*imageDataSet, buffer) < 0) + { + OFLOG_ERROR(Internals::Logger, "cannot write DICOM file to memory"); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + } + catch (...) + { + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + + // check the image to make sure it is consistent, i.e. that its sopClass and sopInstance correspond + // to those mentioned in the request. If not, set the status in the response message variable. + if ((rsp->DimseStatus == STATUS_Success)) + { + // which SOP class and SOP instance ? + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, /*opt_correctUIDPadding*/ OFFalse)) + { + //OFLOG_ERROR(Internals::Logger, "bad DICOM file: " << fileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + } + else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else + { + try + { + cbdata->handler->Handle(buffer, summary, dicomJson, cbdata->distantAET); + } + catch (PalanthirException& e) + { + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + OFLOG_ERROR(Internals::Logger, "Exception while storing DICOM: " << e.What()); + } + } + } + } + } + } + } + +/* + * This function processes a DIMSE C-STORE-RQ commmand that was + * received over the network connection. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * msg - [in] The DIMSE C-STORE-RQ message that was received. + * presID - [in] The ID of the presentation context which was specified in the PDV which contained + * the DIMSE command. + */ + OFCondition Internals::storeScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IStoreRequestHandler& handler) + { + OFCondition cond = EC_Normal; + T_DIMSE_C_StoreRQ *req; + + // assign the actual information of the C-STORE-RQ command to a local variable + req = &msg->msg.CStoreRQ; + + // intialize some variables + StoreCallbackData callbackData; + callbackData.handler = &handler; + callbackData.modality = dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"); + callbackData.affectedSOPInstanceUID = req->AffectedSOPInstanceUID; + callbackData.messageID = req->MessageID; + if (assoc && assoc->params) + { + callbackData.distantAET = assoc->params->DULparams.callingAPTitle; + } + else + { + callbackData.distantAET = ""; + } + + DcmFileFormat dcmff; + + // store SourceApplicationEntityTitle in metaheader + if (assoc && assoc->params) + { + const char *aet = assoc->params->DULparams.callingAPTitle; + if (aet) dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet); + } + + // define an address where the information which will be received over the network will be stored + DcmDataset *dset = dcmff.getDataset(); + + cond = DIMSE_storeProvider(assoc, presID, req, NULL, /*opt_useMetaheader*/OFFalse, &dset, + storeScpCallback, &callbackData, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Logger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + // return return value + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Internals/StoreScp.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IStoreRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palanthir +{ + namespace Internals + { + OFCondition storeScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IStoreRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/PalanthirInitialization.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,236 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PalanthirInitialization.h" + +#include "../Core/PalanthirException.h" +#include "../Core/Toolbox.h" + +#include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> +#include <curl/curl.h> +#include <boost/thread.hpp> + +namespace Palanthir +{ + static const char* CONFIGURATION_FILE = "Configuration.json"; + + static boost::mutex globalMutex_; + static std::auto_ptr<Json::Value> configuration_; + + + static void ReadGlobalConfiguration(const char* configurationFile) + { + configuration_.reset(new Json::Value); + + std::string content; + + if (configurationFile) + { + Toolbox::ReadFile(content, configurationFile); + } + else + { + try + { +#if PALANTHIR_STANDALONE == 0 + boost::filesystem::path p = PALANTHIR_PATH; + p /= "Resources"; + p /= CONFIGURATION_FILE; + Toolbox::ReadFile(content, p.string()); +#else + Toolbox::ReadFile(content, CONFIGURATION_FILE); +#endif + } + catch (PalanthirException&) + { + // No configuration file found, give up with empty configuration + return; + } + } + + Json::Reader reader; + if (!reader.parse(content, *configuration_)) + { + throw PalanthirException("Unable to read the configuration file"); + } + } + + + void PalanthirInitialize(const char* configurationFile) + { + boost::mutex::scoped_lock lock(globalMutex_); + ReadGlobalConfiguration(configurationFile); + curl_global_init(CURL_GLOBAL_ALL); + } + + + + void PalanthirFinalize() + { + boost::mutex::scoped_lock lock(globalMutex_); + curl_global_cleanup(); + configuration_.reset(NULL); + } + + + + std::string GetGlobalStringParameter(const std::string& parameter, + const std::string& defaultValue) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (configuration_->isMember(parameter)) + { + return (*configuration_) [parameter].asString(); + } + else + { + return defaultValue; + } + } + + + int GetGlobalIntegerParameter(const std::string& parameter, + int defaultValue) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (configuration_->isMember(parameter)) + { + return (*configuration_) [parameter].asInt(); + } + else + { + return defaultValue; + } + } + + bool GetGlobalBoolParameter(const std::string& parameter, + bool defaultValue) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (configuration_->isMember(parameter)) + { + return (*configuration_) [parameter].asBool(); + } + else + { + return defaultValue; + } + } + + + + + void GetDicomModality(const std::string& name, + std::string& aet, + std::string& address, + int& port) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (!configuration_->isMember("DicomModalities")) + { + throw PalanthirException(""); + } + + const Json::Value& modalities = (*configuration_) ["DicomModalities"]; + if (modalities.type() != Json::objectValue || + !modalities.isMember(name)) + { + throw PalanthirException(""); + } + + try + { + aet = modalities[name].get(0u, "").asString(); + address = modalities[name].get(1u, "").asString(); + port = modalities[name].get(2u, "").asInt(); + } + catch (...) + { + throw PalanthirException("Badly formatted DICOM modality"); + } + } + + + + void GetListOfDicomModalities(std::set<std::string>& target) + { + boost::mutex::scoped_lock lock(globalMutex_); + + target.clear(); + + if (!configuration_->isMember("DicomModalities")) + { + return; + } + + const Json::Value& modalities = (*configuration_) ["DicomModalities"]; + if (modalities.type() != Json::objectValue) + { + throw PalanthirException("Badly formatted list of DICOM modalities"); + } + + Json::Value::Members members = modalities.getMemberNames(); + for (size_t i = 0; i < members.size(); i++) + { + for (size_t j = 0; j < members[i].size(); j++) + { + if (!isalnum(members[i][j]) && members[i][j] != '-') + { + throw PalanthirException("Only alphanumeric and dash characters are allowed in the names of the modalities"); + } + } + + target.insert(members[i]); + } + } + + + + void SetupRegisteredUsers(MongooseServer& httpServer) + { + boost::mutex::scoped_lock lock(globalMutex_); + + httpServer.ClearUsers(); + + if (!configuration_->isMember("RegisteredUsers")) + { + return; + } + + const Json::Value& users = (*configuration_) ["RegisteredUsers"]; + if (users.type() != Json::objectValue) + { + throw PalanthirException("Badly formatted list of users"); + } + + Json::Value::Members usernames = users.getMemberNames(); + for (size_t i = 0; i < usernames.size(); i++) + { + const std::string& username = usernames[i]; + std::string password = users[username].asString(); + httpServer.RegisterUser(username.c_str(), password.c_str()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/PalanthirInitialization.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,51 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <set> +#include <json/json.h> +#include "../Core/HttpServer/MongooseServer.h" + +namespace Palanthir +{ + void PalanthirInitialize(const char* configurationFile = NULL); + + void PalanthirFinalize(); + + std::string GetGlobalStringParameter(const std::string& parameter, + const std::string& defaultValue); + + int GetGlobalIntegerParameter(const std::string& parameter, + int defaultValue); + + bool GetGlobalBoolParameter(const std::string& parameter, + bool defaultValue); + + void GetDicomModality(const std::string& name, + std::string& aet, + std::string& address, + int& port); + + void GetListOfDicomModalities(std::set<std::string>& target); + + void SetupRegisteredUsers(MongooseServer& httpServer); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/PalanthirRestApi.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,802 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PalanthirRestApi.h" + +#include "PalanthirInitialization.h" +#include "FromDcmtkBridge.h" +#include "../Core/Uuid.h" + +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <boost/lexical_cast.hpp> + +namespace Palanthir +{ + static void SendJson(HttpOutput& output, + const Json::Value& value) + { + Json::StyledWriter writer; + std::string s = writer.write(value); + output.AnswerBufferWithContentType(s, "application/json"); + } + + + static void SimplifyTagsRecursion(Json::Value& target, + const Json::Value& source) + { + assert(source.isObject()); + + target = Json::objectValue; + Json::Value::Members members = source.getMemberNames(); + + for (size_t i = 0; i < members.size(); i++) + { + const Json::Value& v = source[members[i]]; + const std::string& name = v["Name"].asString(); + const std::string& type = v["Type"].asString(); + + if (type == "String") + { + target[name] = v["Value"].asString(); + } + else if (type == "TooLong" || + type == "Null") + { + target[name] = Json::nullValue; + } + else if (type == "Sequence") + { + const Json::Value& array = v["Value"]; + assert(array.isArray()); + + Json::Value children = Json::arrayValue; + for (size_t i = 0; i < array.size(); i++) + { + Json::Value c; + SimplifyTagsRecursion(c, array[i]); + children.append(c); + } + + target[name] = children; + } + else + { + assert(0); + } + } + } + + + static void SimplifyTags(Json::Value& target, + const FileStorage& storage, + const std::string& fileUuid) + { + std::string s; + storage.ReadFile(s, fileUuid); + + Json::Value source; + Json::Reader reader; + if (!reader.parse(s, source)) + { + throw PalanthirException("Corrupted JSON file"); + } + + SimplifyTagsRecursion(target, source); + } + + + bool PalanthirRestApi::Store(Json::Value& result, + const std::string& postData) + { + // Prepare an input stream for the memory buffer + DcmInputBufferStream is; + if (postData.size() > 0) + { + is.setBuffer(&postData[0], postData.size()); + } + is.setEos(); + + //printf("[%d]\n", postData.size()); + + DcmFileFormat dicomFile; + if (dicomFile.read(is).good()) + { + DicomMap dicomSummary; + FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); + + Json::Value dicomJson; + FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); + + std::string instanceUuid; + StoreStatus status = StoreStatus_Failure; + if (postData.size() > 0) + { + status = index_.Store + (instanceUuid, storage_, reinterpret_cast<const char*>(&postData[0]), + postData.size(), dicomSummary, dicomJson, ""); + } + + switch (status) + { + case StoreStatus_Success: + result["ID"] = instanceUuid; + result["Path"] = "/instances/" + instanceUuid; + result["Status"] = "Success"; + return true; + + case StoreStatus_AlreadyStored: + result["ID"] = instanceUuid; + result["Path"] = "/instances/" + instanceUuid; + result["Status"] = "AlreadyStored"; + return true; + + default: + return false; + } + } + + return false; + } + + void PalanthirRestApi::ConnectToModality(DicomUserConnection& c, + const std::string& name) + { + std::string aet, address; + int port; + GetDicomModality(name, aet, address, port); + c.SetLocalApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTHIR")); + c.SetDistantApplicationEntityTitle(aet); + c.SetDistantHost(address); + c.SetDistantPort(port); + c.Open(); + } + + bool PalanthirRestApi::MergeQueryAndTemplate(DicomMap& result, + const std::string& postData) + { + Json::Value query; + Json::Reader reader; + + if (!reader.parse(postData, query) || + query.type() != Json::objectValue) + { + return false; + } + + Json::Value::Members members = query.getMemberNames(); + for (size_t i = 0; i < members.size(); i++) + { + DicomTag t = FromDcmtkBridge::FindTag(members[i]); + result.SetValue(t, query[members[i]].asString()); + } + + return true; + } + + bool PalanthirRestApi::DicomFindPatient(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindPatientTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + DicomFindAnswers answers; + c.FindPatient(answers, m); + answers.ToJson(result); + return true; + } + + bool PalanthirRestApi::DicomFindStudy(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindStudyTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + if (m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && + m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) + { + return false; + } + + DicomFindAnswers answers; + c.FindStudy(answers, m); + answers.ToJson(result); + return true; + } + + bool PalanthirRestApi::DicomFindSeries(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindSeriesTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + if ((m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && + m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) || + m.GetValue(DicomTag::STUDY_UID).AsString().size() <= 2) + { + return false; + } + + DicomFindAnswers answers; + c.FindSeries(answers, m); + answers.ToJson(result); + return true; + } + + bool PalanthirRestApi::DicomFind(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindPatientTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + DicomFindAnswers patients; + c.FindPatient(patients, m); + + // Loop over the found patients + result = Json::arrayValue; + for (size_t i = 0; i < patients.GetSize(); i++) + { + Json::Value patient(Json::objectValue); + FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i)); + + DicomMap::SetupFindStudyTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + m.CopyTagIfExists(patients.GetAnswer(i), DicomTag::PATIENT_ID); + + DicomFindAnswers studies; + c.FindStudy(studies, m); + + patient["Studies"] = Json::arrayValue; + + // Loop over the found studies + for (size_t j = 0; j < studies.GetSize(); j++) + { + Json::Value study(Json::objectValue); + FromDcmtkBridge::ToJson(study, studies.GetAnswer(j)); + + DicomMap::SetupFindSeriesTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::PATIENT_ID); + m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::STUDY_UID); + + DicomFindAnswers series; + c.FindSeries(series, m); + + // Loop over the found series + study["Series"] = Json::arrayValue; + for (size_t k = 0; k < series.GetSize(); k++) + { + Json::Value series2(Json::objectValue); + FromDcmtkBridge::ToJson(series2, series.GetAnswer(k)); + study["Series"].append(series2); + } + + patient["Studies"].append(study); + } + + result.append(patient); + } + + return true; + } + + + + bool PalanthirRestApi::DicomStore(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + Json::Value found(Json::objectValue); + + if (!Toolbox::IsUuid(postData)) + { + // This is not a UUID, assume this is a DICOM instance + c.Store(postData); + } + else if (index_.GetSeries(found, postData)) + { + // The UUID corresponds to a series + for (size_t i = 0; i < found["Instances"].size(); i++) + { + std::string uuid = found["Instances"][i].asString(); + Json::Value instance(Json::objectValue); + if (index_.GetInstance(instance, uuid)) + { + std::string content; + storage_.ReadFile(content, instance["FileUuid"].asString()); + c.Store(content); + } + else + { + return false; + } + } + } + else if (index_.GetInstance(found, postData)) + { + // The UUID corresponds to an instance + std::string content; + storage_.ReadFile(content, found["FileUuid"].asString()); + c.Store(content); + } + else + { + return false; + } + + return true; + } + + + PalanthirRestApi::PalanthirRestApi(ServerIndex& index, + const std::string& path) : + index_(index), + storage_(path) + { + GetListOfDicomModalities(modalities_); + } + + + void PalanthirRestApi::Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string& postData) + { + if (uri.size() == 0) + { + if (method == "GET") + { + output.Redirect("/app/explorer.html"); + } + else + { + output.SendMethodNotAllowedError("GET"); + } + + return; + } + + bool existingResource = false; + Json::Value result(Json::objectValue); + + + // List all the instances --------------------------------------------------- + + if (uri.size() == 1 && uri[0] == "instances") + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + index_.GetAllUuids(result, "Instances"); + existingResource = true; + } + else if (method == "POST") + { + // Add a new instance to the storage + if (Store(result, postData)) + { + SendJson(output, result); + return; + } + else + { + output.SendHeader(Palanthir_HttpStatus_415_UnsupportedMediaType); + return; + } + } + else + { + output.SendMethodNotAllowedError("GET,POST"); + return; + } + } + + + // List all the patients, studies or series --------------------------------- + + if (uri.size() == 1 && + (uri[0] == "series" || + uri[0] == "studies" || + uri[0] == "patients")) + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + + if (uri[0] == "instances") + index_.GetAllUuids(result, "Instances"); + else if (uri[0] == "series") + index_.GetAllUuids(result, "Series"); + else if (uri[0] == "studies") + index_.GetAllUuids(result, "Studies"); + else if (uri[0] == "patients") + index_.GetAllUuids(result, "Patients"); + + existingResource = true; + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + + // Information about a single object ---------------------------------------- + + else if (uri.size() == 2 && + (uri[0] == "instances" || + uri[0] == "series" || + uri[0] == "studies" || + uri[0] == "patients")) + { + if (method == "GET") + { + if (uri[0] == "patients") + { + existingResource = index_.GetPatient(result, uri[1]); + } + else if (uri[0] == "studies") + { + existingResource = index_.GetStudy(result, uri[1]); + } + else if (uri[0] == "series") + { + existingResource = index_.GetSeries(result, uri[1]); + } + else if (uri[0] == "instances") + { + existingResource = index_.GetInstance(result, uri[1]); + } + } + else if (method == "DELETE") + { + if (uri[0] == "patients") + { + existingResource = index_.DeletePatient(result, uri[1]); + } + else if (uri[0] == "studies") + { + existingResource = index_.DeleteStudy(result, uri[1]); + } + else if (uri[0] == "series") + { + existingResource = index_.DeleteSeries(result, uri[1]); + } + else if (uri[0] == "instances") + { + existingResource = index_.DeleteInstance(result, uri[1]); + } + + if (existingResource) + { + result["Status"] = "Success"; + } + } + else + { + output.SendMethodNotAllowedError("GET,DELETE"); + return; + } + } + + + // Get the DICOM or the JSON file of one instance --------------------------- + + else if (uri.size() == 3 && + uri[0] == "instances" && + (uri[2] == "file" || + uri[2] == "tags" || + uri[2] == "simplified-tags")) + { + std::string fileUuid, contentType; + if (uri[2] == "file") + { + existingResource = index_.GetDicomFile(fileUuid, uri[1]); + contentType = "application/dicom"; + } + else if (uri[2] == "tags" || + uri[2] == "simplified-tags") + { + existingResource = index_.GetJsonFile(fileUuid, uri[1]); + contentType = "application/json"; + } + + if (existingResource) + { + if (uri[2] == "simplified-tags") + { + Json::Value v; + SimplifyTags(v, storage_, fileUuid); + SendJson(output, v); + return; + } + else + { + output.AnswerFile(storage_, fileUuid, contentType); + return; + } + } + } + + + else if (uri.size() == 3 && + uri[0] == "instances" && + uri[2] == "frames") + { + Json::Value instance(Json::objectValue); + existingResource = index_.GetInstance(instance, uri[1]); + + if (existingResource) + { + result = Json::arrayValue; + + unsigned int numberOfFrames = 1; + try + { + Json::Value tmp = instance["MainDicomTags"]["NumberOfFrames"]; + numberOfFrames = boost::lexical_cast<unsigned int>(tmp.asString()); + } + catch (boost::bad_lexical_cast) + { + } + + for (unsigned int i = 0; i < numberOfFrames; i++) + { + result.append(i); + } + } + } + + + else if (uri[0] == "instances" && + ((uri.size() == 3 && + (uri[2] == "preview" || + uri[2] == "image-uint8" || + uri[2] == "image-uint16")) || + (uri.size() == 5 && + uri[2] == "frames" && + (uri[4] == "preview" || + uri[4] == "image-uint8" || + uri[4] == "image-uint16")))) + { + std::string uuid; + existingResource = index_.GetDicomFile(uuid, uri[1]); + + std::string action = uri[2]; + + unsigned int frame = 0; + if (existingResource && + uri.size() == 5) + { + // Access to multi-frame image + action = uri[4]; + try + { + frame = boost::lexical_cast<unsigned int>(uri[3]); + } + catch (boost::bad_lexical_cast) + { + existingResource = false; + } + } + + if (existingResource) + { + std::string dicomContent, png; + storage_.ReadFile(dicomContent, uuid); + try + { + if (action == "preview") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_Preview); + } + else if (action == "image-uint8") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt8); + } + else if (action == "image-uint16") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt16); + } + else + { + throw PalanthirException(ErrorCode_InternalError); + } + + output.AnswerBufferWithContentType(png, "image/png"); + return; + } + catch (PalanthirException&) + { + output.Redirect("/app/images/Unsupported.png"); + return; + } + } + } + + + + // Changes API -------------------------------------------------------------- + + if (uri.size() == 1 && uri[0] == "changes") + { + if (method == "GET") + { + const static unsigned int MAX_RESULTS = 100; + + std::string filter = GetArgument(arguments, "filter", ""); + int64_t since; + unsigned int limit; + try + { + since = boost::lexical_cast<int64_t>(GetArgument(arguments, "since", "0")); + limit = boost::lexical_cast<unsigned int>(GetArgument(arguments, "limit", "0")); + } + catch (boost::bad_lexical_cast) + { + output.SendHeader(Palanthir_HttpStatus_400_BadRequest); + return; + } + + if (limit == 0 || limit > MAX_RESULTS) + { + limit = MAX_RESULTS; + } + + if (!index_.GetChanges(result, since, filter, limit)) + { + output.SendHeader(Palanthir_HttpStatus_400_BadRequest); + return; + } + + existingResource = true; + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + + // DICOM bridge ------------------------------------------------------------- + + if (uri.size() == 1 && + uri[0] == "modalities") + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + existingResource = true; + + for (Modalities::const_iterator it = modalities_.begin(); + it != modalities_.end(); it++) + { + result.append(*it); + } + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + if ((uri.size() == 2 || + uri.size() == 3) && + uri[0] == "modalities") + { + if (modalities_.find(uri[1]) == modalities_.end()) + { + // Unknown modality + } + else if (uri.size() == 2) + { + if (method != "GET") + { + output.SendMethodNotAllowedError("POST"); + return; + } + else + { + existingResource = true; + result = Json::arrayValue; + result.append("find-patient"); + result.append("find-study"); + result.append("find-series"); + result.append("find"); + result.append("store"); + } + } + else if (uri.size() == 3) + { + if (uri[2] != "find-patient" && + uri[2] != "find-study" && + uri[2] != "find-series" && + uri[2] != "find" && + uri[2] != "store") + { + // Unknown request + } + else if (method != "POST") + { + output.SendMethodNotAllowedError("POST"); + return; + } + else + { + DicomUserConnection connection; + ConnectToModality(connection, uri[1]); + existingResource = true; + + if ((uri[2] == "find-patient" && !DicomFindPatient(result, connection, postData)) || + (uri[2] == "find-study" && !DicomFindStudy(result, connection, postData)) || + (uri[2] == "find-series" && !DicomFindSeries(result, connection, postData)) || + (uri[2] == "find" && !DicomFind(result, connection, postData)) || + (uri[2] == "store" && !DicomStore(result, connection, postData))) + { + output.SendHeader(Palanthir_HttpStatus_400_BadRequest); + return; + } + } + } + } + + + if (existingResource) + { + SendJson(output, result); + } + else + { + output.SendHeader(Palanthir_HttpStatus_404_NotFound); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/PalanthirRestApi.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,87 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/HttpServer/HttpHandler.h" +#include "ServerIndex.h" +#include "DicomProtocol/DicomUserConnection.h" + +#include <set> + + +namespace Palanthir +{ + class PalanthirRestApi : public HttpHandler + { + private: + typedef std::set<std::string> Modalities; + + ServerIndex& index_; + FileStorage storage_; + Modalities modalities_; + + bool Store(Json::Value& result, + const std::string& postData); + + void ConnectToModality(DicomUserConnection& c, + const std::string& name); + + bool MergeQueryAndTemplate(DicomMap& result, + const std::string& postData); + + bool DicomFindPatient(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFindStudy(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFindSeries(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFind(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomStore(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + public: + PalanthirRestApi(ServerIndex& index, + const std::string& path); + + virtual bool IsServedUri(const UriComponents& uri) + { + return true; + } + + virtual void Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string& postData); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/PrepareDatabase.sql Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,122 @@ +CREATE TABLE GlobalProperties( + name TEXT PRIMARY KEY, + value TEXT + ); + +CREATE TABLE Patients( + uuid TEXT PRIMARY KEY, + dicomPatientId TEXT + ); + +CREATE TABLE Studies( + uuid TEXT PRIMARY KEY, + parentPatient TEXT REFERENCES Patients(uuid) ON DELETE CASCADE, + dicomStudy TEXT + ); + +CREATE TABLE Series( + uuid TEXT PRIMARY KEY, + parentStudy TEXT REFERENCES Studies(uuid) ON DELETE CASCADE, + dicomSeries TEXT + ); + +CREATE TABLE Instances( + uuid TEXT PRIMARY KEY, + parentSeries TEXT REFERENCES Series(uuid) ON DELETE CASCADE, + dicomInstance TEXT, + fileUuid TEXT, + fileSize INTEGER, + jsonUuid TEXT, + distantAet TEXT + ); + +CREATE TABLE MainDicomTags( + uuid TEXT, + tagGroup INTEGER, + tagElement INTEGER, + value TEXT, + PRIMARY KEY(uuid, tagGroup, tagElement) + ); + +CREATE TABLE Changes( + seq INTEGER PRIMARY KEY AUTOINCREMENT, + basePath TEXT, + uuid TEXT + ); + + +CREATE INDEX PatientToStudies ON Studies(parentPatient); +CREATE INDEX StudyToSeries ON Series(parentStudy); +CREATE INDEX SeriesToInstances ON Instances(parentSeries); + +CREATE INDEX DicomPatientIndex ON Patients(dicomPatientId); +CREATE INDEX DicomStudyIndex ON Studies(dicomStudy); +CREATE INDEX DicomSeriesIndex ON Series(dicomSeries); +CREATE INDEX DicomInstanceIndex ON Instances(dicomInstance); + +CREATE INDEX MainDicomTagsIndex ON MainDicomTags(uuid); +CREATE INDEX ChangesIndex ON Changes(uuid); + +CREATE TRIGGER InstanceRemoved +AFTER DELETE ON Instances +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT DeleteFromFileStorage(old.fileUuid); + SELECT DeleteFromFileStorage(old.jsonUuid); + SELECT SignalDeletedLevel(3, old.parentSeries); +END; + +CREATE TRIGGER SeriesRemoved +AFTER DELETE ON Series +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(2, old.parentStudy); +END; + +CREATE TRIGGER StudyRemoved +AFTER DELETE ON Studies +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(1, old.parentPatient); +END; + +CREATE TRIGGER PatientRemoved +AFTER DELETE ON Patients +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(0, ""); +END; + + + + +CREATE TRIGGER InstanceRemovedUpwardCleaning +AFTER DELETE ON Instances +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Instances WHERE parentSeries = old.parentSeries) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent series"); -- TODO REMOVE THIS + DELETE FROM Series WHERE uuid = old.parentSeries; + END; + +CREATE TRIGGER SeriesRemovedUpwardCleaning +AFTER DELETE ON Series +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Series WHERE parentStudy = old.parentStudy) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent study"); -- TODO REMOVE THIS + DELETE FROM Studies WHERE uuid = old.parentStudy; + END; + +CREATE TRIGGER StudyRemovedUpwardCleaning +AFTER DELETE ON Studies +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Studies WHERE parentPatient = old.parentPatient) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent patient"); -- TODO REMOVE THIS + DELETE FROM Patients WHERE uuid = old.parentPatient; + END;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/ServerIndex.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,833 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "ServerIndex.h" + +using namespace Palanthir; + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include "EmbeddedResources.h" +#include "../Core/Toolbox.h" +#include "../Core/Uuid.h" +#include "../Core/DicomFormat/DicomArray.h" +#include "../Core/SQLite/Transaction.h" +#include "FromDcmtkBridge.h" + +#include <boost/lexical_cast.hpp> +#include <stdio.h> + +namespace Palanthir +{ + namespace Internals + { + class DeleteFromFileStorageFunction : public SQLite::IScalarFunction + { + private: + FileStorage fileStorage_; + + public: + DeleteFromFileStorageFunction(const std::string& path) : + fileStorage_(path) + { + } + + virtual const char* GetName() const + { + return "DeleteFromFileStorage"; + } + + virtual unsigned int GetCardinality() const + { + return 1; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + std::string fileUuid = context.GetStringValue(0); + printf("Removing file [%s]\n", fileUuid.c_str()); + if (Toolbox::IsUuid(fileUuid)) + { + fileStorage_.Remove(fileUuid); + } + } + }; + + + class SignalDeletedLevelFunction : public SQLite::IScalarFunction + { + private: + int remainingLevel_; + std::string remainingLevelUuid_; + + public: + void Clear() + { + remainingLevel_ = std::numeric_limits<int>::max(); + } + + bool HasRemainingLevel() const + { + return (remainingLevel_ != 0 && + remainingLevel_ != std::numeric_limits<int>::max()); + } + + const std::string& GetRemainingLevelUuid() const + { + assert(HasRemainingLevel()); + return remainingLevelUuid_; + } + + const char* GetRemainingLevelType() const + { + assert(HasRemainingLevel()); + switch (remainingLevel_) + { + case 1: + return "patient"; + case 2: + return "study"; + case 3: + return "series"; + default: + throw PalanthirException(ErrorCode_InternalError); + } + } + + virtual const char* GetName() const + { + return "SignalDeletedLevel"; + } + + virtual unsigned int GetCardinality() const + { + return 2; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + int level = context.GetIntValue(0); + if (level < remainingLevel_) + { + remainingLevel_ = level; + remainingLevelUuid_ = context.GetStringValue(1); + } + + //printf("deleted level [%d] [%s]\n", level, context.GetStringValue(1).c_str()); + } + }; + } + + + void ServerIndex::StoreMainDicomTags(const std::string& uuid, + const DicomMap& map) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); + + DicomArray flattened(map); + for (size_t i = 0; i < flattened.GetSize(); i++) + { + s.Reset(); + s.BindString(0, uuid); + s.BindInt(1, flattened.GetElement(i).GetTag().GetGroup()); + s.BindInt(2, flattened.GetElement(i).GetTag().GetElement()); + s.BindString(3, flattened.GetElement(i).GetValue().AsString()); + s.Run(); + } + } + + bool ServerIndex::GetMainDicomStringTag(std::string& result, + const std::string& uuid, + const DicomTag& tag) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT * FROM MainDicomTags WHERE uuid=? AND tagGroup=? AND tagElement=?"); + s.BindString(0, uuid); + s.BindInt(1, tag.GetGroup()); + s.BindInt(2, tag.GetElement()); + if (!s.Step()) + { + return false; + } + + result = s.ColumnString(0); + return true; + } + + bool ServerIndex::GetMainDicomIntTag(int& result, + const std::string& uuid, + const DicomTag& tag) + { + std::string s; + if (!GetMainDicomStringTag(s, uuid, tag)) + { + return false; + } + + try + { + result = boost::lexical_cast<int>(s); + return true; + } + catch (boost::bad_lexical_cast) + { + return false; + } + } + + bool ServerIndex::HasInstance(std::string& instanceUuid, + const std::string& dicomInstance) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); + s.BindString(0, dicomInstance); + if (s.Step()) + { + instanceUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + + void ServerIndex::RecordChange(const std::string& resourceType, + const std::string& uuid) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?)"); + s.BindString(0, resourceType); + s.BindString(1, uuid); + s.Run(); + } + + + std::string ServerIndex::CreateInstance(const std::string& parentSeriesUuid, + const std::string& dicomInstance, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t fileSize, + const std::string& jsonUuid, + const std::string& distantAet) + { + std::string instanceUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?)"); + s.BindString(0, instanceUuid); + s.BindString(1, parentSeriesUuid); + s.BindString(2, dicomInstance); + s.BindString(3, fileUuid); + s.BindInt64(4, fileSize); + s.BindString(5, jsonUuid); + s.BindString(6, distantAet); + s.Run(); + + RecordChange("instances", instanceUuid); + + DicomMap dicom; + dicomSummary.ExtractInstanceInformation(dicom); + StoreMainDicomTags(instanceUuid, dicom); + + return instanceUuid; + } + + void ServerIndex::RemoveInstance(const std::string& uuid) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Instances WHERE uuid=?"); + s.BindString(0, uuid); + s.Run(); + } + + bool ServerIndex::HasSeries(std::string& seriesUuid, + const std::string& dicomSeries) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE dicomSeries=?"); + s.BindString(0, dicomSeries); + if (s.Step()) + { + seriesUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreateSeries(const std::string& parentStudyUuid, + const std::string& dicomSeries, + const DicomMap& dicomSummary) + { + std::string seriesUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?)"); + s.BindString(0, seriesUuid); + s.BindString(1, parentStudyUuid); + s.BindString(2, dicomSeries); + s.Run(); + + RecordChange("series", seriesUuid); + + DicomMap dicom; + dicomSummary.ExtractSeriesInformation(dicom); + StoreMainDicomTags(seriesUuid, dicom); + + return seriesUuid; + } + + bool ServerIndex::HasStudy(std::string& studyUuid, + const std::string& dicomStudy) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE dicomStudy=?"); + s.BindString(0, dicomStudy); + if (s.Step()) + { + studyUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreateStudy(const std::string& parentPatientUuid, + const std::string& dicomStudy, + const DicomMap& dicomSummary) + { + std::string studyUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Studies VALUES(?, ?, ?)"); + s.BindString(0, studyUuid); + s.BindString(1, parentPatientUuid); + s.BindString(2, dicomStudy); + s.Run(); + + RecordChange("studies", studyUuid); + + DicomMap dicom; + dicomSummary.ExtractStudyInformation(dicom); + StoreMainDicomTags(studyUuid, dicom); + + return studyUuid; + } + + + + bool ServerIndex::HasPatient(std::string& patientUuid, + const std::string& dicomPatientId) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Patients WHERE dicomPatientId=?"); + s.BindString(0, dicomPatientId); + if (s.Step()) + { + patientUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreatePatient(const std::string& patientId, + const DicomMap& dicomSummary) + { + std::string patientUuid = Toolbox::GenerateUuid(); + std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); + s.BindString(0, patientUuid); + s.BindString(1, dicomPatientId); + s.Run(); + + RecordChange("patients", patientUuid); + + DicomMap dicom; + dicomSummary.ExtractPatientInformation(dicom); + StoreMainDicomTags(patientUuid, dicom); + + return patientUuid; + } + + + void ServerIndex::GetMainDicomTags(DicomMap& map, + const std::string& uuid) + { + map.Clear(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE uuid=?"); + s.BindString(0, uuid); + while (s.Step()) + { + map.SetValue(s.ColumnInt(1), + s.ColumnInt(2), + s.ColumnString(3)); + } + } + + void ServerIndex::MainDicomTagsToJson(Json::Value& target, + const std::string& uuid) + { + DicomMap map; + GetMainDicomTags(map, uuid); + target["MainDicomTags"] = Json::objectValue; + FromDcmtkBridge::ToJson(target["MainDicomTags"], map); + } + + + bool ServerIndex::DeleteInternal(Json::Value& target, + const std::string& uuid, + const std::string& tableName) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + deletedLevels_->Clear(); + + SQLite::Statement s(db_, "DELETE FROM " + tableName + " WHERE uuid=?"); + s.BindString(0, uuid); + + if (!s.Run()) + { + return false; + } + + if (db_.GetLastChangeCount() == 0) + { + // Nothing was deleted, inexistent UUID + return false; + } + + if (deletedLevels_->HasRemainingLevel()) + { + std::string type(deletedLevels_->GetRemainingLevelType()); + const std::string& uuid = deletedLevels_->GetRemainingLevelUuid(); + + target["RemainingAncestor"] = Json::Value(Json::objectValue); + target["RemainingAncestor"]["Path"] = "/" + type + "/" + uuid; + target["RemainingAncestor"]["Type"] = type; + target["RemainingAncestor"]["ID"] = uuid; + } + else + { + target["RemainingAncestor"] = Json::nullValue; + } + + return true; + } + + + ServerIndex::ServerIndex(const std::string& storagePath) + { + boost::filesystem::path p = storagePath; + + try + { + boost::filesystem::create_directories(storagePath); + } + catch (boost::filesystem::filesystem_error) + { + } + + p /= "index"; + db_.Open(p.string()); + db_.Register(new Internals::DeleteFromFileStorageFunction(storagePath)); + deletedLevels_ = (Internals::SignalDeletedLevelFunction*) + db_.Register(new Internals::SignalDeletedLevelFunction); + + if (!db_.DoesTableExist("GlobalProperties")) + { + printf("Creating the database\n"); + std::string query; + EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); + db_.Execute(query); + } + } + + + StoreStatus ServerIndex::Store(std::string& instanceUuid, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t uncompressedFileSize, + const std::string& jsonUuid, + const std::string& distantAet) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); + std::string dicomInstance = dicomSummary.GetValue(DicomTag::INSTANCE_UID).AsString(); + std::string dicomSeries = dicomSummary.GetValue(DicomTag::SERIES_UID).AsString(); + std::string dicomStudy = dicomSummary.GetValue(DicomTag::STUDY_UID).AsString(); + + try + { + SQLite::Transaction t(db_); + t.Begin(); + + if (HasInstance(instanceUuid, dicomInstance)) + { + return StoreStatus_AlreadyStored; + // TODO: Check consistency? + } + + std::string patientUuid; + if (HasPatient(patientUuid, dicomPatientId)) + { + // TODO: Check consistency? + } + else + { + patientUuid = CreatePatient(dicomPatientId, dicomSummary); + } + + std::string studyUuid; + if (HasStudy(studyUuid, dicomStudy)) + { + // TODO: Check consistency? + } + else + { + studyUuid = CreateStudy(patientUuid, dicomStudy, dicomSummary); + } + + std::string seriesUuid; + if (HasSeries(seriesUuid, dicomSeries)) + { + // TODO: Check consistency? + } + else + { + seriesUuid = CreateSeries(studyUuid, dicomSeries, dicomSummary); + } + + instanceUuid = CreateInstance(seriesUuid, dicomInstance, dicomSummary, fileUuid, + uncompressedFileSize, jsonUuid, distantAet); + + t.Commit(); + return StoreStatus_Success; + //t.Rollback(); + } + catch (PalanthirException& e) + { + std::cout << "EXCEPT2 [" << e.What() << "]" << " " << db_.GetErrorMessage() << std::endl; + } + + return StoreStatus_Failure; + } + + + StoreStatus ServerIndex::Store(std::string& instanceUuid, + FileStorage& storage, + const char* dicomFile, + size_t dicomSize, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet) + { + std::string fileUuid = storage.Create(dicomFile, dicomSize); + std::string jsonUuid = storage.Create(dicomJson.toStyledString()); + StoreStatus status = Store(instanceUuid, dicomSummary, fileUuid, + dicomSize, jsonUuid, distantAet); + + if (status != StoreStatus_Success) + { + storage.Remove(fileUuid); + storage.Remove(jsonUuid); + } + + switch (status) + { + case StoreStatus_Success: + std::cout << "New instance stored: " << GetTotalSize() << std::endl; + break; + + case StoreStatus_AlreadyStored: + std::cout << "Already stored" << std::endl; + break; + + case StoreStatus_Failure: + std::cout << "Store failure" << std::endl; + break; + } + + return status; + } + + uint64_t ServerIndex::GetTotalSize() + { + boost::mutex::scoped_lock scoped_lock(mutex_); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(fileSize) FROM Instances"); + s.Run(); + return s.ColumnInt64(0); + } + + + SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) + { + int numberOfSlices; + if (!GetMainDicomIntTag(numberOfSlices, seriesUuid, DicomTag::NUMBER_OF_SLICES) || + numberOfSlices < 0) + { + return SeriesStatus_Unknown; + } + + // Loop over the instances of the series + //std::set< + + // TODO + return SeriesStatus_Unknown; + } + + + + + + bool ServerIndex::GetInstance(Json::Value& result, + const std::string& instanceUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (!s.Step()) + { + return false; + } + else + { + result["ID"] = instanceUuid; + result["ParentSeries"] = s.ColumnString(0); + result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? + result["FileUuid"] = s.ColumnString(3); + MainDicomTagsToJson(result, instanceUuid); + return true; + } + } + + + bool ServerIndex::GetSeries(Json::Value& result, + const std::string& seriesUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries FROM Series WHERE uuid=?"); + s1.BindString(0, seriesUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = seriesUuid; + result["ParentStudy"] = s1.ColumnString(0); + MainDicomTagsToJson(result, seriesUuid); + + Json::Value instances(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE parentSeries=?"); + s2.BindString(0, seriesUuid); + while (s2.Step()) + { + instances.append(s2.ColumnString(0)); + } + + result["Instances"] = instances; + + return true; + } + + + bool ServerIndex::GetStudy(Json::Value& result, + const std::string& studyUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentPatient, dicomStudy FROM Studies WHERE uuid=?"); + s1.BindString(0, studyUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = studyUuid; + result["ParentPatient"] = s1.ColumnString(0); + MainDicomTagsToJson(result, studyUuid); + + Json::Value series(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE parentStudy=?"); + s2.BindString(0, studyUuid); + while (s2.Step()) + { + series.append(s2.ColumnString(0)); + } + + result["Series"] = series; + return true; + } + + + bool ServerIndex::GetPatient(Json::Value& result, + const std::string& patientUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT dicomPatientId FROM Patients WHERE uuid=?"); + s1.BindString(0, patientUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = patientUuid; + MainDicomTagsToJson(result, patientUuid); + + Json::Value studies(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE parentPatient=?"); + s2.BindString(0, patientUuid); + while (s2.Step()) + { + studies.append(s2.ColumnString(0)); + } + + result["Studies"] = studies; + return true; + } + + + bool ServerIndex::GetJsonFile(std::string& fileUuid, + const std::string& instanceUuid) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT jsonUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (s.Step()) + { + fileUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + bool ServerIndex::GetDicomFile(std::string& fileUuid, + const std::string& instanceUuid) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (s.Step()) + { + fileUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + + void ServerIndex::GetAllUuids(Json::Value& target, + const std::string& tableName) + { + assert(target.type() == Json::arrayValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + std::string query = "SELECT uuid FROM " + tableName; + SQLite::Statement s(db_, query); + while (s.Step()) + { + target.append(s.ColumnString(0)); + } + } + + + bool ServerIndex::GetChanges(Json::Value& target, + int64_t since, + const std::string& filter, + unsigned int maxResults) + { + assert(target.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + if (filter.size() != 0 && + filter != "instances" && + filter != "series" && + filter != "studies" && + filter != "patients") + { + return false; + } + + std::auto_ptr<SQLite::Statement> s; + if (filter.size() == 0) + { + s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " + "ORDER BY seq LIMIT ?")); + s->BindInt64(0, since); + s->BindInt(1, maxResults); + } + else + { + s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " + "AND basePath=? ORDER BY seq LIMIT ?")); + s->BindInt64(0, since); + s->BindString(1, filter); + s->BindInt(2, maxResults); + } + + int64_t lastSeq = 0; + Json::Value results(Json::arrayValue); + while (s->Step()) + { + int64_t seq = s->ColumnInt64(0); + std::string basePath = s->ColumnString(1); + std::string uuid = s->ColumnString(2); + + if (filter.size() == 0 || + filter == basePath) + { + Json::Value change(Json::objectValue); + change["Seq"] = static_cast<int>(seq); // TODO JsonCpp in 64bit + change["BasePath"] = basePath; + change["ID"] = uuid; + results.append(change); + } + + if (seq > lastSeq) + { + lastSeq = seq; + } + } + + target["Results"] = results; + target["LastSeq"] = static_cast<int>(lastSeq); // TODO JsonCpp in 64bit + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/ServerIndex.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,193 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/thread.hpp> +#include "../Core/SQLite/Connection.h" +#include "../Core/DicomFormat/DicomMap.h" +#include "../Core/FileStorage.h" + + +namespace Palanthir +{ + enum SeriesStatus + { + SeriesStatus_Complete, + SeriesStatus_Missing, + SeriesStatus_Inconsistent, + SeriesStatus_Unknown + }; + + + enum StoreStatus + { + StoreStatus_Success, + StoreStatus_AlreadyStored, + StoreStatus_Failure + }; + + + namespace Internals + { + class SignalDeletedLevelFunction; + } + + + class ServerIndex + { + private: + SQLite::Connection db_; + boost::mutex mutex_; + + // DO NOT delete the following one, SQLite::Connection will do it automatically + Internals::SignalDeletedLevelFunction* deletedLevels_; + + void StoreMainDicomTags(const std::string& uuid, + const DicomMap& map); + + bool GetMainDicomStringTag(std::string& result, + const std::string& uuid, + const DicomTag& tag); + + bool GetMainDicomIntTag(int& result, + const std::string& uuid, + const DicomTag& tag); + + bool HasInstance(std::string& instanceUuid, + const std::string& dicomInstance); + + void RecordChange(const std::string& resourceType, + const std::string& uuid); + + std::string CreateInstance(const std::string& parentSeriesUuid, + const std::string& dicomInstance, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t fileSize, + const std::string& jsonUuid, + const std::string& distantAet); + + void RemoveInstance(const std::string& uuid); + + bool HasSeries(std::string& seriesUuid, + const std::string& dicomSeries); + + std::string CreateSeries(const std::string& parentStudyUuid, + const std::string& dicomSeries, + const DicomMap& dicomSummary); + + bool HasStudy(std::string& studyUuid, + const std::string& dicomStudy); + + std::string CreateStudy(const std::string& parentPatientUuid, + const std::string& dicomStudy, + const DicomMap& dicomSummary); + + bool HasPatient(std::string& patientUuid, + const std::string& dicomPatientId); + + std::string CreatePatient(const std::string& patientId, + const DicomMap& dicomSummary); + + void GetMainDicomTags(DicomMap& map, + const std::string& uuid); + + void MainDicomTagsToJson(Json::Value& target, + const std::string& uuid); + + bool DeleteInternal(Json::Value& target, + const std::string& uuid, + const std::string& tableName); + + public: + ServerIndex(const std::string& storagePath); + + StoreStatus Store(std::string& instanceUuid, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t uncompressedFileSize, + const std::string& jsonUuid, + const std::string& distantAet); + + StoreStatus Store(std::string& instanceUuid, + FileStorage& storage, + const char* dicomFile, + size_t dicomSize, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet); + + uint64_t GetTotalSize(); + + SeriesStatus GetSeriesStatus(const std::string& seriesUuid); + + + bool GetInstance(Json::Value& result, + const std::string& instanceUuid); + + bool GetSeries(Json::Value& result, + const std::string& seriesUuid); + + bool GetStudy(Json::Value& result, + const std::string& studyUuid); + + bool GetPatient(Json::Value& result, + const std::string& patientUuid); + + bool GetJsonFile(std::string& fileUuid, + const std::string& instanceUuid); + + bool GetDicomFile(std::string& fileUuid, + const std::string& instanceUuid); + + void GetAllUuids(Json::Value& target, + const std::string& tableName); + + bool DeletePatient(Json::Value& target, + const std::string& patientUuid) + { + return DeleteInternal(target, patientUuid, "Patients"); + } + + bool DeleteStudy(Json::Value& target, + const std::string& studyUuid) + { + return DeleteInternal(target, studyUuid, "Studies"); + } + + bool DeleteSeries(Json::Value& target, + const std::string& seriesUuid) + { + return DeleteInternal(target, seriesUuid, "Series"); + } + + bool DeleteInstance(Json::Value& target, + const std::string& instanceUuid) + { + return DeleteInternal(target, instanceUuid, "Instances"); + } + + bool GetChanges(Json::Value& target, + int64_t since, + const std::string& filter, + unsigned int maxResults); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/ToDcmtkBridge.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,49 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "ToDcmtkBridge.h" + +#include <memory> +#include <dcmtk/dcmdata/dcelem.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palanthir +{ + DcmTagKey ToDcmtkBridge::Convert(const DicomTag& tag) + { + return DcmTagKey(tag.GetGroup(), tag.GetElement()); + } + + + DcmDataset* ToDcmtkBridge::Convert(const DicomMap& map) + { + std::auto_ptr<DcmDataset> result(new DcmDataset); + + for (DicomMap::Map::const_iterator + it = map.map_.begin(); it != map.map_.end(); it++) + { + std::string s = it->second->AsString(); + DU_putStringDOElement(result.get(), Convert(it->first), s.c_str()); + } + + return result.release(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/ToDcmtkBridge.h Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" +#include <dcmtk/dcmdata/dcdatset.h> + + +namespace Palanthir +{ + class ToDcmtkBridge + { + public: + static DcmTagKey Convert(const DicomTag& tag); + + static DcmDataset* Convert(const DicomMap& map); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/main.cpp Sun Sep 16 09:22:48 2012 +0200 @@ -0,0 +1,169 @@ +/** + * Palanthir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PalanthirRestApi.h" + +#include <stdio.h> + +#include "../Core/HttpServer/EmbeddedResourceHttpHandler.h" +#include "../Core/HttpServer/FilesystemHttpHandler.h" +#include "../Core/HttpServer/MongooseServer.h" +#include "DicomProtocol/DicomServer.h" +#include "PalanthirInitialization.h" + + +using namespace Palanthir; + + +class MyDicomStore : public IStoreRequestHandler +{ +private: + ServerIndex& index_; + FileStorage storage_; + +public: + MyDicomStore(ServerIndex& index, + const std::string& path) : + index_(index), + storage_(path) + { + } + + virtual void Handle(const std::vector<uint8_t>& dicomFile, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& remoteAet) + { + std::string instanceUuid; + if (dicomFile.size() > 0) + { + index_.Store(instanceUuid, storage_, + reinterpret_cast<const char*>(&dicomFile[0]), dicomFile.size(), + dicomSummary, dicomJson, remoteAet); + } + } +}; + + +class MyDicomStoreFactory : public IStoreRequestHandlerFactory +{ +private: + ServerIndex& index_; + std::string path_; + +public: + MyDicomStoreFactory(ServerIndex& index, + const std::string& path) : + index_(index), + path_(path) + { + } + + virtual IStoreRequestHandler* ConstructStoreRequestHandler() + { + return new MyDicomStore(index_, path_); + } + + void Done() + { + //index_.db().Execute("DELETE FROM Studies"); + } +}; + + + + + + + +int main(int argc, char* argv[]) +{ + try + { + if (argc >= 2) + { + PalanthirInitialize(argv[1]); + } + else + { + PalanthirInitialize(); + } + + std::string storageDirectory = GetGlobalStringParameter("StorageDirectory", "PalanthirStorage"); + ServerIndex index(storageDirectory); + MyDicomStoreFactory storeScp(index, storageDirectory); + + { + // DICOM server + DicomServer dicomServer; + dicomServer.SetCalledApplicationEntityTitleCheck(GetGlobalBoolParameter("DicomCheckCalledAet", false)); + dicomServer.SetStoreRequestHandlerFactory(storeScp); + dicomServer.SetPortNumber(GetGlobalIntegerParameter("DicomPort", 4242)); + dicomServer.SetApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTHIR")); + + // HTTP server + MongooseServer httpServer; + httpServer.SetPort(GetGlobalIntegerParameter("HttpPort", 8000)); + httpServer.SetRemoteAccessAllowed(GetGlobalBoolParameter("RemoteAccessAllowed", false)); + + httpServer.SetAuthenticationEnabled(GetGlobalBoolParameter("AuthenticationEnabled", false)); + SetupRegisteredUsers(httpServer); + + if (GetGlobalBoolParameter("SslEnabled", false)) + { + std::string certificate = GetGlobalStringParameter("SslCertificate", "certificate.pem"); + httpServer.SetSslEnabled(true); + httpServer.SetSslCertificate(certificate.c_str()); + } + else + { + httpServer.SetSslEnabled(false); + } + +#if PALANTHIR_STANDALONE == 1 + httpServer.RegisterHandler(new EmbeddedResourceHttpHandler("/app", EmbeddedResources::PALANTHIR_EXPLORER)); +#else + httpServer.RegisterHandler(new FilesystemHttpHandler("/app", PALANTHIR_PATH "/PalanthirExplorer")); +#endif + + httpServer.RegisterHandler(new PalanthirRestApi(index, storageDirectory)); + + // GO !!! + httpServer.Start(); + dicomServer.Start(); + + printf("The server has started\n"); + Toolbox::ServerBarrier(); + + // Stop + printf("Finishing\n"); + } + + storeScp.Done(); + } + catch (PalanthirException& e) + { + std::cout << "EXCEPT [" << e.What() << "]" << std::endl; + } + + PalanthirFinalize(); + + return 0; +}
--- a/PalanthirCppClient/CMakeLists.txt Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -# Mini-project to check whether "PalanthirCppClient" can compile in a -# standalone fashion - -cmake_minimum_required(VERSION 2.8) - -project(PalanthirCppClientTest) - -SET(STATIC_BUILD OFF) - -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DownloadPackage.cmake) -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/JsonCppConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/LibCurlConfiguration.cmake) - -if (${CMAKE_COMPILER_IS_GNUCXX}) - set(CMAKE_C_FLAGS "-Wall -pedantic -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile - set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wno-long-long -Wno-variadic-macros") - set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") -elseif (${MSVC}) - add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) -endif() - -add_library(PalanthirCppClient - SHARED - - ${THIRD_PARTY_SOURCES} - HttpException.cpp - HttpClient.cpp - ) - -add_executable(Test - main.cpp - ) - -target_link_libraries(Test PalanthirCppClient)
--- a/PalanthirCppClient/HttpClient.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpClient.h" - -#include <string.h> -#include <curl/curl.h> - - -namespace Palanthir -{ - struct HttpClient::PImpl - { - CURL* curl_; - struct curl_slist *postHeaders_; - }; - - - static CURLcode CheckCode(CURLcode code) - { - if (code != CURLE_OK) - { - printf("ICI: %s\n", curl_easy_strerror(code)); - throw HttpException("CURL: " + std::string(curl_easy_strerror(code))); - } - - return code; - } - - - static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *payload) - { - std::string& target = *(static_cast<std::string*>(payload)); - - size_t length = size * nmemb; - if (length == 0) - return 0; - - size_t pos = target.size(); - - target.resize(pos + length); - memcpy(&target.at(pos), buffer, length); - - return length; - } - - - HttpClient::HttpClient() : pimpl_(new PImpl) - { - pimpl_->postHeaders_ = NULL; - if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL) - { - throw HttpException("HttpClient: Not enough memory"); - } - - pimpl_->curl_ = curl_easy_init(); - if (!pimpl_->curl_) - { - curl_slist_free_all(pimpl_->postHeaders_); - throw HttpException("HttpClient: Not enough memory"); - } - - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1)); - -#if PALANTHIR_SSL_ENABLED == 1 - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); -#endif - - url_ = ""; - method_ = Palanthir_HttpMethod_Get; - lastStatus_ = Palanthir_HttpStatus_200_Ok; - isVerbose_ = false; - } - - - HttpClient::~HttpClient() - { - curl_easy_cleanup(pimpl_->curl_); - curl_slist_free_all(pimpl_->postHeaders_); - } - - - void HttpClient::SetVerbose(bool isVerbose) - { - isVerbose_ = isVerbose; - - if (isVerbose_) - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1)); - } - else - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0)); - } - } - - - bool HttpClient::Apply(std::string& answer) - { - answer.clear(); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, NULL)); - - switch (method_) - { - case Palanthir_HttpMethod_Get: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L)); - break; - - case Palanthir_HttpMethod_Post: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->postHeaders_)); - - if (postData_.size() > 0) - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, postData_.c_str())); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, postData_.size())); - } - else - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0)); - } - - break; - - case Palanthir_HttpMethod_Delete: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE")); - break; - - case Palanthir_HttpMethod_Put: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L)); - break; - - default: - throw HttpException("HttpClient: Internal error"); - } - - // Do the actual request - CheckCode(curl_easy_perform(pimpl_->curl_)); - - long status; - CheckCode(curl_easy_getinfo(pimpl_->curl_, CURLINFO_RESPONSE_CODE, &status)); - - if (status == 0) - { - // This corresponds to a call to an inexistent host - lastStatus_ = Palanthir_HttpStatus_500_InternalServerError; - } - else - { - lastStatus_ = static_cast<Palanthir_HttpStatus>(status); - } - - return (status >= 200 && status < 300); - } - - - bool HttpClient::Apply(Json::Value& answer) - { - std::string s; - if (Apply(s)) - { - Json::Reader reader; - return reader.parse(s, answer); - } - else - { - return false; - } - } -}
--- a/PalanthirCppClient/HttpClient.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - -#include "HttpEnumerations.h" -#include "HttpException.h" - -#include <string> -#include <boost/shared_ptr.hpp> -#include <json/json.h> - -namespace Palanthir -{ - class HttpClient - { - private: - struct PImpl; - boost::shared_ptr<PImpl> pimpl_; - - std::string url_; - Palanthir_HttpMethod method_; - Palanthir_HttpStatus lastStatus_; - std::string postData_; - bool isVerbose_; - - public: - HttpClient(); - - ~HttpClient(); - - void SetUrl(const char* url) - { - url_ = std::string(url); - } - - void SetUrl(const std::string& url) - { - url_ = url; - } - - const std::string& GetUrl() const - { - return url_; - } - - void SetMethod(Palanthir_HttpMethod method) - { - method_ = method; - } - - Palanthir_HttpMethod GetMethod() const - { - return method_; - } - - std::string& AccessPostData() - { - return postData_; - } - - const std::string& AccessPostData() const - { - return postData_; - } - - void SetVerbose(bool isVerbose); - - bool IsVerbose() const - { - return isVerbose_; - } - - bool Apply(std::string& answer); - - bool Apply(Json::Value& answer); - - Palanthir_HttpStatus GetLastStatus() const - { - return lastStatus_; - } - - const char* GetLastStatusText() const - { - return HttpException::GetDescription(lastStatus_); - } - - }; -}
--- a/PalanthirCppClient/HttpEnumerations.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - - -/** - * This file contains the enumerations for the access to the Palanthir - * REST API in C and C++. Namespaces are not used, in order to enable - * the access in C. - **/ - -// Most common, non-joke and non-experimental HTTP status codes -// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes -enum Palanthir_HttpStatus -{ - Palanthir_HttpStatus_None = -1, - - // 1xx Informational - Palanthir_HttpStatus_100_Continue = 100, - Palanthir_HttpStatus_101_SwitchingProtocols = 101, - Palanthir_HttpStatus_102_Processing = 102, - - // 2xx Success - Palanthir_HttpStatus_200_Ok = 200, - Palanthir_HttpStatus_201_Created = 201, - Palanthir_HttpStatus_202_Accepted = 202, - Palanthir_HttpStatus_203_NonAuthoritativeInformation = 203, - Palanthir_HttpStatus_204_NoContent = 204, - Palanthir_HttpStatus_205_ResetContent = 205, - Palanthir_HttpStatus_206_PartialContent = 206, - Palanthir_HttpStatus_207_MultiStatus = 207, - Palanthir_HttpStatus_208_AlreadyReported = 208, - Palanthir_HttpStatus_226_IMUsed = 226, - - // 3xx Redirection - Palanthir_HttpStatus_300_MultipleChoices = 300, - Palanthir_HttpStatus_301_MovedPermanently = 301, - Palanthir_HttpStatus_302_Found = 302, - Palanthir_HttpStatus_303_SeeOther = 303, - Palanthir_HttpStatus_304_NotModified = 304, - Palanthir_HttpStatus_305_UseProxy = 305, - Palanthir_HttpStatus_307_TemporaryRedirect = 307, - - // 4xx Client Error - Palanthir_HttpStatus_400_BadRequest = 400, - Palanthir_HttpStatus_401_Unauthorized = 401, - Palanthir_HttpStatus_402_PaymentRequired = 402, - Palanthir_HttpStatus_403_Forbidden = 403, - Palanthir_HttpStatus_404_NotFound = 404, - Palanthir_HttpStatus_405_MethodNotAllowed = 405, - Palanthir_HttpStatus_406_NotAcceptable = 406, - Palanthir_HttpStatus_407_ProxyAuthenticationRequired = 407, - Palanthir_HttpStatus_408_RequestTimeout = 408, - Palanthir_HttpStatus_409_Conflict = 409, - Palanthir_HttpStatus_410_Gone = 410, - Palanthir_HttpStatus_411_LengthRequired = 411, - Palanthir_HttpStatus_412_PreconditionFailed = 412, - Palanthir_HttpStatus_413_RequestEntityTooLarge = 413, - Palanthir_HttpStatus_414_RequestUriTooLong = 414, - Palanthir_HttpStatus_415_UnsupportedMediaType = 415, - Palanthir_HttpStatus_416_RequestedRangeNotSatisfiable = 416, - Palanthir_HttpStatus_417_ExpectationFailed = 417, - Palanthir_HttpStatus_422_UnprocessableEntity = 422, - Palanthir_HttpStatus_423_Locked = 423, - Palanthir_HttpStatus_424_FailedDependency = 424, - Palanthir_HttpStatus_426_UpgradeRequired = 426, - - // 5xx Server Error - Palanthir_HttpStatus_500_InternalServerError = 500, - Palanthir_HttpStatus_501_NotImplemented = 501, - Palanthir_HttpStatus_502_BadGateway = 502, - Palanthir_HttpStatus_503_ServiceUnavailable = 503, - Palanthir_HttpStatus_504_GatewayTimeout = 504, - Palanthir_HttpStatus_505_HttpVersionNotSupported = 505, - Palanthir_HttpStatus_506_VariantAlsoNegotiates = 506, - Palanthir_HttpStatus_507_InsufficientStorage = 507, - Palanthir_HttpStatus_509_BandwidthLimitExceeded = 509, - Palanthir_HttpStatus_510_NotExtended = 510 -}; - - -enum Palanthir_HttpMethod -{ - Palanthir_HttpMethod_Get = 0, - Palanthir_HttpMethod_Post = 1, - Palanthir_HttpMethod_Delete = 2, - Palanthir_HttpMethod_Put = 3 -};
--- a/PalanthirCppClient/HttpException.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpException.h" - -namespace Palanthir -{ - const char* HttpException::What() const - { - if (status_ == Palanthir_HttpStatus_None) - { - return custom_.c_str(); - } - else - { - return GetDescription(status_); - } - } - - const char* HttpException::GetDescription(Palanthir_HttpStatus status) - { - switch (status) - { - case Palanthir_HttpStatus_100_Continue: - return "Continue"; - - case Palanthir_HttpStatus_101_SwitchingProtocols: - return "Switching Protocols"; - - case Palanthir_HttpStatus_102_Processing: - return "Processing"; - - case Palanthir_HttpStatus_200_Ok: - return "OK"; - - case Palanthir_HttpStatus_201_Created: - return "Created"; - - case Palanthir_HttpStatus_202_Accepted: - return "Accepted"; - - case Palanthir_HttpStatus_203_NonAuthoritativeInformation: - return "Non-Authoritative Information"; - - case Palanthir_HttpStatus_204_NoContent: - return "No Content"; - - case Palanthir_HttpStatus_205_ResetContent: - return "Reset Content"; - - case Palanthir_HttpStatus_206_PartialContent: - return "Partial Content"; - - case Palanthir_HttpStatus_207_MultiStatus: - return "Multi-Status"; - - case Palanthir_HttpStatus_208_AlreadyReported: - return "Already Reported"; - - case Palanthir_HttpStatus_226_IMUsed: - return "IM Used"; - - case Palanthir_HttpStatus_300_MultipleChoices: - return "Multiple Choices"; - - case Palanthir_HttpStatus_301_MovedPermanently: - return "Moved Permanently"; - - case Palanthir_HttpStatus_302_Found: - return "Found"; - - case Palanthir_HttpStatus_303_SeeOther: - return "See Other"; - - case Palanthir_HttpStatus_304_NotModified: - return "Not Modified"; - - case Palanthir_HttpStatus_305_UseProxy: - return "Use Proxy"; - - case Palanthir_HttpStatus_307_TemporaryRedirect: - return "Temporary Redirect"; - - case Palanthir_HttpStatus_400_BadRequest: - return "Bad Request"; - - case Palanthir_HttpStatus_401_Unauthorized: - return "Unauthorized"; - - case Palanthir_HttpStatus_402_PaymentRequired: - return "Payment Required"; - - case Palanthir_HttpStatus_403_Forbidden: - return "Forbidden"; - - case Palanthir_HttpStatus_404_NotFound: - return "Not Found"; - - case Palanthir_HttpStatus_405_MethodNotAllowed: - return "Method Not Allowed"; - - case Palanthir_HttpStatus_406_NotAcceptable: - return "Not Acceptable"; - - case Palanthir_HttpStatus_407_ProxyAuthenticationRequired: - return "Proxy Authentication Required"; - - case Palanthir_HttpStatus_408_RequestTimeout: - return "Request Timeout"; - - case Palanthir_HttpStatus_409_Conflict: - return "Conflict"; - - case Palanthir_HttpStatus_410_Gone: - return "Gone"; - - case Palanthir_HttpStatus_411_LengthRequired: - return "Length Required"; - - case Palanthir_HttpStatus_412_PreconditionFailed: - return "Precondition Failed"; - - case Palanthir_HttpStatus_413_RequestEntityTooLarge: - return "Request Entity Too Large"; - - case Palanthir_HttpStatus_414_RequestUriTooLong: - return "Request-URI Too Long"; - - case Palanthir_HttpStatus_415_UnsupportedMediaType: - return "Unsupported Media Type"; - - case Palanthir_HttpStatus_416_RequestedRangeNotSatisfiable: - return "Requested Range Not Satisfiable"; - - case Palanthir_HttpStatus_417_ExpectationFailed: - return "Expectation Failed"; - - case Palanthir_HttpStatus_422_UnprocessableEntity: - return "Unprocessable Entity"; - - case Palanthir_HttpStatus_423_Locked: - return "Locked"; - - case Palanthir_HttpStatus_424_FailedDependency: - return "Failed Dependency"; - - case Palanthir_HttpStatus_426_UpgradeRequired: - return "Upgrade Required"; - - case Palanthir_HttpStatus_500_InternalServerError: - return "Internal Server Error"; - - case Palanthir_HttpStatus_501_NotImplemented: - return "Not Implemented"; - - case Palanthir_HttpStatus_502_BadGateway: - return "Bad Gateway"; - - case Palanthir_HttpStatus_503_ServiceUnavailable: - return "Service Unavailable"; - - case Palanthir_HttpStatus_504_GatewayTimeout: - return "Gateway Timeout"; - - case Palanthir_HttpStatus_505_HttpVersionNotSupported: - return "HTTP Version Not Supported"; - - case Palanthir_HttpStatus_506_VariantAlsoNegotiates: - return "Variant Also Negotiates"; - - case Palanthir_HttpStatus_507_InsufficientStorage: - return "Insufficient Storage"; - - case Palanthir_HttpStatus_509_BandwidthLimitExceeded: - return "Bandwidth Limit Exceeded"; - - case Palanthir_HttpStatus_510_NotExtended: - return "Not Extended"; - - default: - throw HttpException("Unknown HTTP status"); - } - } -}
--- a/PalanthirCppClient/HttpException.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - -#include "HttpEnumerations.h" - -#include <string> - -namespace Palanthir -{ - class HttpException - { - private: - Palanthir_HttpStatus status_; - std::string custom_; - - public: - static const char* GetDescription(Palanthir_HttpStatus status); - - HttpException(const std::string& custom) - { - status_ = Palanthir_HttpStatus_None; - custom_ = custom; - } - - HttpException(Palanthir_HttpStatus status) - { - status_ = status; - } - - Palanthir_HttpStatus GetHttpStatus() const - { - return status_; - } - - const char* What() const; - }; -}
--- a/PalanthirCppClient/main.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpClient.h" - -#include <iostream> - -int main() -{ - // Prepare a simple call to a Web service - Palanthir::HttpClient c; - c.SetUrl("http://nominatim.openstreetmap.org/search?format=json&q=chu+liege+belgium"); - - // Do the request and store the result in a JSON structure - Json::Value result; - c.Apply(result); - - // Display the JSON answer - std::cout << result << std::endl; - - return 0; -}
--- a/PalanthirExplorer/explorer.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -ul.tree ul { - margin-left: 36px; -} - -#progress { - position: relative; - /*height: 2em; */ - width: 100%; - background-color: grey; - height: 2.5em; -} - -#progress .label { - z-index: 10; - position: absolute; - left:0; - top: 0; - width: 100%; - font-weight: bold; - text-align: center; - text-shadow: none; - padding: .5em; - color: white; -} - -#progress .bar { - z-index: 0; - position: absolute; - left:0; - top: 0; - height: 100%; - width: 0%; - background-color: green; -}
--- a/PalanthirExplorer/explorer.html Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -<!DOCTYPE html> - -<html> - <head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Palanthir Explorer</title> - - <link rel="stylesheet" href="libs/jquery.mobile-1.1.0.min.css" /> - <link rel="stylesheet" href="libs/jqtree.css" /> - <link rel="stylesheet" href="libs/jquery.mobile.simpledialog.min.css" /> - <link rel="stylesheet" href="libs/jquery-file-upload/css/style.css" /> - <link rel="stylesheet" href="libs/jquery-file-upload/css/jquery.fileupload-ui.css" /> - <link rel="stylesheet" href="libs/slimbox2/slimbox2.css" /> - - <script src="libs/jquery-1.7.2.min.js"></script> - <script src="libs/jquery.mobile-1.1.0.min.js"></script> - <script src="libs/jqm.page.params.js"></script> - <script src="libs/tree.jquery.js"></script> - <script src="libs/date.js"></script> - <script src="libs/jquery.mobile.simpledialog2.js"></script> - <script src="libs/slimbox2.js"></script> - <script src="libs/jquery.blockUI.js"></script> - - <!-- https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin --> - <script src="libs/jquery-file-upload/js/vendor/jquery.ui.widget.js"></script> - <script src="libs/jquery-file-upload/js/jquery.iframe-transport.js"></script> - <script src="libs/jquery-file-upload/js/jquery.fileupload.js"></script> - - <link rel="stylesheet" href="explorer.css" /> - <script src="file-upload.js"></script> - <script src="explorer.js"></script> - </head> - <body> - <div data-role="page" id="find-patients" > - <div data-role="header" > - <h1>Find a patient</h1> - <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> - </div> - <div data-role="content"> - <ul id="all-patients" data-role="listview" data-inset="true" data-filter="true"> - </ul> - </div> - </div> - - <div data-role="page" id="upload" > - <div data-role="header" > - <h1>Upload DICOM files</h1> - <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> - </div> - <div data-role="content"> - <div style="display:none"> - <input id="fileupload" type="file" name="files[]" data-url="/instances/" multiple> - </div> - <p> - <ul data-role="listview" data-inset="true"> - <li data-icon="arrow-r" data-theme="e"><a href="#" id="upload-button">Start the upload</a></li> - <!--li data-icon="gear" data-theme="e"><a href="#" id="upload-abort" class="ui-disabled">Abort the current upload</a></li--> - <li data-icon="delete" data-theme="e"><a href="#" id="upload-clear">Clear the pending uploads</a></li> - </ul> - <div id="progress" class="ui-corner-all"> - <span class="bar ui-corner-all"></span> - <div class="label"></div> - </div> - </p> - <ul id="upload-list" data-role="listview" data-inset="true"> - <li data-role="list-divider">Drag and drop DICOM files here</li> - </ul> - </div> - </div> - - <div data-role="page" id="patient" > - <div data-role="header" > - <h1>List of the studies of one patient</h1> - <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> - <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> - </div> - <div data-role="content"> - <div class="ui-grid-a"> - <div class="ui-block-a" style="width:30%"> - <div style="padding-right:10px"> - <ul data-role="listview" data-inset="true" data-theme="a" id="patient-info"> - </ul> - <p> - <a href="#find-patients" data-role="button" data-icon="search">Go to patient finder</a> - <a href="#" data-role="button" data-icon="delete" id="patient-delete">Delete this patient</a> - </p> - </div> - </div> - <div class="ui-block-b" style="width:70%"> - <div style="padding:10px"> - <ul id="list-studies" data-role="listview" data-inset="true" data-filter="true"> - </ul> - </div> - </div> - </div> - </div> - </div> - - <div data-role="page" id="study"> - <div data-role="header"> - <h1>List of the series of one study</h1> - <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> - <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> - </div> - <div data-role="content"> - <div class="ui-grid-a"> - <div class="ui-block-a" style="width:30%"> - <div style="padding-right:10px"> - <ul data-role="listview" data-inset="true" data-theme="a" id="study-info"> - </ul> - <p> - <a href="#" data-role="button" data-icon="delete" id="study-delete">Delete this study</a> - </p> - </div> - </div> - <div class="ui-block-b" style="width:70%"> - <div style="padding:10px"> - <ul id="list-series" data-role="listview" data-inset="true" data-filter="true"> - </ul> - </div> - </div> - </div> - </div> - </div> - - <div data-role="page" id="series"> - <div data-role="header"> - <h1>List of the instances of one series</h1> - <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> - <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> - </div> - <div data-role="content"> - <div class="ui-grid-a"> - <div class="ui-block-a" style="width:30%"> - <div style="padding-right:10px"> - <ul data-role="listview" data-inset="true" data-theme="a" id="series-info"> - </ul> - <p> - <a href="#" data-role="button" data-icon="delete" id="series-delete">Delete this series</a> - <a href="#" data-role="button" data-icon="arrow-d" id="series-preview">Preview this series</a> - <a href="#" data-role="button" data-icon="arrow-d" id="series-store">Store in another DICOM modality</a> - </p> - </div> - </div> - <div class="ui-block-b" style="width:70%"> - <div style="padding:10px"> - <ul id="list-instances" data-role="listview" data-inset="true" data-filter="true"> - </ul> - </div> - </div> - </div> - </div> - </div> - - <div data-role="page" id="instance"> - <div data-role="header"> - <h1>One DICOM instance</h1> - <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> - <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> - </div> - <div data-role="content"> - <div class="ui-grid-a"> - <div class="ui-block-a" style="width:30%"> - <div style="padding-right:10px"> - <ul data-role="listview" data-inset="true" data-theme="a" id="instance-info"> - </ul> - <p> - <a href="#" data-role="button" data-icon="delete" id="instance-delete">Delete this instance</a> - <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-dicom">Download the DICOM file</a> - <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-json">Download the JSON file</a> - <a href="#" data-role="button" data-icon="arrow-d" id="instance-preview">Preview the instance</a> - <a href="#" data-role="button" data-icon="arrow-d" id="instance-store">Store in another DICOM modality</a> - </p> - </div> - </div> - <div class="ui-block-b" style="width:70%"> - <div style="padding:10px"> - <div class="ui-body ui-body-b"> - <h1>DICOM Tags</h1> - <p align="right"> - <input type="checkbox" id="show-tag-name" checked="checked" class="custom" data-mini="true" /> - <label for="show-tag-name">Show tag description</label> - </p> - <div id="dicom-tree"></div> - </div> - </div> - </div> - </div> - </div> - </div> - - <div id="loading" style="display:none;" class="ui-body-c"> - <p align="center"><b>Sending to DICOM modality...</b></p> - <p><img src="libs/images/ajax-loader2.gif" alt="" /></p> - </div> - - <div id="dialog" style="display:none" > - </div> - </body> -</html>
--- a/PalanthirExplorer/explorer.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,729 +0,0 @@ -// http://stackoverflow.com/questions/1663741/is-there-a-good-jquery-drag-and-drop-file-upload-plugin - - -// Forbid the access to IE -if ($.browser.msie) -{ - alert("Please use Mozilla Firefox or Google Chrome. Microsoft Internet Explorer is not supported."); -} - -// http://jquerymobile.com/demos/1.1.0/docs/api/globalconfig.html -//$.mobile.ajaxEnabled = false; -//$.mobile.page.prototype.options.addBackBtn = true; -//$.mobile.defaultPageTransition = 'slide'; - -// http://stackoverflow.com/a/4673436 -String.prototype.format = function() { - var args = arguments; - return this.replace(/{(\d+)}/g, function(match, number) { - /*return typeof args[number] != 'undefined' - ? args[number] - : match;*/ - - return args[number]; - }); -}; - - -$(document).ready(function() { - var $tree = $('#dicom-tree'); - $tree.tree({ - autoEscape: false - }); - - $('#dicom-tree').bind( - 'tree.click', - function(event) { - if (event.node.is_open) - $tree.tree('closeNode', event.node, true); - else - $tree.tree('openNode', event.node, true); - } - ); -}); - - -function SplitLongUid(s) -{ - return '<span>' + s.substr(0, s.length / 2) + '</span> <span>' + s.substr(s.length / 2, s.length - s.length / 2) + '</span>'; -} - - -function ParseDicomDate(s) -{ - y = parseInt(s.substr(0, 4), 10); - m = parseInt(s.substr(4, 2), 10) - 1; - d = parseInt(s.substr(6, 2), 10); - - if (y == null || m == null || d == null || - !isFinite(y) || !isFinite(m) || !isFinite(d)) - { - return null; - } - - if (y < 1900 || y > 2100 || - m < 0 || m >= 12 || - d <= 0 || d >= 32) - { - return null; - } - - return new Date(y, m, d); -} - - -function FormatDicomDate(s) -{ - if (s == undefined) - return "No date"; - - var d = ParseDicomDate(s); - if (d == null) - return '?'; - else - return d.toString('dddd, MMMM d, yyyy'); -} - - - -function SortOnDicomTag(arr, tag, isInteger, reverse) -{ - var defaultValue; - if (isInteger) - defaultValue = 0; - else - defaultValue = ''; - - arr.sort(function(a, b) { - var ta = a.MainDicomTags[tag]; - var tb = b.MainDicomTags[tag]; - var order; - - if (ta == undefined) - ta = defaultValue; - - if (tb == undefined) - tb = defaultValue; - - if (isInteger) - { - ta = parseInt(ta, 10); - tb = parseInt(tb, 10); - order = ta - tb; - } - else - { - if (ta < tb) - order = -1; - else if (ta > tb) - order = 1; - else - order = 0; - } - - if (reverse) - return -order; - else - return order; - }); -} - - - -function GetSingleResource(type, uuid, callback) -{ - var resource = null; - $.ajax({ - url: '/' + type + '/' + uuid, - dataType: 'json', - async: false, - success: function(s) { - callback(s); - } - }); -} - - -function GetMultipleResources(type, uuids, callback) -{ - if (uuids == null) - { - $.ajax({ - url: '/' + type, - dataType: 'json', - async: false, - success: function(s) { - uuids = s; - } - }); - } - - var resources = []; - var ajaxRequests = uuids.map(function(uuid) { - return $.ajax({ - url: '/' + type + '/' + uuid, - dataType: 'json', - async: true, - success: function(s) { - resources.push(s); - } - }); - }); - - // Wait for all the AJAX requests to end - $.when.apply($, ajaxRequests).then(function() { - callback(resources); - }); -} - - - -function CompleteFormatting(s, link, isReverse) -{ - if (link != null) - { - s = 'href="' + link + '">' + s + '</a>'; - - if (isReverse) - s = 'data-direction="reverse" '+ s; - - s = '<a ' + s; - } - - if (isReverse) - return '<li data-icon="back">' + s + '</li>'; - else - return '<li>' + s + '</li>'; -} - - -function FormatMainDicomTags(tags, tagsToIgnore) -{ - var s = ''; - - for (var i in tags) - { - if (tagsToIgnore.indexOf(i) == -1) - { - var v = tags[i]; - - if (i == "PatientBirthDate" || - i == "StudyDate" || - i == "SeriesDate") - { - v = FormatDicomDate(v); - } - else if (i == "DicomStudyInstanceUID" || - i == "DicomSeriesInstanceUID") - { - v = SplitLongUid(v); - } - - - s += ('<p>{0}: <strong>{1}</strong></p>').format(i, v); - } - } - - return s; -} - - -function FormatPatient(patient, link, isReverse) -{ - var s = ('<h3>{0}</h3>{1}' + - '<span class="ui-li-count">{2}</span>' - ).format - (patient.MainDicomTags.PatientName, - FormatMainDicomTags(patient.MainDicomTags, [ - "PatientName", - "OtherPatientIDs" - ]), - patient.Studies.length - ); - - return CompleteFormatting(s, link, isReverse); -} - - - -function FormatStudy(study, link, isReverse) -{ - var s = ('<h3>{0}</h3>{1}' + - '<span class="ui-li-count">{2}</span>' - ).format - (study.MainDicomTags.StudyDescription, - FormatMainDicomTags(study.MainDicomTags, [ - "StudyDescription", - "StudyTime" - ]), - study.Series.length - ); - - return CompleteFormatting(s, link, isReverse); -} - - - -function FormatSeries(series, link, isReverse) -{ - var s = ('<h3>{0}</h3>{1}' + - '<span class="ui-li-count">{2}</span>').format - (series.MainDicomTags.SeriesDescription, - FormatMainDicomTags(series.MainDicomTags, [ - "SeriesDescription", - "SeriesTime", - "Manufacturer", - "ImagesInAcquisition", - "SeriesDate" - ]), - series.Instances.length - ); - - return CompleteFormatting(s, link, isReverse); -} - - -function FormatInstance(instance, link, isReverse) -{ - var s = ('<h3>Instance {0}</h3>{1}').format - (instance.MainDicomTags.InstanceNumber, - FormatMainDicomTags(instance.MainDicomTags, [ - "AcquisitionNumber", - "InstanceNumber", - "InstanceCreationDate", - "InstanceCreationTime" - ]) - ); - - return CompleteFormatting(s, link, isReverse); -} - - - - -$('#find-patients').live('pagebeforeshow', function() { - GetMultipleResources('patients', null, function(patients) { - var target = $('#all-patients'); - $('li', target).remove(); - - SortOnDicomTag(patients, 'PatientName', false, false); - - for (var i = 0; i < patients.length; i++) { - var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID); - target.append(p); - } - - target.listview('refresh'); - }); -}); - - - -$('#patient').live('pagebeforeshow', function() { - if ($.mobile.pageData) { - GetSingleResource('patients', $.mobile.pageData.uuid, function(patient) { - GetMultipleResources('studies', patient.Studies, function(studies) { - SortOnDicomTag(studies, 'StudyDate', false, true); - - $('#patient-info li').remove(); - $('#patient-info') - .append('<li data-role="list-divider">Patient</li>') - .append(FormatPatient(patient)) - .listview('refresh'); - - var target = $('#list-studies'); - $('li', target).remove(); - - for (var i = 0; i < studies.length; i++) { - if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate) - { - target.append('<li data-role="list-divider">{0}</li>'.format - (FormatDicomDate(studies[i].MainDicomTags.StudyDate))); - } - - target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID)); - } - - target.listview('refresh'); - }); - }); - } -}); - - -$('#study').live('pagebeforeshow', function() { - if ($.mobile.pageData) { - GetSingleResource('studies', $.mobile.pageData.uuid, function(study) { - GetSingleResource('patients', study.ParentPatient, function(patient) { - GetMultipleResources('series', study.Series, function(series) { - SortOnDicomTag(series, 'SeriesDate', false, true); - - $('#study-info li').remove(); - $('#study-info') - .append('<li data-role="list-divider">Patient</li>') - .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) - .append('<li data-role="list-divider">Study</li>') - .append(FormatStudy(study)) - .listview('refresh'); - - var target = $('#list-series'); - $('li', target).remove(); - for (var i = 0; i < series.length; i++) { - if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate) - { - target.append('<li data-role="list-divider">{0}</li>'.format - (FormatDicomDate(series[i].MainDicomTags.SeriesDate))); - } - target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID)); - } - target.listview('refresh'); - }); - }); - }); - } -}); - - -$('#series').live('pagebeforeshow', function() { - if ($.mobile.pageData) { - GetSingleResource('series', $.mobile.pageData.uuid, function(series) { - GetSingleResource('studies', series.ParentStudy, function(study) { - GetSingleResource('patients', study.ParentPatient, function(patient) { - GetMultipleResources('instances', series.Instances, function(instances) { - SortOnDicomTag(instances, 'InstanceNumber', true, false); - - $('#series-info li').remove(); - $('#series-info') - .append('<li data-role="list-divider">Patient</li>') - .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) - .append('<li data-role="list-divider">Study</li>') - .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) - .append('<li data-role="list-divider">Series</li>') - .append(FormatSeries(series)) - .listview('refresh'); - - var target = $('#list-instances'); - $('li', target).remove(); - for (var i = 0; i < instances.length; i++) { - target.append(FormatInstance(instances[i], '#instance?uuid=' + instances[i].ID)); - } - target.listview('refresh'); - }); - }); - }); - }); - } -}); - - - -function ConvertForTree(dicom) -{ - var result = []; - - for (var i in dicom) { - if (dicom[i] != null) { - var label = i + '<span class="tag-name"> (<i>' + dicom[i]["Name"] + '</i>)</span>: '; - - if (dicom[i]["Type"] == 'String') - { - result.push({ - label: label + '<strong>' + dicom[i]["Value"] + '</strong>', - children: [] - }); - } - else if (dicom[i]["Type"] == 'TooLong') - { - result.push({ - label: label + '<i>Too long</i>', - children: [] - }); - } - else if (dicom[i]["Type"] == 'Null') - { - result.push({ - label: label + '<i>Null</i>', - children: [] - }); - } - else if (dicom[i]["Type"] == 'Sequence') - { - var c = []; - for (var j = 0; j < dicom[i]["Value"].length; j++) { - c.push({ - label: 'Item ' + j, - children: ConvertForTree(dicom[i]["Value"][j]) - }); - } - - result.push({ - label: label + '[]', - children: c - }); - } - } - } - - return result; -} - - -$('#instance').live('pagebeforeshow', function() { - if ($.mobile.pageData) { - GetSingleResource('instances', $.mobile.pageData.uuid, function(instance) { - GetSingleResource('series', instance.ParentSeries, function(series) { - GetSingleResource('studies', series.ParentStudy, function(study) { - GetSingleResource('patients', study.ParentPatient, function(patient) { - - $('#instance-info li').remove(); - $('#instance-info') - .append('<li data-role="list-divider">Patient</li>') - .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) - .append('<li data-role="list-divider">Study</li>') - .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) - .append('<li data-role="list-divider">Series</li>') - .append(FormatSeries(series, '#series?uuid=' + series.ID, true)) - .append('<li data-role="list-divider">Instance</li>') - .append(FormatInstance(instance)) - .listview('refresh'); - - $.ajax({ - url: '/instances/' + instance.ID + '/tags', - dataType: 'json', - success: function(s) { - $('#dicom-tree').tree('loadData', ConvertForTree(s)); - } - }); - - }); - }); - }); - }); - } -}); - - - -function DeleteResource(path) -{ - $.ajax({ - url: path, - type: 'DELETE', - dataType: 'json', - async: false, - success: function(s) { - var ancestor = s.RemainingAncestor; - if (ancestor == null) - $.mobile.changePage('#find-patients'); - else - $.mobile.changePage('#' + ancestor.Type + '?uuid=' + ancestor.ID); - } - }); -} - - - -function OpenDeleteResourceDialog(path, title) -{ - $(document).simpledialog2({ - // http://dev.jtsage.com/jQM-SimpleDialog/demos2/ - // http://dev.jtsage.com/jQM-SimpleDialog/demos2/options.html - mode: 'button', - animate: false, - headerText: title, - headerClose: true, - width: '500px', - buttons : { - 'OK': { - click: function () { - DeleteResource(path); - }, - icon: "delete", - theme: "c" - }, - 'Cancel': { - click: function () { - } - } - } - }); -} - - - -$('#instance-delete').live('click', function() { - OpenDeleteResourceDialog('/instances/' + $.mobile.pageData.uuid, - 'Delete this instance?'); -}); - -$('#study-delete').live('click', function() { - OpenDeleteResourceDialog('/studies/' + $.mobile.pageData.uuid, - 'Delete this study?'); -}); - -$('#series-delete').live('click', function() { - OpenDeleteResourceDialog('/series/' + $.mobile.pageData.uuid, - 'Delete this series?'); -}); - -$('#patient-delete').live('click', function() { - OpenDeleteResourceDialog('/patients/' + $.mobile.pageData.uuid, - 'Delete this patient?'); -}); - - -$('#instance-download-dicom').live('click', function(e) { - // http://stackoverflow.com/a/1296101 - e.preventDefault(); //stop the browser from following - window.location.href = '/instances/' + $.mobile.pageData.uuid + '/file'; -}); - -$('#instance-download-json').live('click', function(e) { - // http://stackoverflow.com/a/1296101 - e.preventDefault(); //stop the browser from following - window.location.href = '/instances/' + $.mobile.pageData.uuid + '/tags'; -}); - - -$('#instance-preview').live('click', function(e) { - if ($.mobile.pageData) { - GetSingleResource('instances', $.mobile.pageData.uuid + '/frames', function(frames) { - if (frames.length == 1) - { - // Viewing a single-frame image - jQuery.slimbox('/instances/' + $.mobile.pageData.uuid + '/preview', '', { - overlayFadeDuration : 1, - resizeDuration : 1, - imageFadeDuration : 1 - }); - } - else - { - // Viewing a multi-frame image - - var images = []; - for (var i = 0; i < frames.length; i++) { - images.push([ '/instances/' + $.mobile.pageData.uuid + '/frames/' + i + '/preview' ]); - } - - jQuery.slimbox(images, 0, { - overlayFadeDuration : 1, - resizeDuration : 1, - imageFadeDuration : 1, - loop : true - }); - } - }); - - } -}); - -$('#series-preview').live('click', function(e) { - if ($.mobile.pageData) { - GetSingleResource('series', $.mobile.pageData.uuid, function(series) { - GetMultipleResources('instances', series.Instances, function(instances) { - SortOnDicomTag(instances, 'InstanceNumber', true, false); - - var images = []; - for (var i = 0; i < instances.length; i++) { - images.push([ '/instances/' + instances[i].ID + '/preview', - '{0}/{1}'.format(i + 1, instances.length) ]) - } - - jQuery.slimbox(images, 0, { - overlayFadeDuration : 1, - resizeDuration : 1, - imageFadeDuration : 1, - loop : true - }); - }) - }); - } -}); - - - - - - -function ChooseDicomModality(callback) -{ - $.ajax({ - url: '/modalities', - type: 'GET', - dataType: 'json', - async: false, - success: function(modalities) { - var clickedModality = ''; - var items = $('<ul>') - .attr('data-role', 'listview'); - - for (var i = 0; i < modalities.length; i++) { - var modality = modalities[i]; - var item = $('<li>') - .html('<a href="#" rel="close">' + modality + '</a>') - .attr('modality', modality) - .click(function() { - clickedModality = $(this).attr('modality'); - }); - items.append(item); - } - - $('#dialog').simpledialog2({ - mode: 'blank', - animate: false, - headerText: 'DICOM modality', - headerClose: true, - width: '100%', - blankContent: items, - callbackClose: function() { - var timer; - function WaitForDialogToClose() { - if (!$('#dialog').is(':visible')) { - clearInterval(timer); - callback(clickedModality); - } - } - timer = setInterval(WaitForDialogToClose, 100); - } - }); - } - }); -} - - -$('#instance-store,#series-store').live('click', function(e) { - ChooseDicomModality(function(modality) { - if (modality != '') { - $.ajax({ - url: '/modalities/' + modality + '/store', - type: 'POST', - dataType: 'text', - data: $.mobile.pageData.uuid, - async: true, // Necessary to block UI - beforeSend: function() { - $.blockUI({ message: $('#loading') }); - }, - complete: function(s) { - $.unblockUI(); - }, - success: function(s) { - console.log('done !'); - }, - error: function() { - alert('Error during C-Store'); - } - }); - - } - }); -}); - - -$('#show-tag-name').live('change', function(e) { - var checked = e.currentTarget.checked; - if (checked) - $('.tag-name').show(); - else - $('.tag-name').hide(); -});
--- a/PalanthirExplorer/file-upload.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -var pendingUploads = []; -var currentUpload = 0; -var totalUpload = 0; - -$(document).ready(function() { - // Initialize the jQuery File Upload widget: - $('#fileupload').fileupload({ - //dataType: 'json', - //maxChunkSize: 500, - //sequentialUploads: true, - limitConcurrentUploads: 3, - add: function (e, data) { - pendingUploads.push(data); - } - }) - .bind('fileuploadstop', function(e, data) { - $('#upload-button').removeClass('ui-disabled'); - //$('#upload-abort').addClass('ui-disabled'); - $('#progress .bar').css('width', '100%'); - if ($('#progress .label').text() != 'Failure') - $('#progress .label').text('Done'); - }) - .bind('fileuploadfail', function(e, data) { - $('#progress .bar') - .css('width', '100%') - .css('background-color', 'red'); - $('#progress .label').text('Failure'); - }) - .bind('fileuploaddrop', function (e, data) { - var target = $('#upload-list'); - $.each(data.files, function (index, file) { - target.append('<li class="pending-file">' + file.name + '</li>'); - }); - target.listview('refresh'); - }) - .bind('fileuploadsend', function (e, data) { - // Update the progress bar. Note: for some weird reason, the - // "fileuploadprogressall" does not work under Firefox. - var progress = parseInt(currentUpload / totalUploads * 100, 10); - currentUpload += 1; - $('#progress .label').text('Uploading: ' + progress + '%'); - $('#progress .bar') - .css('width', progress + '%') - .css('background-color', 'green'); - }); -}); - - - -$('#upload').live('pageshow', function() { - $('#fileupload').fileupload('enable'); -}); - -$('#upload').live('pagehide', function() { - $('#fileupload').fileupload('disable'); -}); - - -$('#upload-button').live('click', function() { - var pu = pendingUploads; - pendingUploads = []; - - $('.pending-file').remove(); - $('#upload-list').listview('refresh'); - $('#progress .bar').css('width', '0%'); - $('#progress .label').text(''); - - currentUpload = 1; - totalUploads = pu.length + 1; - if (pu.length > 0) { - $('#upload-button').addClass('ui-disabled'); - //$('#upload-abort').removeClass('ui-disabled'); - } - - for (var i = 0; i < pu.length; i++) { - pu[i].submit(); - } -}); - -$('#upload-clear').live('click', function() { - pendingUploads = []; - $('.pending-file').remove(); - $('#upload-list').listview('refresh'); -}); - -/*$('#upload-abort').live('click', function() { - $('#fileupload').fileupload().abort(); - });*/
--- a/PalanthirExplorer/libs/date.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/** - * Version: 1.0 Alpha-1 - * Build Date: 13-Nov-2007 - * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. - * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. - * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/ - */ -Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}}; -Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} -return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} -return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}} -return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);} -if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;} -var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);} -if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);} -if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);} -if(x.hour||x.hours){this.addHours(x.hour||x.hours);} -if(x.month||x.months){this.addMonths(x.month||x.months);} -if(x.year||x.years){this.addYears(x.year||x.years);} -if(x.day||x.days){this.addDays(x.day||x.days);} -return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");} -return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;} -if(!x.second&&x.second!==0){x.second=-1;} -if(!x.minute&&x.minute!==0){x.minute=-1;} -if(!x.hour&&x.hour!==0){x.hour=-1;} -if(!x.day&&x.day!==0){x.day=-1;} -if(!x.month&&x.month!==0){x.month=-1;} -if(!x.year&&x.year!==0){x.year=-1;} -if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());} -if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());} -if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());} -if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());} -if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());} -if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());} -if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());} -if(x.timezone){this.setTimezone(x.timezone);} -if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);} -return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;} -var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}} -return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();}; -Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;} -return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);} -var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;} -return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);} -var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";} -return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}}; -(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;} -break;} -return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];} -rx.push(r[0]);s=r[1];} -return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];} -return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];} -throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));} -return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;} -if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} -try{r=(px[i].call(this,s));}catch(e){r=null;} -if(r){return r;}} -throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} -try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);} -rx.push(r[0]);s=r[1];} -return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];} -return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;} -rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;} -s=q[1];} -if(!r){throw new $P.Exception(s);} -if(q){throw new $P.Exception(q[1]);} -if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}} -return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;} -rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;} -if(!last&&q[1].length===0){last=true;} -if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}} -p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}} -if(rx[1].length<best[1].length){best=rx;} -if(best[1].length===0){break;}} -if(best[0].length===0){return best;} -if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);} -best[1]=q[1];} -return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);} -return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];} -if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);} -var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}} -return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}} -this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");} -var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});} -return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;} -for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}} -if(this.now){return new Date();} -var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);} -if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;} -if(!this.unit){this.unit="day";} -if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;} -if(this.unit=="week"){this.unit="day";this.value=this.value*7;} -this[this.unit+"s"]=this.value*orient;} -return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;} -if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();} -if(this.month&&!this.day){this.day=1;} -return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));} -fn=_C[keys]=_.any.apply(null,px);} -return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));} -return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){} -return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;} -try{r=Date.Grammar.start.call({},s);}catch(e){return null;} -return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;} -return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
--- a/PalanthirExplorer/libs/jqm.page.params.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -// jqm.page.params.js - version 0.1 -// Copyright (c) 2011, Kin Blas -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the <organization> nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -(function( $, window, undefined ) { - -// Given a query string, convert all the name/value pairs -// into a property/value object. If a name appears more than -// once in a query string, the value is automatically turned -// into an array. -function queryStringToObject( qstr ) -{ - var result = {}, - nvPairs = ( ( qstr || "" ).replace( /^\?/, "" ).split( /&/ ) ), - i, pair, n, v; - - for ( i = 0; i < nvPairs.length; i++ ) { - var pstr = nvPairs[ i ]; - if ( pstr ) { - pair = pstr.split( /=/ ); - n = pair[ 0 ]; - v = pair[ 1 ]; - if ( result[ n ] === undefined ) { - result[ n ] = v; - } else { - if ( typeof result[ n ] !== "object" ) { - result[ n ] = [ result[ n ] ]; - } - result[ n ].push( v ); - } - } - } - - return result; -} - -// The idea here is to listen for any pagebeforechange notifications from -// jQuery Mobile, and then muck with the toPage and options so that query -// params can be passed to embedded/internal pages. So for example, if a -// changePage() request for a URL like: -// -// http://mycompany.com/myapp/#page-1?foo=1&bar=2 -// -// is made, the page that will actually get shown is: -// -// http://mycompany.com/myapp/#page-1 -// -// The browser's location will still be updated to show the original URL. -// The query params for the embedded page are also added as a property/value -// object on the options object. You can access it from your page notifications -// via data.options.pageData. -$( document ).bind( "pagebeforechange", function( e, data ) { - - // We only want to handle the case where we are being asked - // to go to a page by URL, and only if that URL is referring - // to an internal page by id. - - if ( typeof data.toPage === "string" ) { - var u = $.mobile.path.parseUrl( data.toPage ); - if ( $.mobile.path.isEmbeddedPage( u ) ) { - // The request is for an internal page, if the hash - // contains query (search) params, strip them off the - // toPage URL and then set options.dataUrl appropriately - // so the location.hash shows the originally requested URL - // that hash the query params in the hash. - - var u2 = $.mobile.path.parseUrl( u.hash.replace( /^#/, "" ) ); - if ( u2.search ) { - if ( !data.options.dataUrl ) { - data.options.dataUrl = data.toPage; - } - data.options.pageData = queryStringToObject( u2.search ); - data.toPage = u.hrefNoHash + "#" + u2.pathname; - } - } - } -}); - -})( jQuery, window ); - - - - -// http://stackoverflow.com/a/8295488 -$(document).bind("pagebeforechange", function( event, data ) { - $.mobile.pageData = (data && data.options && data.options.pageData) - ? data.options.pageData - : {}; -});
--- a/PalanthirExplorer/libs/jqtree.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -ul.tree { - margin-left: 12px; -} - -ul.tree, -ul.tree ul { - list-style: none outside; - margin-bottom: 0; - padding: 0; -} - -ul.tree ul { - display: block; - margin-left: 12px; - margin-right: 0; -} - -ul.tree li.closed > ul { - display: none; -} - -ul.tree li { - clear: both; -} - -ul.tree .toggler { - background-image: url(jqtree-icons.png); - background-repeat: no-repeat; - background-position: -8px 0; - width: 8px; - height: 8px; - display: block; - position: absolute; - left: -12px; - top: 30%; - text-indent: -9999px; - border-bottom: none; -} - -ul.tree div { - cursor: pointer; -} - -ul.tree .title { - color: #1C4257; - vertical-align: middle; -} - -ul.tree li.folder { - margin-bottom: 4px; -} - -ul.tree li.folder.closed { - margin-bottom: 1px; -} - -ul.tree li.folder .title { - margin-left: 0; -} - -ul.tree .toggler.closed { - background-position: 0 0; -} - -span.tree-dragging { - color: #fff; - background: #000; - opacity: 0.6; - cursor: pointer; - padding: 2px 8px; -} - -ul.tree li.ghost { - position: relative; - z-index: 10; - margin-right: 10px; -} - -ul.tree li.ghost span { - display: block; -} - -ul.tree li.ghost span.circle { - background-image: url(jqtree-icons.png); - background-repeat: no-repeat; - background-position: 0 -8px; - height: 8px; - width: 8px; - position: absolute; - top: -4px; - left: 2px; -} - -ul.tree li.ghost span.line { - background-color: #0000ff; - height: 2px; - padding: 0; - position: absolute; - top: -1px; - left: 10px; - width: 100%; -} - -ul.tree li.ghost.inside { - margin-left: 48px; -} - -ul.tree span.tree-hit { - position: absolute; - display: block; -} - -ul.tree span.border { - position: absolute; - display: block; - left: -2px; - top: 0; - border: solid 2px #0000ff; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - margin: 0; -} - -ul.tree div { - width: 100%; /* todo: why is this in here? */ - *width: auto; /* ie7 fix; issue 41 */ - position: relative; -} - -ul.tree li.selected > div, -ul.tree li.selected > div:hover { - background-color: #97BDD6; - background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#89AFCA)); - background: -moz-linear-gradient(top, #BEE0F5, #89AFCA); - background: -ms-linear-gradient(top, #BEE0F5, #89AFCA); - background: -o-linear-gradient(top, #BEE0F5, #89AFCA); - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); -} - -ul.tree .moving > div .title { - outline: dashed 1px #0000ff; -}
--- a/PalanthirExplorer/libs/jquery-1.7.2.min.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -/*! jQuery v1.7.2 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},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(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.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(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.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(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={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,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[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","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file
--- a/PalanthirExplorer/libs/jquery-file-upload/css/jquery.fileupload-ui.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -@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; - } -}
--- a/PalanthirExplorer/libs/jquery-file-upload/css/style.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -@charset 'UTF-8'; -/* - * jQuery File Upload Plugin CSS Example 1.0 - * 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 - */ - -body{ - padding-top: 60px; -}
--- a/PalanthirExplorer/libs/jquery-file-upload/js/cors/jquery.postmessage-transport.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * jQuery postMessage Transport Plugin 1.1 - * 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'; - - var counter = 0, - names = [ - 'accepts', - 'cache', - 'contents', - 'contentType', - 'crossDomain', - 'data', - 'dataType', - 'headers', - 'ifModified', - 'mimeType', - 'password', - 'processData', - 'timeout', - 'traditional', - 'type', - 'url', - 'username' - ], - convert = function (p) { - return p; - }; - - $.ajaxSetup({ - converters: { - 'postmessage text': convert, - 'postmessage json': convert, - 'postmessage html': convert - } - }); - - $.ajaxTransport('postmessage', function (options) { - if (options.postMessage && window.postMessage) { - var iframe, - loc = $('<a>').prop('href', options.postMessage)[0], - target = loc.protocol + '//' + loc.host, - xhrUpload = options.xhr().upload; - return { - send: function (_, completeCallback) { - var message = { - id: 'postmessage-transport-' + (counter += 1) - }, - eventName = 'message.' + message.id; - iframe = $( - '<iframe style="display:none;" src="' + - options.postMessage + '" name="' + - message.id + '"></iframe>' - ).bind('load', function () { - $.each(names, function (i, name) { - message[name] = options[name]; - }); - message.dataType = message.dataType.replace('postmessage ', ''); - $(window).bind(eventName, function (e) { - e = e.originalEvent; - var data = e.data, - ev; - if (e.origin === target && data.id === message.id) { - if (data.type === 'progress') { - ev = document.createEvent('Event'); - ev.initEvent(data.type, false, true); - $.extend(ev, data); - xhrUpload.dispatchEvent(ev); - } else { - completeCallback( - data.status, - data.statusText, - {postmessage: data.result}, - data.headers - ); - iframe.remove(); - $(window).unbind(eventName); - } - } - }); - iframe[0].contentWindow.postMessage( - message, - target - ); - }).appendTo(document.body); - }, - abort: function () { - if (iframe) { - iframe.remove(); - } - } - }; - } - }); - -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/cors/jquery.xdr-transport.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * jQuery XDomainRequest Transport Plugin 1.1.2 - * 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 - * - * Based on Julian Aubourg's ajaxHooks xdr.js: - * https://github.com/jaubourg/ajaxHooks/ - */ - -/*jslint unparam: true */ -/*global define, window, XDomainRequest */ - -(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'; - if (window.XDomainRequest && !$.support.cors) { - $.ajaxTransport(function (s) { - if (s.crossDomain && s.async) { - if (s.timeout) { - s.xdrTimeout = s.timeout; - delete s.timeout; - } - var xdr; - return { - send: function (headers, completeCallback) { - function callback(status, statusText, responses, responseHeaders) { - xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; - xdr = null; - completeCallback(status, statusText, responses, responseHeaders); - } - xdr = new XDomainRequest(); - // XDomainRequest only supports GET and POST: - if (s.type === 'DELETE') { - s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + - '_method=DELETE'; - s.type = 'POST'; - } else if (s.type === 'PUT') { - s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + - '_method=PUT'; - s.type = 'POST'; - } - xdr.open(s.type, s.url); - xdr.onload = function () { - callback( - 200, - 'OK', - {text: xdr.responseText}, - 'Content-Type: ' + xdr.contentType - ); - }; - xdr.onerror = function () { - callback(404, 'Not Found'); - }; - if (s.xdrTimeout) { - xdr.ontimeout = function () { - callback(0, 'timeout'); - }; - xdr.timeout = s.xdrTimeout; - } - xdr.send((s.hasContent && s.data) || null); - }, - abort: function () { - if (xdr) { - xdr.onerror = $.noop(); - xdr.abort(); - } - } - }; - } - }); - } -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload-fp.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -/* - * jQuery File Upload File Processing Plugin 1.0 - * 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 - ); - } -}(function ($, loadImage) { - 'use strict'; - - // The File Upload IP version extends the basic fileupload widget - // with file processing functionality: - $.widget('blueimpFP.fileupload', $.blueimp.fileupload, { - - options: { - // The list of file processing actions: - process: [ - /* - { - action: 'load', - fileTypes: /^image\/(gif|jpeg|png)$/, - maxFileSize: 20000000 // 20MB - }, - { - action: 'resize', - maxWidth: 1920, - maxHeight: 1200, - minWidth: 800, - minHeight: 600 - }, - { - action: 'save' - } - */ - ], - - // 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('process', data).done(function () { - data.submit(); - }); - } - }, - - processActions: { - // Loads the image given via data.files and data.index - // as canvas element. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - load: function (data, options) { - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (window.HTMLCanvasElement && - window.HTMLCanvasElement.prototype.toBlob && - ($.type(options.maxFileSize) !== 'number' || - file.size < options.maxFileSize) && - (!options.fileTypes || - options.fileTypes.test(file.type))) { - loadImage( - file, - function (canvas) { - data.canvas = canvas; - dfd.resolveWith(that, [data]); - }, - {canvas: true} - ); - } else { - dfd.rejectWith(that, [data]); - } - return dfd.promise(); - }, - // Resizes the image given as data.canvas and updates - // data.canvas with the resized image. - // Accepts the options maxWidth, maxHeight, minWidth and - // minHeight to scale the given image: - resize: function (data, options) { - if (data.canvas) { - var canvas = loadImage.scale(data.canvas, options); - if (canvas.width !== data.canvas.width || - canvas.height !== data.canvas.height) { - data.canvas = canvas; - data.processed = true; - } - } - return data; - }, - // Saves the processed image given as data.canvas - // inplace at data.index of data.files: - save: function (data, options) { - // Do nothing if no processing has happened: - if (!data.canvas || !data.processed) { - return data; - } - var that = this, - file = data.files[data.index], - name = file.name, - dfd = $.Deferred(), - callback = 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) - ); - } - } - // Store the created blob at the position - // of the original file in the files list: - data.files[data.index] = blob; - dfd.resolveWith(that, [data]); - }; - // Use canvas.mozGetAsFile directly, to retain the filename, as - // Gecko doesn't support the filename option for FormData.append: - if (data.canvas.mozGetAsFile) { - callback(data.canvas.mozGetAsFile( - (/^image\/(jpeg|png)$/.test(file.type) && name) || - ((name && name.replace(/\..+$/, '')) || - 'blob') + '.png', - file.type - )); - } else { - data.canvas.toBlob(callback, file.type); - } - return dfd.promise(); - } - }, - - // Resizes the file at the given index and stores the created blob at - // the original position of the files list, returns a Promise object: - _processFile: function (files, index, options) { - var that = this, - dfd = $.Deferred().resolveWith(that, [{ - files: files, - index: index - }]), - chain = dfd.promise(); - that._processing += 1; - $.each(options.process, function (i, settings) { - chain = chain.pipe(function (data) { - return that.processActions[settings.action] - .call(this, data, settings); - }); - }); - chain.always(function () { - that._processing -= 1; - if (that._processing === 0) { - that.element - .removeClass('fileupload-processing'); - } - }); - if (that._processing === 1) { - that.element.addClass('fileupload-processing'); - } - return chain; - }, - - // Processes the files 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 files (inplace) is done: - process: function (data) { - var that = this, - options = $.extend({}, this.options, data); - if (options.process && options.process.length && - this._isXHRUpload(options)) { - $.each(data.files, function (index, file) { - that._processingQueue = that._processingQueue.pipe( - function () { - var dfd = $.Deferred(); - that._processFile(data.files, index, options) - .always(function () { - dfd.resolveWith(that); - }); - return dfd.promise(); - } - ); - }); - } - return this._processingQueue; - }, - - _create: function () { - $.blueimp.fileupload.prototype._create.call(this); - this._processing = 0; - this._processingQueue = $.Deferred().resolveWith(this) - .promise(); - } - - }); - -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload-ui.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,702 +0,0 @@ -/* - * jQuery File Upload User Interface Plugin 6.9.1 - * 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-fp' - ], factory); - } else { - // Browser globals: - factory( - window.jQuery, - window.tmpl, - window.loadImage - ); - } -}(function ($, tmpl, loadImage) { - 'use strict'; - - // The UI version extends the FP (file processing) version or the basic - // file upload widget and adds complete user interface interaction: - var parentWidget = ($.blueimpFP || $.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 container for the list of files. If undefined, it is set to - // an element with class "files" inside of the widget element: - filesContainer: undefined, - // By default, files are appended to the files container. - // Set the following option to true, to prepend files instead: - prependFiles: false, - // 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('process', data).done(function () { - that._adjustMaxNumberOfFiles(-files.length); - data.isAdjusted = true; - data.files.valid = data.isValidated = that._validate(files); - data.context = that._renderUpload(files).data('data', data); - options.filesContainer[ - options.prependFiles ? 'prepend' : 'append' - ](data.context); - 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' - ) - .attr('aria-valuenow', 100) - .find('.bar').css( - 'width', - '100%' - ); - } - return that._trigger('sent', e, data); - }, - // Callback for successful uploads: - done: function (e, data) { - var that = $(this).data('fileupload'), - template; - if (data.context) { - data.context.each(function (index) { - var file = ($.isArray(data.result) && - data.result[index]) || {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) { - var progress = parseInt(data.loaded / data.total * 100, 10); - data.context.find('.progress') - .attr('aria-valuenow', progress) - .find('.bar').css( - 'width', - progress + '%' - ); - } - }, - // Callback for global upload progress events: - progressall: function (e, data) { - var $this = $(this), - progress = parseInt(data.loaded / data.total * 100, 10), - globalProgressNode = $this.find('.fileupload-progress'), - extendedProgressNode = globalProgressNode - .find('.progress-extended'); - if (extendedProgressNode.length) { - extendedProgressNode.html( - $this.data('fileupload')._renderExtendedProgress(data) - ); - } - globalProgressNode - .find('.progress') - .attr('aria-valuenow', progress) - .find('.bar').css( - 'width', - progress + '%' - ); - }, - // Callback for uploads start, equivalent to the global ajaxStart event: - start: function (e) { - var that = $(this).data('fileupload'); - that._transition($(this).find('.fileupload-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-progress')).done( - function () { - $(this).find('.progress') - .attr('aria-valuenow', '0') - .find('.bar').css('width', '0%'); - $(this).find('.progress-extended').html(' '); - 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'; - }, - - _formatBitrate: function (bits) { - if (typeof bits !== 'number') { - return ''; - } - if (bits >= 1000000000) { - return (bits / 1000000000).toFixed(2) + ' Gbit/s'; - } - if (bits >= 1000000) { - return (bits / 1000000).toFixed(2) + ' Mbit/s'; - } - if (bits >= 1000) { - return (bits / 1000).toFixed(2) + ' kbit/s'; - } - return bits + ' bit/s'; - }, - - _formatTime: function (seconds) { - var date = new Date(seconds * 1000), - days = parseInt(seconds / 86400, 10); - days = days ? days + 'd ' : ''; - return days + - ('0' + date.getUTCHours()).slice(-2) + ':' + - ('0' + date.getUTCMinutes()).slice(-2) + ':' + - ('0' + date.getUTCSeconds()).slice(-2); - }, - - _formatPercentage: function (floatValue) { - return (floatValue * 100).toFixed(2) + ' %'; - }, - - _renderExtendedProgress: function (data) { - return this._formatBitrate(data.bitrate) + ' | ' + - this._formatTime( - (data.total - data.loaded) * 8 / data.bitrate - ) + ' | ' + - this._formatPercentage( - data.loaded / data.total - ) + ' | ' + - this._formatFileSize(data.loaded) + ' / ' + - this._formatFileSize(data.total); - }, - - _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, - dfd = $.Deferred(); - return ((loadImage && loadImage( - file, - function (img) { - node.append(img); - that._forceReflow(node); - that._transition(node).done(function () { - dfd.resolveWith(node); - }); - if (!$.contains(document.body, node[0])) { - // If the element is not part of the DOM, - // transition events are not triggered, - // so we have to resolve manually: - dfd.resolveWith(node); - } - }, - { - maxWidth: options.previewMaxWidth, - maxHeight: options.previewMaxHeight, - canvas: options.previewAsCanvas - } - )) || dfd.resolveWith(node)) && dfd; - }, - - _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 dfd = $.Deferred(); - that._renderPreview(file, $(element)).done( - function () { - dfd.resolveWith(that); - } - ); - return dfd.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) { - return $.support.transition && node.length && - node[0].offsetWidth; - }, - - _transition: function (node) { - var dfd = $.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); - dfd.resolveWith(node); - } - } - ).toggleClass('in'); - } else { - node.toggleClass('in'); - dfd.resolveWith(node); - } - return dfd; - }, - - _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 (!$.blueimpFP) { - this._processingQueue = $.Deferred().resolveWith(this).promise(); - this.process = 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); - } - - }); - -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/jquery.fileupload.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,968 +0,0 @@ -/* - * jQuery File Upload Plugin 5.12 - * 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, - // Interval in milliseconds to calculate and trigger progress events: - progressInterval: 100, - // Interval in milliseconds to calculate progress bitrate: - bitrateInterval: 500, - - // 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' - ], - - _BitrateTimer: function () { - this.timestamp = +(new Date()); - this.loaded = 0; - this.bitrate = 0; - this.getBitrate = function (now, loaded, interval) { - var timeDiff = now - this.timestamp; - if (!this.bitrate || !interval || timeDiff > interval) { - this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; - this.loaded = loaded; - this.timestamp = now; - } - return this.bitrate; - }; - }, - - _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); - } - if ($.isArray(options.formData)) { - return options.formData; - } - 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 now = +(new Date()), - total, - loaded; - if (data._time && data.progressInterval && - (now - data._time < data.progressInterval) && - e.loaded !== e.total) { - return; - } - data._time = now; - 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; - data.bitrate = data._bitrateTimer.getBitrate( - now, - loaded, - data.bitrateInterval - ); - // 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, - bitrate: this._bitrateTimer.getBitrate( - now, - this._loaded, - data.bitrateInterval - ) - }); - } - }, - - _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'); - // Set timer for global bitrate progress calculation: - this._bitrateTimer = new this._BitrateTimer(); - } - 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; - this._bitrateTimer = null; - } - }, - - _onSend: function (e, data) { - var that = this, - jqXHR, - slot, - pipe, - options = that._getAJAXSettings(data), - send = function (resolve, args) { - that._sending += 1; - // Set timer for bitrate progress calculation: - options._bitrateTimer = new that._BitrateTimer(); - 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; - } - }, - - _getFileInputFiles: function (fileInput) { - fileInput = $(fileInput); - var files = $.each($.makeArray(fileInput.prop('files')), this._normalizeFile), - value; - if (!files.length) { - value = fileInput.prop('value'); - if (!value) { - return []; - } - // 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: - files = [{name: value.replace(/^.*\\/, '')}]; - } - return files; - }, - - _onChange: function (e) { - var that = e.data.fileupload, - data = { - fileInput: $(e.target), - form: $(e.target.form) - }; - data.files = that._getFileInputFiles(data.fileInput); - 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 = '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; - // Initialize options set via HTML5 data-attributes: - $.extend(options, $(this.element[0].cloneNode(false)).data()); - 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; - } - if (data.fileInput && !data.files) { - data.files = this._getFileInputFiles(data.fileInput); - } else { - 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) { - if (data.fileInput && !data.files) { - data.files = this._getFileInputFiles(data.fileInput); - } else { - data.files = $.each($.makeArray(data.files), this._normalizeFile); - } - if (data.files.length) { - return this._onSend(null, data); - } - } - return this._getXHRPromise(false, data && data.context); - } - - }); - -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/jquery.iframe-transport.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * 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()); - } - } - }); - -}));
--- a/PalanthirExplorer/libs/jquery-file-upload/js/locale.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * jQuery File Upload Plugin Localization Example 6.5.1 - * 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 - */ - -/*global window */ - -window.locale = { - "fileupload": { - "errors": { - "maxFileSize": "File is too big", - "minFileSize": "File is too small", - "acceptFileTypes": "Filetype not allowed", - "maxNumberOfFiles": "Max number of files exceeded", - "uploadedBytes": "Uploaded bytes exceed file size", - "emptyResult": "Empty file upload result" - }, - "error": "Error", - "start": "Start", - "cancel": "Cancel", - "destroy": "Delete" - } -};
--- a/PalanthirExplorer/libs/jquery-file-upload/js/vendor/jquery.ui.widget.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/* - * jQuery UI Widget 1.8.18+amd - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Widget - */ - -(function (factory) { - if (typeof define === "function" && define.amd) { - // Register as an anonymous AMD module: - define(["jquery"], factory); - } else { - // Browser globals: - factory(jQuery); - } -}(function( $, undefined ) { - -// jQuery 1.4+ -if ( $.cleanData ) { - var _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 ); - }; -} else { - var _remove = $.fn.remove; - $.fn.remove = function( selector, keepData ) { - return this.each(function() { - if ( !keepData ) { - if ( !selector || $.filter( selector, [ this ] ).length ) { - $( "*", this ).add( [ this ] ).each(function() { - try { - $( this ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - }); - } - } - return _remove.call( $(this), selector, keepData ); - }); - }; -} - -$.widget = function( name, base, prototype ) { - var namespace = name.split( "." )[ 0 ], - fullName; - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName ] = function( elem ) { - return !!$.data( elem, name ); - }; - - $[ namespace ] = $[ namespace ] || {}; - $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without initializing for simple inheritance - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - - var 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 -// $.each( basePrototype, function( key, val ) { -// if ( $.isPlainObject(val) ) { -// basePrototype[ key ] = $.extend( {}, val ); -// } -// }); - basePrototype.options = $.extend( true, {}, basePrototype.options ); - $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { - namespace: namespace, - widgetName: name, - widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, - widgetBaseClass: fullName - }, prototype ); - - $.widget.bridge( name, $[ namespace ][ name ] ); -}; - -$.widget.bridge = function( name, object ) { - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = Array.prototype.slice.call( arguments, 1 ), - returnValue = this; - - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.extend.apply( null, [ true, options ].concat(args) ) : - options; - - // prevent calls to internal methods - if ( isMethodCall && options.charAt( 0 ) === "_" ) { - return returnValue; - } - - if ( isMethodCall ) { - this.each(function() { - var instance = $.data( this, name ), - methodValue = instance && $.isFunction( instance[options] ) ? - instance[ options ].apply( instance, args ) : - instance; - // TODO: add this back in 1.9 and use $.error() (see #5972) -// if ( !instance ) { -// throw "cannot call methods on " + name + " prior to initialization; " + -// "attempted to call method '" + options + "'"; -// } -// if ( !$.isFunction( instance[options] ) ) { -// throw "no such method '" + options + "' for " + name + " widget instance"; -// } -// var methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue; - return false; - } - }); - } else { - this.each(function() { - var instance = $.data( this, name ); - if ( instance ) { - instance.option( options || {} )._init(); - } else { - $.data( this, name, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( options, element ) { - // allow instantiation without initializing for simple inheritance - if ( arguments.length ) { - this._createWidget( options, element ); - } -}; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - options: { - disabled: false - }, - _createWidget: function( options, element ) { - // $.widget.bridge stores the plugin instance, but we do it anyway - // so that it's stored even before the _create function runs - $.data( element, this.widgetName, this ); - this.element = $( element ); - this.options = $.extend( true, {}, - this.options, - this._getCreateOptions(), - options ); - - var self = this; - this.element.bind( "remove." + this.widgetName, function() { - self.destroy(); - }); - - this._create(); - this._trigger( "create" ); - this._init(); - }, - _getCreateOptions: function() { - return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; - }, - _create: function() {}, - _init: function() {}, - - destroy: function() { - this.element - .unbind( "." + this.widgetName ) - .removeData( this.widgetName ); - this.widget() - .unbind( "." + this.widgetName ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetBaseClass + "-disabled " + - "ui-state-disabled" ); - }, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.extend( {}, this.options ); - } - - if (typeof key === "string" ) { - if ( value === undefined ) { - return this.options[ key ]; - } - options = {}; - options[ key ] = value; - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var self = this; - $.each( options, function( key, value ) { - self._setOption( key, value ); - }); - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - [ value ? "addClass" : "removeClass"]( - this.widgetBaseClass + "-disabled" + " " + - "ui-state-disabled" ) - .attr( "aria-disabled", value ); - } - - return this; - }, - - enable: function() { - return this._setOption( "disabled", false ); - }, - disable: function() { - return this._setOption( "disabled", true ); - }, - - _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.call( this.element[0], event, data ) === false || - event.isDefaultPrevented() ); - } -}; - -}));
--- a/PalanthirExplorer/libs/jquery.blockUI.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,499 +0,0 @@ -/*! - * jQuery blockUI plugin - * Version 2.39 (23-MAY-2011) - * @requires jQuery v1.2.3 or later - * - * Examples at: http://malsup.com/jquery/block/ - * Copyright (c) 2007-2010 M. Alsup - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Thanks to Amir-Hossein Sobhi for some excellent contributions! - */ - -;(function($) { - -if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) { - alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery); - return; -} - -$.fn._fadeIn = $.fn.fadeIn; - -var noOp = function() {}; - -// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle -// retarded userAgent strings on Vista) -var mode = document.documentMode || 0; -var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8); -var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode; - -// global $ methods for blocking/unblocking the entire page -$.blockUI = function(opts) { install(window, opts); }; -$.unblockUI = function(opts) { remove(window, opts); }; - -// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) -$.growlUI = function(title, message, timeout, onClose) { - var $m = $('<div class="growlUI"></div>'); - if (title) $m.append('<h1>'+title+'</h1>'); - if (message) $m.append('<h2>'+message+'</h2>'); - if (timeout == undefined) timeout = 3000; - $.blockUI({ - message: $m, fadeIn: 700, fadeOut: 1000, centerY: false, - timeout: timeout, showOverlay: false, - onUnblock: onClose, - css: $.blockUI.defaults.growlCSS - }); -}; - -// plugin method for blocking element content -$.fn.block = function(opts) { - return this.unblock({ fadeOut: 0 }).each(function() { - if ($.css(this,'position') == 'static') - this.style.position = 'relative'; - if ($.browser.msie) - this.style.zoom = 1; // force 'hasLayout' - install(this, opts); - }); -}; - -// plugin method for unblocking element content -$.fn.unblock = function(opts) { - return this.each(function() { - remove(this, opts); - }); -}; - -$.blockUI.version = 2.39; // 2nd generation blocking at no extra cost! - -// override these in your code to change the default behavior and style -$.blockUI.defaults = { - // message displayed when blocking (use null for no message) - message: '<h1>Please wait...</h1>', - - title: null, // title string; only used when theme == true - draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) - - theme: false, // set to true to use with jQuery UI themes - - // styles for the message when blocking; if you wish to disable - // these and use an external stylesheet then do this in your code: - // $.blockUI.defaults.css = {}; - css: { - padding: 0, - margin: 0, - width: '30%', - top: '40%', - left: '35%', - textAlign: 'center', - color: '#000', - border: '3px solid #aaa', - backgroundColor:'#fff', - cursor: 'wait' - }, - - // minimal style set used when themes are used - themedCSS: { - width: '30%', - top: '40%', - left: '35%' - }, - - // styles for the overlay - overlayCSS: { - backgroundColor: '#000', - opacity: 0.6, - cursor: 'wait' - }, - - // styles applied when using $.growlUI - growlCSS: { - width: '350px', - top: '10px', - left: '', - right: '10px', - border: 'none', - padding: '5px', - opacity: 0.6, - cursor: 'default', - color: '#fff', - backgroundColor: '#000', - '-webkit-border-radius': '10px', - '-moz-border-radius': '10px', - 'border-radius': '10px' - }, - - // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w - // (hat tip to Jorge H. N. de Vasconcelos) - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', - - // force usage of iframe in non-IE browsers (handy for blocking applets) - forceIframe: false, - - // z-index for the blocking overlay - baseZ: 1000, - - // set these to true to have the message automatically centered - centerX: true, // <-- only effects element blocking (page block controlled via css above) - centerY: true, - - // allow body element to be stetched in ie6; this makes blocking look better - // on "short" pages. disable if you wish to prevent changes to the body height - allowBodyStretch: true, - - // enable if you want key and mouse events to be disabled for content that is blocked - bindEvents: true, - - // be default blockUI will supress tab navigation from leaving blocking content - // (if bindEvents is true) - constrainTabKey: true, - - // fadeIn time in millis; set to 0 to disable fadeIn on block - fadeIn: 200, - - // fadeOut time in millis; set to 0 to disable fadeOut on unblock - fadeOut: 400, - - // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock - timeout: 0, - - // disable if you don't want to show the overlay - showOverlay: true, - - // if true, focus will be placed in the first available input field when - // page blocking - focusInput: true, - - // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) - applyPlatformOpacityRules: true, - - // callback method invoked when fadeIn has completed and blocking message is visible - onBlock: null, - - // callback method invoked when unblocking has completed; the callback is - // passed the element that has been unblocked (which is the window object for page - // blocks) and the options that were passed to the unblock call: - // onUnblock(element, options) - onUnblock: null, - - // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 - quirksmodeOffsetHack: 4, - - // class name of the message block - blockMsgClass: 'blockMsg' -}; - -// private data and functions follow... - -var pageBlock = null; -var pageBlockEls = []; - -function install(el, opts) { - var full = (el == window); - var msg = opts && opts.message !== undefined ? opts.message : undefined; - opts = $.extend({}, $.blockUI.defaults, opts || {}); - opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); - var css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); - var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); - msg = msg === undefined ? opts.message : msg; - - // remove the current block (if there is one) - if (full && pageBlock) - remove(window, {fadeOut:0}); - - // if an existing element is being used as the blocking content then we capture - // its current place in the DOM (and current display style) so we can restore - // it when we unblock - if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { - var node = msg.jquery ? msg[0] : msg; - var data = {}; - $(el).data('blockUI.history', data); - data.el = node; - data.parent = node.parentNode; - data.display = node.style.display; - data.position = node.style.position; - if (data.parent) - data.parent.removeChild(node); - } - - $(el).data('blockUI.onUnblock', opts.onUnblock); - var z = opts.baseZ; - - // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; - // layer1 is the iframe layer which is used to supress bleed through of underlying content - // layer2 is the overlay layer which has opacity and a wait cursor (by default) - // layer3 is the message content that is displayed while blocking - - var lyr1 = ($.browser.msie || opts.forceIframe) - ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>') - : $('<div class="blockUI" style="display:none"></div>'); - - var lyr2 = opts.theme - ? $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>') - : $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'); - - var lyr3, s; - if (opts.theme && full) { - s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">' + - '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + - '<div class="ui-widget-content ui-dialog-content"></div>' + - '</div>'; - } - else if (opts.theme) { - s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">' + - '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + - '<div class="ui-widget-content ui-dialog-content"></div>' + - '</div>'; - } - else if (full) { - s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>'; - } - else { - s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>'; - } - lyr3 = $(s); - - // if we have a message, style it - if (msg) { - if (opts.theme) { - lyr3.css(themedCSS); - lyr3.addClass('ui-widget-content'); - } - else - lyr3.css(css); - } - - // style the overlay - if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))) - lyr2.css(opts.overlayCSS); - lyr2.css('position', full ? 'fixed' : 'absolute'); - - // make iframe layer transparent in IE - if ($.browser.msie || opts.forceIframe) - lyr1.css('opacity',0.0); - - //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); - var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); - $.each(layers, function() { - this.appendTo($par); - }); - - if (opts.theme && opts.draggable && $.fn.draggable) { - lyr3.draggable({ - handle: '.ui-dialog-titlebar', - cancel: 'li' - }); - } - - // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) - var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0); - if (ie6 || expr) { - // give body 100% height - if (full && opts.allowBodyStretch && $.boxModel) - $('html,body').css('height','100%'); - - // fix ie6 issue when blocked element has a border width - if ((ie6 || !$.boxModel) && !full) { - var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); - var fixT = t ? '(0 - '+t+')' : 0; - var fixL = l ? '(0 - '+l+')' : 0; - } - - // simulate fixed position - $.each([lyr1,lyr2,lyr3], function(i,o) { - var s = o[0].style; - s.position = 'absolute'; - if (i < 2) { - full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"') - : s.setExpression('height','this.parentNode.offsetHeight + "px"'); - full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"') - : s.setExpression('width','this.parentNode.offsetWidth + "px"'); - if (fixL) s.setExpression('left', fixL); - if (fixT) s.setExpression('top', fixT); - } - else if (opts.centerY) { - if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); - s.marginTop = 0; - } - else if (!opts.centerY && full) { - var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0; - var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; - s.setExpression('top',expression); - } - }); - } - - // show the message - if (msg) { - if (opts.theme) - lyr3.find('.ui-widget-content').append(msg); - else - lyr3.append(msg); - if (msg.jquery || msg.nodeType) - $(msg).show(); - } - - if (($.browser.msie || opts.forceIframe) && opts.showOverlay) - lyr1.show(); // opacity is zero - if (opts.fadeIn) { - var cb = opts.onBlock ? opts.onBlock : noOp; - var cb1 = (opts.showOverlay && !msg) ? cb : noOp; - var cb2 = msg ? cb : noOp; - if (opts.showOverlay) - lyr2._fadeIn(opts.fadeIn, cb1); - if (msg) - lyr3._fadeIn(opts.fadeIn, cb2); - } - else { - if (opts.showOverlay) - lyr2.show(); - if (msg) - lyr3.show(); - if (opts.onBlock) - opts.onBlock(); - } - - // bind key and mouse events - bind(1, el, opts); - - if (full) { - pageBlock = lyr3[0]; - pageBlockEls = $(':input:enabled:visible',pageBlock); - if (opts.focusInput) - setTimeout(focus, 20); - } - else - center(lyr3[0], opts.centerX, opts.centerY); - - if (opts.timeout) { - // auto-unblock - var to = setTimeout(function() { - full ? $.unblockUI(opts) : $(el).unblock(opts); - }, opts.timeout); - $(el).data('blockUI.timeout', to); - } -}; - -// remove the block -function remove(el, opts) { - var full = (el == window); - var $el = $(el); - var data = $el.data('blockUI.history'); - var to = $el.data('blockUI.timeout'); - if (to) { - clearTimeout(to); - $el.removeData('blockUI.timeout'); - } - opts = $.extend({}, $.blockUI.defaults, opts || {}); - bind(0, el, opts); // unbind events - - if (opts.onUnblock === null) { - opts.onUnblock = $el.data('blockUI.onUnblock'); - $el.removeData('blockUI.onUnblock'); - } - - var els; - if (full) // crazy selector to handle odd field errors in ie6/7 - els = $('body').children().filter('.blockUI').add('body > .blockUI'); - else - els = $('.blockUI', el); - - if (full) - pageBlock = pageBlockEls = null; - - if (opts.fadeOut) { - els.fadeOut(opts.fadeOut); - setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut); - } - else - reset(els, data, opts, el); -}; - -// move blocking element back into the DOM where it started -function reset(els,data,opts,el) { - els.each(function(i,o) { - // remove via DOM calls so we don't lose event handlers - if (this.parentNode) - this.parentNode.removeChild(this); - }); - - if (data && data.el) { - data.el.style.display = data.display; - data.el.style.position = data.position; - if (data.parent) - data.parent.appendChild(data.el); - $(el).removeData('blockUI.history'); - } - - if (typeof opts.onUnblock == 'function') - opts.onUnblock(el,opts); -}; - -// bind/unbind the handler -function bind(b, el, opts) { - var full = el == window, $el = $(el); - - // don't bother unbinding if there is nothing to unbind - if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) - return; - if (!full) - $el.data('blockUI.isBlocked', b); - - // don't bind events when overlay is not in use or if bindEvents is false - if (!opts.bindEvents || (b && !opts.showOverlay)) - return; - - // bind anchors and inputs for mouse and key events - var events = 'mousedown mouseup keydown keypress'; - b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler); - -// former impl... -// var $e = $('a,:input'); -// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); -}; - -// event handler to suppress keyboard/mouse events when blocking -function handler(e) { - // allow tab navigation (conditionally) - if (e.keyCode && e.keyCode == 9) { - if (pageBlock && e.data.constrainTabKey) { - var els = pageBlockEls; - var fwd = !e.shiftKey && e.target === els[els.length-1]; - var back = e.shiftKey && e.target === els[0]; - if (fwd || back) { - setTimeout(function(){focus(back)},10); - return false; - } - } - } - var opts = e.data; - // allow events within the message content - if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0) - return true; - - // allow events for content that is not being blocked - return $(e.target).parents().children().filter('div.blockUI').length == 0; -}; - -function focus(back) { - if (!pageBlockEls) - return; - var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; - if (e) - e.focus(); -}; - -function center(el, x, y) { - var p = el.parentNode, s = el.style; - var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); - var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); - if (x) s.left = l > 0 ? (l+'px') : '0'; - if (y) s.top = t > 0 ? (t+'px') : '0'; -}; - -function sz(el, p) { - return parseInt($.css(el,p))||0; -}; - -})(jQuery);
--- a/PalanthirExplorer/libs/jquery.mobile-1.1.0.min.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ -.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted}.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- a/PalanthirExplorer/libs/jquery.mobile-1.1.0.min.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ -(function(D,s,k){typeof define==="function"&&define.amd?define(["jquery"],function(a){k(a,D,s);return a.mobile}):k(D.jQuery,D,s)})(this,document,function(D,s,k){(function(a,c,b,e){function f(a){for(;a&&typeof a.originalEvent!=="undefined";)a=a.originalEvent;return a}function d(b){for(var d={},f,g;b;){f=a.data(b,t);for(g in f)if(f[g])d[g]=d.hasVirtualBinding=true;b=b.parentNode}return d}function g(){y&&(clearTimeout(y),y=0);y=setTimeout(function(){F=y=0;C.length=0;z=false;G=true},a.vmouse.resetTimerDuration)} -function h(b,d,g){var c,h;if(!(h=g&&g[b])){if(g=!g)a:{for(g=d.target;g;){if((h=a.data(g,t))&&(!b||h[b]))break a;g=g.parentNode}g=null}h=g}if(h){c=d;var g=c.type,z,j;c=a.Event(c);c.type=b;h=c.originalEvent;z=a.event.props;g.search(/^(mouse|click)/)>-1&&(z=w);if(h)for(j=z.length;j;)b=z[--j],c[b]=h[b];if(g.search(/mouse(down|up)|click/)>-1&&!c.which)c.which=1;if(g.search(/^touch/)!==-1&&(b=f(h),g=b.touches,b=b.changedTouches,g=g&&g.length?g[0]:b&&b.length?b[0]:e))for(h=0,len=u.length;h<len;h++)b=u[h], -c[b]=g[b];a(d.target).trigger(c)}return c}function j(b){var d=a.data(b.target,x);if(!z&&(!F||F!==d))if(d=h("v"+b.type,b))d.isDefaultPrevented()&&b.preventDefault(),d.isPropagationStopped()&&b.stopPropagation(),d.isImmediatePropagationStopped()&&b.stopImmediatePropagation()}function o(b){var g=f(b).touches,c;if(g&&g.length===1&&(c=b.target,g=d(c),g.hasVirtualBinding))F=L++,a.data(c,x,F),y&&(clearTimeout(y),y=0),A=G=false,c=f(b).touches[0],s=c.pageX,E=c.pageY,h("vmouseover",b,g),h("vmousedown",b,g)} -function m(a){G||(A||h("vmousecancel",a,d(a.target)),A=true,g())}function p(b){if(!G){var c=f(b).touches[0],e=A,z=a.vmouse.moveDistanceThreshold;A=A||Math.abs(c.pageX-s)>z||Math.abs(c.pageY-E)>z;flags=d(b.target);A&&!e&&h("vmousecancel",b,flags);h("vmousemove",b,flags);g()}}function l(a){if(!G){G=true;var b=d(a.target),c;h("vmouseup",a,b);if(!A&&(c=h("vclick",a,b))&&c.isDefaultPrevented())c=f(a).changedTouches[0],C.push({touchID:F,x:c.clientX,y:c.clientY}),z=true;h("vmouseout",a,b);A=false;g()}}function r(b){var b= -a.data(b,t),d;if(b)for(d in b)if(b[d])return true;return false}function n(){}function k(b){var d=b.substr(1);return{setup:function(){r(this)||a.data(this,t,{});a.data(this,t)[b]=true;v[b]=(v[b]||0)+1;v[b]===1&&H.bind(d,j);a(this).bind(d,n);if(K)v.touchstart=(v.touchstart||0)+1,v.touchstart===1&&H.bind("touchstart",o).bind("touchend",l).bind("touchmove",p).bind("scroll",m)},teardown:function(){--v[b];v[b]||H.unbind(d,j);K&&(--v.touchstart,v.touchstart||H.unbind("touchstart",o).unbind("touchmove",p).unbind("touchend", -l).unbind("scroll",m));var f=a(this),g=a.data(this,t);g&&(g[b]=false);f.unbind(d,n);r(this)||f.removeData(t)}}}var t="virtualMouseBindings",x="virtualTouchID",c="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),u="clientX clientY pageX pageY screenX screenY".split(" "),w=a.event.props.concat(a.event.mouseHooks?a.event.mouseHooks.props:[]),v={},y=0,s=0,E=0,A=false,C=[],z=false,G=false,K="addEventListener"in b,H=a(b),L=1,F=0;a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10, -resetTimerDuration:1500};for(var I=0;I<c.length;I++)a.event.special[c[I]]=k(c[I]);K&&b.addEventListener("click",function(b){var d=C.length,f=b.target,g,c,e,h,z;if(d){g=b.clientX;c=b.clientY;threshold=a.vmouse.clickDistanceThreshold;for(e=f;e;){for(h=0;h<d;h++)if(z=C[h],e===f&&Math.abs(z.x-g)<threshold&&Math.abs(z.y-c)<threshold||a.data(e,x)===z.touchID){b.preventDefault();b.stopPropagation();return}e=e.parentNode}}},true)})(jQuery,s,k);(function(a,c,b){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/, -"$1")}var f="hashchange",d=k,g,h=a.event.special,j=d.documentMode,o="on"+f in c&&(j===b||j>7);a.fn[f]=function(a){return a?this.bind(f,a):this.trigger(f)};a.fn[f].delay=50;h[f]=a.extend(h[f],{setup:function(){if(o)return false;a(g.start)},teardown:function(){if(o)return false;a(g.stop)}});g=function(){function g(){var b=e(),d=t(r);if(b!==r)k(r=b,d),a(c).trigger(f);else if(d!==r)location.href=location.href.replace(/#.*/,"")+d;j=setTimeout(g,a.fn[f].delay)}var h={},j,r=e(),n=function(a){return a},k= -n,t=n;h.start=function(){j||g()};h.stop=function(){j&&clearTimeout(j);j=b};a.browser.msie&&!o&&function(){var b,c;h.start=function(){if(!b)c=(c=a.fn[f].src)&&c+e(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){c||k(e());g()}).attr("src",c||"javascript:0").insertAfter("body")[0].contentWindow,d.onpropertychange=function(){try{if(event.propertyName==="title")b.document.title=d.title}catch(a){}}};h.stop=n;t=function(){return e(b.location.href)};k=function(g,c){var e=b.document, -h=a.fn[f].domain;if(g!==c)e.title=d.title,e.open(),h&&e.write('<script>document.domain="'+h+'"<\/script>'),e.close(),b.location.hash=g}}();return h}()})(jQuery,this);(function(a,c){if(a.cleanData){var b=a.cleanData;a.cleanData=function(f){for(var d=0,g;(g=f[d])!=null;d++)a(g).triggerHandler("remove");b(f)}}else{var e=a.fn.remove;a.fn.remove=function(b,d){return this.each(function(){d||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){a(this).triggerHandler("remove")});return e.call(a(this), -b,d)})}}a.widget=function(b,d,g){var c=b.split(".")[0],e,b=b.split(".")[1];e=c+"-"+b;if(!g)g=d,d=a.Widget;a.expr[":"][e]=function(d){return!!a.data(d,b)};a[c]=a[c]||{};a[c][b]=function(a,b){arguments.length&&this._createWidget(a,b)};d=new d;d.options=a.extend(true,{},d.options);a[c][b].prototype=a.extend(true,d,{namespace:c,widgetName:b,widgetEventPrefix:a[c][b].prototype.widgetEventPrefix||b,widgetBaseClass:e},g);a.widget.bridge(b,a[c][b])};a.widget.bridge=function(b,d){a.fn[b]=function(g){var e= -typeof g==="string",j=Array.prototype.slice.call(arguments,1),o=this,g=!e&&j.length?a.extend.apply(null,[true,g].concat(j)):g;if(e&&g.charAt(0)==="_")return o;e?this.each(function(){var d=a.data(this,b);if(!d)throw"cannot call methods on "+b+" prior to initialization; attempted to call method '"+g+"'";if(!a.isFunction(d[g]))throw"no such method '"+g+"' for "+b+" widget instance";var e=d[g].apply(d,j);if(e!==d&&e!==c)return o=e,false}):this.each(function(){var c=a.data(this,b);c?c.option(g||{})._init(): -a.data(this,b,new d(g,this))});return o}};a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)};a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(b,d){a.data(d,this.widgetName,this);this.element=a(d);this.options=a.extend(true,{},this.options,this._getCreateOptions(),b);var g=this;this.element.bind("remove."+this.widgetName,function(){g.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){var b= -{};a.metadata&&(b=a.metadata.get(element)[this.widgetName]);return b},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(b,d){var g=b;if(arguments.length===0)return a.extend({},this.options);if(typeof b==="string"){if(d===c)return this.options[b]; -g={};g[b]=d}this._setOptions(g);return this},_setOptions:function(b){var d=this;a.each(b,function(a,b){d._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b;a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(b,d,g){var c=this.options[b],d=a.Event(d); -d.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase();g=g||{};if(d.originalEvent)for(var b=a.event.props.length,e;b;)e=a.event.props[--b],d[e]=d.originalEvent[e];this.element.trigger(d,g);return!(a.isFunction(c)&&c.call(this.element[0],d,g)===false||d.isDefaultPrevented())}}})(jQuery);(function(a,c){a.widget("mobile.widget",{_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments);this._trigger("init")},_getCreateOptions:function(){var b=this.element, -e={};a.each(this.options,function(a){var d=b.jqmData(a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()}));d!==c&&(e[a]=d)});return e},enhanceWithin:function(b,c){this.enhance(a(this.options.initSelector,a(b)),c)},enhance:function(b,c){var f,d=a(b),d=a.mobile.enhanceable(d);c&&d.length&&(f=(f=a.mobile.closestPageData(d))&&f.keepNativeSelector()||"",d=d.not(f));d[this.widgetName]()},raise:function(a){throw"Widget ["+this.widgetName+"]: "+a;}})})(jQuery);(function(a,c){var b={};a.mobile=a.extend({}, -{version:"1.1.0",ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:true,hashListeningEnabled:true,linkBindingEnabled:true,defaultPageTransition:"fade",maxTransitionWidth:false,minScrollBack:250,touchOverflowEnabled:false,defaultDialogTransition:"pop",loadingMessage:"loading",pageLoadErrorMessage:"Error Loading Page",loadingMessageTextVisible:false,loadingMessageTheme:"a",pageLoadErrorMessageTheme:"e",autoInitializePage:true, -pushStateEnabled:true,ignoreContentEnabled:false,orientationChangeEnabled:true,buttonMarkup:{hoverDelay:200},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,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,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},silentScroll:function(b){if(a.type(b)!== -"number")b=a.mobile.defaultHomeScroll;a.event.special.scrollstart.enabled=false;setTimeout(function(){c.scrollTo(0,b);a(k).trigger("silentscroll",{x:0,y:b})},20);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},nsNormalizeDict:b,nsNormalize:function(d){return!d?void 0:b[d]||(b[d]=a.camelCase(a.mobile.ns+d))},getInheritedTheme:function(a,b){for(var c=a[0],e="",f=/ui-(bar|body|overlay)-([a-z])\b/,m,p;c;){m=c.className||"";if((p=f.exec(m))&&(e=p[2]))break;c=c.parentNode}return e|| -b||"a"},closestPageData:function(a){return a.closest(':jqmData(role="page"), :jqmData(role="dialog")').data("page")},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;for(var e=b.length,f=a(),o,m,p,l=0;l<e;l++){m=b.eq(l);p=false;for(o=b[l];o;){if((o.getAttribute?o.getAttribute("data-"+a.mobile.ns+c):"")==="false"){p=true;break}o=o.parentNode}p||(f=f.add(m))}return f}}, -a.mobile);a.fn.jqmData=function(b,c){var f;typeof b!="undefined"&&(b&&(b=a.mobile.nsNormalize(b)),f=this.data.apply(this,arguments.length<2?[b]:[b,c]));return f};a.jqmData=function(b,c,f){var e;typeof c!="undefined"&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,f));return e};a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))};a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))};a.fn.removeWithDependents=function(){a.removeWithDependents(this)};a.removeWithDependents= -function(b){b=a(b);(b.jqmData("dependents")||a()).remove();b.remove()};a.fn.addDependents=function(b){a.addDependents(a(this),b)};a.addDependents=function(b,c){var f=a(b).jqmData("dependents")||a();a(b).jqmData("dependents",a.merge(f,c))};a.fn.getEncodedText=function(){return a("<div/>").text(a(this).text()).html()};a.fn.jqmEnhanceable=function(){return a.mobile.enhanceable(this)};a.fn.jqmHijackable=function(){return a.mobile.hijackable(this)};var e=a.find,f=/:jqmData\(([^)]*)\)/g;a.find=function(b, -c,h,j){b=b.replace(f,"[data-"+(a.mobile.ns||"")+"$1]");return e.call(this,b,c,h,j)};a.extend(a.find,e);a.find.matches=function(b,c){return a.find(b,null,null,c)};a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}})(jQuery,this);(function(a){a(s);var c=a("html");a.mobile.media=function(){var b={},e=a("<div id='jquery-mediatest'>"),f=a("<body>").append(e);return function(a){if(!(a in b)){var g=k.createElement("style"),h="@media "+a+" { #jquery-mediatest { position:absolute; } }"; -g.type="text/css";g.styleSheet?g.styleSheet.cssText=h:g.appendChild(k.createTextNode(h));c.prepend(f).prepend(g);b[a]=e.css("position")==="absolute";f.add(g).remove()}return b[a]}}()})(jQuery);(function(a,c){function b(a){var b=a.charAt(0).toUpperCase()+a.substr(1),a=(a+" "+g.join(b+" ")+b).split(" "),f;for(f in a)if(d[a[f]]!==c)return true}function e(a,b,c){var d=k.createElement("div"),c=c?[c]:g,f;for(i=0;i<c.length;i++){var e=c[i],h="-"+e.charAt(0).toLowerCase()+e.substr(1)+"-"+a+": "+b+";",e=e.charAt(0).toUpperCase()+ -e.substr(1)+(a.charAt(0).toUpperCase()+a.substr(1));d.setAttribute("style",h);d.style[e]&&(f=true)}return!!f}var f=a("<body>").prependTo("html"),d=f[0].style,g=["Webkit","Moz","O"],h="palmGetResource"in s,j=s.operamini&&{}.toString.call(s.operamini)==="[object OperaMini]",o=s.blackberry;a.extend(a.mobile,{browser:{}});a.mobile.browser.ie=function(){for(var a=3,b=k.createElement("div"),c=b.all||[];b.innerHTML="<\!--[if gt IE "+ ++a+"]><br><![endif]--\>",c[0];);return a>4?a:!a}();a.extend(a.support, -{orientation:"orientation"in s&&"onorientationchange"in s,touch:"ontouchend"in k,cssTransitions:"WebKitTransitionEvent"in s||e("transition","height 100ms linear"),pushState:"pushState"in history&&"replaceState"in history,mediaquery:a.mobile.media("only all"),cssPseudoElement:!!b("content"),touchOverflow:!!b("overflowScrolling"),cssTransform3d:e("perspective","10px","moz")||a.mobile.media("(-"+g.join("-transform-3d),(-")+"-transform-3d),(transform-3d)"),boxShadow:!!b("boxShadow")&&!o,scrollTop:("pageXOffset"in -s||"scrollTop"in k.documentElement||"scrollTop"in f[0])&&!h&&!j,dynamicBaseTag:function(){var b=location.protocol+"//"+location.host+location.pathname+"ui-dir/",c=a("head base"),d=null,e="",g;c.length?e=c.attr("href"):c=d=a("<base>",{href:b}).appendTo("head");g=a("<a href='testurl' />").prependTo(f)[0].href;c[0].href=e||location.pathname;d&&d.remove();return g.indexOf(b)===0}()});f.remove();h=function(){var a=s.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")> --1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}();a.mobile.gradeA=function(){return a.support.mediaquery||a.mobile.browser.ie&&a.mobile.browser.ie>=7};a.mobile.ajaxBlacklist=s.blackberry&&!s.WebKitPoint||j||h;h&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")});a.support.boxShadow||a("html").addClass("ui-mobile-nosupport-boxshadow")})(jQuery);(function(a,c,b){function e(b,c,d){var f=d.type;d.type=c;a.event.handle.call(b, -d);d.type=f}a.each("touchstart touchmove touchend orientationchange throttledresize tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(b,c){a.fn[c]=function(a){return a?this.bind(c,a):this.trigger(c)};a.attrFn[c]=true});var f=a.support.touch,d=f?"touchstart":"mousedown",g=f?"touchend":"mouseup",h=f?"touchmove":"mousemove";a.event.special.scrollstart={enabled:true,setup:function(){function b(a,f){d=f;e(c,d?"scrollstart":"scrollstop",a)}var c=this,d,f;a(c).bind("touchmove scroll", -function(c){a.event.special.scrollstart.enabled&&(d||b(c,true),clearTimeout(f),f=setTimeout(function(){b(c,false)},50))})}};a.event.special.tap={setup:function(){var b=this,c=a(b);c.bind("vmousedown",function(d){function f(){clearTimeout(q)}function g(){f();c.unbind("vclick",h).unbind("vmouseup",f);a(k).unbind("vmousecancel",g)}function h(a){g();n==a.target&&e(b,"tap",a)}if(d.which&&d.which!==1)return false;var n=d.target,q;c.bind("vmouseup",f).bind("vclick",h);a(k).bind("vmousecancel",g);q=setTimeout(function(){e(b, -"taphold",a.Event("taphold",{target:n}))},750)})}};a.event.special.swipe={scrollSupressionThreshold:10,durationThreshold:1E3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,setup:function(){var c=a(this);c.bind(d,function(d){function f(b){if(l){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b;k={time:(new Date).getTime(),coords:[c.pageX,c.pageY]};Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault()}}var e=d.originalEvent.touches? -d.originalEvent.touches[0]:d,l={time:(new Date).getTime(),coords:[e.pageX,e.pageY],origin:a(d.target)},k;c.bind(h,f).one(g,function(){c.unbind(h,f);l&&k&&k.time-l.time<a.event.special.swipe.durationThreshold&&Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(l.coords[1]-k.coords[1])<a.event.special.swipe.verticalDistanceThreshold&&l.origin.trigger("swipe").trigger(l.coords[0]>k.coords[0]?"swipeleft":"swiperight");l=k=b})})}};(function(a,b){function c(){var a= -f();a!==e&&(e=a,d.trigger("orientationchange"))}var d=a(b),f,e,g,h,t={0:true,180:true};if(a.support.orientation&&(g=b.innerWidth||a(b).width(),h=b.innerHeight||a(b).height(),g=g>h&&g-h>50,h=t[b.orientation],g&&h||!g&&!h))t={"-90":true,90:true};a.event.special.orientationchange={setup:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;e=f();d.bind("throttledresize",c)},teardown:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;d.unbind("throttledresize", -c)},add:function(a){var b=a.handler;a.handler=function(a){a.orientation=f();return b.apply(this,arguments)}}};a.event.special.orientationchange.orientation=f=function(){var c=true,c=k.documentElement;return(c=a.support.orientation?t[b.orientation]:c&&c.clientWidth/c.clientHeight<1.1)?"portrait":"landscape"}})(jQuery,c);(function(){a.event.special.throttledresize={setup:function(){a(this).bind("resize",b)},teardown:function(){a(this).unbind("resize",b)}};var b=function(){f=(new Date).getTime();g=f- -c;g>=250?(c=f,a(this).trigger("throttledresize")):(d&&clearTimeout(d),d=setTimeout(b,250-g))},c=0,d,f,g})();a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe",swiperight:"swipe"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)}}})})(jQuery,this);(function(a){a.widget("mobile.page",a.mobile.widget,{options:{theme:"c",domCache:false,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){var a=this;if(a._trigger("beforecreate")=== -false)return false;a.element.attr("tabindex","0").addClass("ui-page ui-body-"+a.options.theme).bind("pagebeforehide",function(){a.removeContainerBackground()}).bind("pagebeforeshow",function(){a.setContainerBackground()})},removeContainerBackground:function(){a.mobile.pageContainer.removeClass("ui-overlay-"+a.mobile.getInheritedTheme(this.element.parent()))},setContainerBackground:function(c){this.options.theme&&a.mobile.pageContainer.addClass("ui-overlay-"+(c||this.options.theme))},keepNativeSelector:function(){var c= -this.options;return c.keepNative&&a.trim(c.keepNative)&&c.keepNative!==c.keepNativeDefault?[c.keepNative,c.keepNativeDefault].join(", "):c.keepNativeDefault}})})(jQuery);(function(a,c,b){var e=function(d){d===b&&(d=true);return function(b,f,e,o){var k=new a.Deferred,p=f?" reverse":"",l=a.mobile.urlHistory.getActive().lastScroll||a.mobile.defaultHomeScroll,r=a.mobile.getScreenHeight(),n=a.mobile.maxTransitionWidth!==false&&a(c).width()>a.mobile.maxTransitionWidth,q=!a.support.cssTransitions||n||!b|| -b==="none",t=function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+b)},x=function(){a.event.special.scrollstart.enabled=false;c.scrollTo(0,l);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},u=function(){o.removeClass(a.mobile.activePageClass+" out in reverse "+b).height("")},n=function(){o&&d&&u();e.addClass(a.mobile.activePageClass);a.mobile.focusPage(e);e.height(r+l);x();q||e.animationComplete(w);e.addClass(b+" in"+p);q&&w()},w=function(){d|| -o&&u();e.removeClass("out in reverse "+b).height("");t();a(c).scrollTop()!==l&&x();k.resolve(b,f,e,o,true)};t();o&&!q?(d?o.animationComplete(n):n(),o.height(r+a(c).scrollTop()).addClass(b+" out"+p)):n();return k.promise()}},f=e(),e=e(false);a.mobile.defaultTransitionHandler=f;a.mobile.transitionHandlers={"default":a.mobile.defaultTransitionHandler,sequential:f,simultaneous:e};a.mobile.transitionFallbacks={}})(jQuery,this);(function(a,c){function b(b){r&&(!r.closest(".ui-page-active").length||b)&& -r.removeClass(a.mobile.activeBtnClass);r=null}function e(){t=false;q.length>0&&a.mobile.changePage.apply(null,q.pop())}function f(b,c,d,f){c&&c.data("page")._trigger("beforehide",null,{nextPage:b});b.data("page")._trigger("beforeshow",null,{prevPage:c||a("")});a.mobile.hidePageLoadingMsg();d&&!a.support.cssTransform3d&&a.mobile.transitionFallbacks[d]&&(d=a.mobile.transitionFallbacks[d]);d=(a.mobile.transitionHandlers[d||"default"]||a.mobile.defaultTransitionHandler)(d,f,b,c);d.done(function(){c&& -c.data("page")._trigger("hide",null,{nextPage:b});b.data("page")._trigger("show",null,{prevPage:c||a("")})});return d}function d(){return s.innerHeight||a(s).height()}function g(){var b=a("."+a.mobile.activePageClass),c=parseFloat(b.css("padding-top")),f=parseFloat(b.css("padding-bottom"));b.css("min-height",d()-c-f)}function h(b,c){c&&b.attr("data-"+a.mobile.ns+"role",c);b.page()}function j(a){for(;a;){if(typeof a.nodeName==="string"&&a.nodeName.toLowerCase()=="a")break;a=a.parentNode}return a}function o(b){var b= -a(b).closest(".ui-page").jqmData("url"),c=v.hrefNoHash;if(!b||!l.isPath(b))b=c;return l.makeUrlAbsolute(b,c)}var m=a(s);a("html");var p=a("head"),l={urlParseRE:/^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,parseUrl:function(b){if(a.type(b)==="object")return b;b=l.urlParseRE.exec(b||"")||[];return{href:b[0]||"",hrefNoHash:b[1]||"",hrefNoSearch:b[2]||"",domain:b[3]||"", -protocol:b[4]||"",doubleSlash:b[5]||"",authority:b[6]||"",username:b[8]||"",password:b[9]||"",host:b[10]||"",hostname:b[11]||"",port:b[12]||"",pathname:b[13]||"",directory:b[14]||"",filename:b[15]||"",search:b[16]||"",hash:b[17]||""}},makePathAbsolute:function(a,b){if(a&&a.charAt(0)==="/")return a;for(var a=a||"",c=(b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"")?b.split("/"):[],d=a.split("/"),f=0;f<d.length;f++){var e=d[f];switch(e){case ".":break;case "..":c.length&&c.pop();break;default:c.push(e)}}return"/"+ -c.join("/")},isSameDomain:function(a,b){return l.parseUrl(a).domain===l.parseUrl(b).domain},isRelativeUrl:function(a){return l.parseUrl(a).protocol===""},isAbsoluteUrl:function(a){return l.parseUrl(a).protocol!==""},makeUrlAbsolute:function(a,b){if(!l.isRelativeUrl(a))return a;var c=l.parseUrl(a),d=l.parseUrl(b),f=c.protocol||d.protocol,e=c.protocol?c.doubleSlash:c.doubleSlash||d.doubleSlash,g=c.authority||d.authority,h=c.pathname!=="",j=l.makePathAbsolute(c.pathname||d.filename,d.pathname);return f+ -e+g+j+(c.search||!h&&d.search||"")+c.hash},addSearchParams:function(b,c){var d=l.parseUrl(b),f=typeof c==="object"?a.param(c):c,e=d.search||"?";return d.hrefNoSearch+e+(e.charAt(e.length-1)!=="?"?"&":"")+f+(d.hash||"")},convertUrlToDataUrl:function(a){var b=l.parseUrl(a);if(l.isEmbeddedPage(b))return b.hash.split(x)[0].replace(/^#/,"");else if(l.isSameDomain(b,v))return b.hrefNoHash.replace(v.domain,"");return a},get:function(a){if(a===c)a=location.hash;return l.stripHash(a).replace(/[^\/]*\.[^\/*]+$/, -"")},getFilePath:function(b){var c="&"+a.mobile.subPageUrlKey;return b&&b.split(c)[0].split(x)[0]},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(v.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},cleanHash:function(a){return l.stripHash(a.replace(/\?.*$/,"").replace(x,""))},isExternal:function(a){a=l.parseUrl(a);return a.protocol&&a.domain!==w.domain?true:false},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isFirstPageUrl:function(b){var b= -l.parseUrl(l.makeUrlAbsolute(b,v)),d=a.mobile.firstPage,d=d&&d[0]?d[0].id:c;return(b.hrefNoHash===w.hrefNoHash||y&&b.hrefNoHash===v.hrefNoHash)&&(!b.hash||b.hash==="#"||d&&b.hash.replace(/^#/,"")===d)},isEmbeddedPage:function(a){a=l.parseUrl(a);return a.protocol!==""?a.hash&&(a.hrefNoHash===w.hrefNoHash||y&&a.hrefNoHash===v.hrefNoHash):/^#/.test(a.href)}},r=null,n={stack:[],activeIndex:0,getActive:function(){return n.stack[n.activeIndex]},getPrev:function(){return n.stack[n.activeIndex-1]},getNext:function(){return n.stack[n.activeIndex+ -1]},addNew:function(a,b,c,d,f){n.getNext()&&n.clearForward();n.stack.push({url:a,transition:b,title:c,pageUrl:d,role:f});n.activeIndex=n.stack.length-1},clearForward:function(){n.stack=n.stack.slice(0,n.activeIndex+1)},directHashChange:function(b){var d,f,e;this.getActive();a.each(n.stack,function(a,c){b.currentUrl===c.url&&(d=a<n.activeIndex,f=!d,e=a)});this.activeIndex=e!==c?e:this.activeIndex;d?(b.either||b.isBack)(true):f&&(b.either||b.isForward)(false)},ignoreNextHashChange:false},q=[],t=false, -x="&ui-state=dialog",u=p.children("base"),w=l.parseUrl(location.href),v=u.length?l.parseUrl(l.makeUrlAbsolute(u.attr("href"),w.href)):w,y=w.hrefNoHash!==v.hrefNoHash,B=a.support.dynamicBaseTag?{element:u.length?u:a("<base>",{href:v.hrefNoHash}).prependTo(p),set:function(a){B.element.attr("href",l.makeUrlAbsolute(a,v))},reset:function(){B.element.attr("href",v.hrefNoHash)}}:c;a.mobile.focusPage=function(a){var b=a.find("[autofocus]"),c=a.find(".ui-title:eq(0)");b.length?b.focus():c.length?c.focus(): -a.focus()};var E=true,A,C;A=function(){if(E){var b=a.mobile.urlHistory.getActive();if(b){var c=m.scrollTop();b.lastScroll=c<a.mobile.minScrollBack?a.mobile.defaultHomeScroll:c}}};C=function(){setTimeout(A,100)};m.bind(a.support.pushState?"popstate":"hashchange",function(){E=false});m.one(a.support.pushState?"popstate":"hashchange",function(){E=true});m.one("pagecontainercreate",function(){a.mobile.pageContainer.bind("pagechange",function(){E=true;m.unbind("scrollstop",C);m.bind("scrollstop",C)})}); -m.bind("scrollstop",C);a.mobile.getScreenHeight=d;a.fn.animationComplete=function(b){return a.support.cssTransitions?a(this).one("webkitAnimationEnd animationend",b):(setTimeout(b,0),a(this))};a.mobile.path=l;a.mobile.base=B;a.mobile.urlHistory=n;a.mobile.dialogHashKey=x;a.mobile.allowCrossDomainPages=false;a.mobile.getDocumentUrl=function(b){return b?a.extend({},w):w.href};a.mobile.getDocumentBase=function(b){return b?a.extend({},v):v.href};a.mobile._bindPageRemove=function(){var b=a(this);!b.data("page").options.domCache&& -b.is(":jqmData(external-page='true')")&&b.bind("pagehide.remove",function(){var b=a(this),c=new a.Event("pageremove");b.trigger(c);c.isDefaultPrevented()||b.removeWithDependents()})};a.mobile.loadPage=function(b,d){var f=a.Deferred(),e=a.extend({},a.mobile.loadPage.defaults,d),g=null,j=null,k=l.makeUrlAbsolute(b,a.mobile.activePage&&o(a.mobile.activePage)||v.hrefNoHash);if(e.data&&e.type==="get")k=l.addSearchParams(k,e.data),e.data=c;if(e.data&&e.type==="post")e.reloadPage=true;var u=l.getFilePath(k), -n=l.convertUrlToDataUrl(k);e.pageContainer=e.pageContainer||a.mobile.pageContainer;g=e.pageContainer.children(":jqmData(url='"+n+"')");g.length===0&&n&&!l.isPath(n)&&(g=e.pageContainer.children("#"+n).attr("data-"+a.mobile.ns+"url",n));if(g.length===0)if(a.mobile.firstPage&&l.isFirstPageUrl(u))a.mobile.firstPage.parent().length&&(g=a(a.mobile.firstPage));else if(l.isEmbeddedPage(u))return f.reject(k,d),f.promise();B&&B.reset();if(g.length){if(!e.reloadPage)return h(g,e.role),f.resolve(k,d,g),f.promise(); -j=g}var m=e.pageContainer,x=new a.Event("pagebeforeload"),p={url:b,absUrl:k,dataUrl:n,deferred:f,options:e};m.trigger(x,p);if(x.isDefaultPrevented())return f.promise();if(e.showLoadMsg)var r=setTimeout(function(){a.mobile.showPageLoadingMsg()},e.loadMsgDelay);!a.mobile.allowCrossDomainPages&&!l.isSameDomain(w,k)?f.reject(k,d):a.ajax({url:u,type:e.type,data:e.data,dataType:"html",success:function(c,o,m){var x=a("<div></div>"),v=c.match(/<title[^>]*>([^<]*)/)&&RegExp.$1,w=RegExp("\\bdata-"+a.mobile.ns+ -"url=[\"']?([^\"'>]*)[\"']?");RegExp("(<[^>]+\\bdata-"+a.mobile.ns+"role=[\"']?page[\"']?[^>]*>)").test(c)&&RegExp.$1&&w.test(RegExp.$1)&&RegExp.$1&&(b=u=l.getFilePath(RegExp.$1));B&&B.set(u);x.get(0).innerHTML=c;g=x.find(":jqmData(role='page'), :jqmData(role='dialog')").first();g.length||(g=a("<div data-"+a.mobile.ns+"role='page'>"+c.split(/<\/?body[^>]*>/gmi)[1]+"</div>"));v&&!g.jqmData("title")&&(~v.indexOf("&")&&(v=a("<div>"+v+"</div>").text()),g.jqmData("title",v));if(!a.support.dynamicBaseTag){var q= -l.get(u);g.find("[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]").each(function(){var b=a(this).is("[href]")?"href":a(this).is("[src]")?"src":"action",c=a(this).attr(b),c=c.replace(location.protocol+"//"+location.host+location.pathname,"");/^(\w+:|#|\/)/.test(c)||a(this).attr(b,q+c)})}g.attr("data-"+a.mobile.ns+"url",l.convertUrlToDataUrl(u)).attr("data-"+a.mobile.ns+"external-page",true).appendTo(e.pageContainer);g.one("pagecreate",a.mobile._bindPageRemove);h(g,e.role);k.indexOf("&"+ -a.mobile.subPageUrlKey)>-1&&(g=e.pageContainer.children(":jqmData(url='"+n+"')"));e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg());p.xhr=m;p.textStatus=o;p.page=g;e.pageContainer.trigger("pageload",p);f.resolve(k,d,g,j)},error:function(b,c,g){B&&B.set(l.get());p.xhr=b;p.textStatus=c;p.errorThrown=g;b=new a.Event("pageloadfailed");e.pageContainer.trigger(b,p);b.isDefaultPrevented()||(e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg(),a.mobile.showPageLoadingMsg(a.mobile.pageLoadErrorMessageTheme, -a.mobile.pageLoadErrorMessage,true),setTimeout(a.mobile.hidePageLoadingMsg,1500)),f.reject(k,d))}});return f.promise()};a.mobile.loadPage.defaults={type:"get",data:c,reloadPage:false,role:c,showLoadMsg:false,pageContainer:c,loadMsgDelay:50};a.mobile.changePage=function(d,g){if(t)q.unshift(arguments);else{var j=a.extend({},a.mobile.changePage.defaults,g);j.pageContainer=j.pageContainer||a.mobile.pageContainer;j.fromPage=j.fromPage||a.mobile.activePage;var u=j.pageContainer,o=new a.Event("pagebeforechange"), -m={toPage:d,options:j};u.trigger(o,m);if(!o.isDefaultPrevented())if(d=m.toPage,t=true,typeof d=="string")a.mobile.loadPage(d,j).done(function(b,c,d,e){t=false;c.duplicateCachedPage=e;a.mobile.changePage(d,c)}).fail(function(){t=false;b(true);e();j.pageContainer.trigger("pagechangefailed",m)});else{if(d[0]===a.mobile.firstPage[0]&&!j.dataUrl)j.dataUrl=w.hrefNoHash;var o=j.fromPage,p=j.dataUrl&&l.convertUrlToDataUrl(j.dataUrl)||d.jqmData("url"),v=p;l.getFilePath(p);var r=n.getActive(),s=n.activeIndex=== -0,y=0,B=k.title,A=j.role==="dialog"||d.jqmData("role")==="dialog";if(o&&o[0]===d[0]&&!j.allowSamePageTransition)t=false,u.trigger("pagechange",m);else{h(d,j.role);j.fromHashChange&&n.directHashChange({currentUrl:p,isBack:function(){y=-1},isForward:function(){y=1}});try{k.activeElement&&k.activeElement.nodeName.toLowerCase()!="body"?a(k.activeElement).blur():a("input:focus, textarea:focus, select:focus").blur()}catch(E){}A&&r&&(p=(r.url||"")+x);if(j.changeHash!==false&&p)n.ignoreNextHashChange=true, -l.set(p);var C=!r?B:d.jqmData("title")||d.children(":jqmData(role='header')").find(".ui-title").getEncodedText();C&&B==k.title&&(B=C);d.jqmData("title")||d.jqmData("title",B);j.transition=j.transition||(y&&!s?r.transition:c)||(A?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition);y||n.addNew(p,j.transition,B,v,j.role);k.title=n.getActive().title;a.mobile.activePage=d;j.reverse=j.reverse||y<0;f(d,o,j.transition,j.reverse).done(function(c,f,g,h,l){b();j.duplicateCachedPage&&j.duplicateCachedPage.remove(); -l||a.mobile.focusPage(d);e();u.trigger("pagechange",m)})}}}};a.mobile.changePage.defaults={transition:c,reverse:false,changeHash:true,fromHashChange:false,role:c,duplicateCachedPage:c,pageContainer:c,showLoadMsg:true,dataUrl:c,fromPage:c,allowSamePageTransition:false};a.mobile._registerInternalEvents=function(){a(k).delegate("form","submit",function(b){var c=a(this);if(a.mobile.ajaxEnabled&&!c.is(":jqmData(ajax='false')")&&c.jqmHijackable().length){var d=c.attr("method"),e=c.attr("target"),f=c.attr("action"); -if(!f&&(f=o(c),f===v.hrefNoHash))f=w.hrefNoSearch;f=l.makeUrlAbsolute(f,o(c));!l.isExternal(f)&&!e&&(a.mobile.changePage(f,{type:d&&d.length&&d.toLowerCase()||"get",data:c.serialize(),transition:c.jqmData("transition"),direction:c.jqmData("direction"),reloadPage:true}),b.preventDefault())}});a(k).bind("vclick",function(c){if(!(c.which>1)&&a.mobile.linkBindingEnabled&&(c=j(c.target),a(c).jqmHijackable().length&&c&&l.parseUrl(c.getAttribute("href")||"#").hash!=="#"))b(true),r=a(c).closest(".ui-btn").not(".ui-disabled"), -r.addClass(a.mobile.activeBtnClass),a("."+a.mobile.activePageClass+" .ui-btn").not(c).blur(),a(c).jqmData("href",a(c).attr("href")).attr("href","#")});a(k).bind("click",function(d){if(a.mobile.linkBindingEnabled){var f=j(d.target),e=a(f),g;if(f&&!(d.which>1)&&e.jqmHijackable().length){g=function(){s.setTimeout(function(){b(true)},200)};e.jqmData("href")&&e.attr("href",e.jqmData("href"));if(e.is(":jqmData(rel='back')"))return s.history.back(),false;var h=o(e),f=l.makeUrlAbsolute(e.attr("href")||"#", -h);if(!a.mobile.ajaxEnabled&&!l.isEmbeddedPage(f))g();else{if(f.search("#")!=-1)if(f=f.replace(/[^#]*#/,""))f=l.isPath(f)?l.makeUrlAbsolute(f,h):l.makeUrlAbsolute("#"+f,w.hrefNoHash);else{d.preventDefault();return}var h=e.is("[rel='external']")||e.is(":jqmData(ajax='false')")||e.is("[target]"),k=a.mobile.allowCrossDomainPages&&w.protocol==="file:"&&f.search(/^https?:/)!=-1;h||l.isExternal(f)&&!k?g():(g=e.jqmData("transition"),h=(h=e.jqmData("direction"))&&h==="reverse"||e.jqmData("back"),e=e.attr("data-"+ -a.mobile.ns+"rel")||c,a.mobile.changePage(f,{transition:g,reverse:h,role:e}),d.preventDefault())}}}});a(k).delegate(".ui-page","pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),d=c.attr("href");d&&a.inArray(d,b)===-1&&(b.push(d),a.mobile.loadPage(d,{role:c.attr("data-"+a.mobile.ns+"rel")}))})});a.mobile._handleHashChange=function(b){var d=l.stripHash(b),f={transition:a.mobile.urlHistory.stack.length===0?"none":c,changeHash:false,fromHashChange:true}; -if(!a.mobile.hashListeningEnabled||n.ignoreNextHashChange)n.ignoreNextHashChange=false;else{if(n.stack.length>1&&d.indexOf(x)>-1)if(a.mobile.activePage.is(".ui-dialog"))n.directHashChange({currentUrl:d,either:function(b){var c=a.mobile.urlHistory.getActive();d=c.pageUrl;a.extend(f,{role:c.role,transition:c.transition,reverse:b})}});else{n.directHashChange({currentUrl:d,isBack:function(){s.history.back()},isForward:function(){s.history.forward()}});return}d?(d=typeof d==="string"&&!l.isPath(d)?l.makeUrlAbsolute("#"+ -d,v):d,a.mobile.changePage(d,f)):a.mobile.changePage(a.mobile.firstPage,f)}};m.bind("hashchange",function(){a.mobile._handleHashChange(location.hash)});a(k).bind("pageshow",g);a(s).bind("throttledresize",g)}})(jQuery);(function(a,c){var b={},e=a(c),f=a.mobile.path.parseUrl(location.href);a.extend(b,{initialFilePath:f.pathname+f.search,initialHref:f.hrefNoHash,state:function(){return{hash:location.hash||"#"+b.initialFilePath,title:k.title,initialHref:b.initialHref}},resetUIKeys:function(b){var c="&"+ -a.mobile.subPageUrlKey,f=b.indexOf(a.mobile.dialogHashKey);f>-1?b=b.slice(0,f)+"#"+b.slice(f):b.indexOf(c)>-1&&(b=b.split(c).join("#"+c));return b},hashValueAfterReset:function(c){c=b.resetUIKeys(c);return a.mobile.path.parseUrl(c).hash},nextHashChangePrevented:function(c){a.mobile.urlHistory.ignoreNextHashChange=c;b.onHashChangeDisabled=c},onHashChange:function(){if(!b.onHashChangeDisabled){var c,f;c=location.hash;var e=a.mobile.path.isPath(c),j=e?location.href:a.mobile.getDocumentUrl();c=e?c.replace("#", -""):c;f=b.state();c=a.mobile.path.makeUrlAbsolute(c,j);e&&(c=b.resetUIKeys(c));history.replaceState(f,k.title,c)}},onPopState:function(c){var c=c.originalEvent.state,f,h;if(c){f=b.hashValueAfterReset(a.mobile.urlHistory.getActive().url);h=b.hashValueAfterReset(c.hash.replace("#",""));if(f=f!==h)e.one("hashchange.pushstate",function(){b.nextHashChangePrevented(false)});b.nextHashChangePrevented(false);a.mobile._handleHashChange(c.hash);f&&b.nextHashChangePrevented(true)}},init:function(){e.bind("hashchange", -b.onHashChange);e.bind("popstate",b.onPopState);location.hash===""&&history.replaceState(b.state(),k.title,location.href)}});a(function(){a.mobile.pushStateEnabled&&a.support.pushState&&b.init()})})(jQuery,this);jQuery.mobile.transitionFallbacks.pop="fade";(function(a){a.mobile.transitionHandlers.slide=a.mobile.transitionHandlers.simultaneous;a.mobile.transitionFallbacks.slide="fade"})(jQuery,this);jQuery.mobile.transitionFallbacks.slidedown="fade";jQuery.mobile.transitionFallbacks.slideup="fade"; -jQuery.mobile.transitionFallbacks.flip="fade";jQuery.mobile.transitionFallbacks.flow="fade";jQuery.mobile.transitionFallbacks.turn="fade";(function(a){a.mobile.page.prototype.options.degradeInputs={color:false,date:false,datetime:false,"datetime-local":false,email:false,month:false,number:false,range:"number",search:"text",tel:false,time:false,url:false,week:false};a(k).bind("pagecreate create",function(c){var b=a.mobile.closestPageData(a(c.target)),e;if(b)e=b.options,a(c.target).find("input").not(b.keepNativeSelector()).each(function(){var b= -a(this),c=this.getAttribute("type"),g=e.degradeInputs[c]||"text";if(e.degradeInputs[c]){var h=a("<div>").html(b.clone()).html(),j=h.indexOf(" type=")>-1;b.replaceWith(h.replace(j?/\s+type=["']?\w+['"]?/:/\/?>/,' type="'+g+'" data-'+a.mobile.ns+'type="'+c+'"'+(j?"":">")))}})})})(jQuery);(function(a,c){a.widget("mobile.dialog",a.mobile.widget,{options:{closeBtnText:"Close",overlayTheme:"a",initSelector:":jqmData(role='dialog')"},_create:function(){var b=this,c=this.element,f=a("<a href='#' data-"+a.mobile.ns+ -"icon='delete' data-"+a.mobile.ns+"iconpos='notext'>"+this.options.closeBtnText+"</a>"),d=a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-corner-all ui-overlay-shadow"});c.addClass("ui-dialog ui-overlay-"+this.options.overlayTheme);c.wrapInner(d).children().find(":jqmData(role='header')").prepend(f).end().children(":first-child").addClass("ui-corner-top").end().children(":last-child").addClass("ui-corner-bottom");f.bind("click",function(){b.close()});c.bind("vclick submit",function(b){var b= -a(b.target).closest(b.type==="vclick"?"a":"form"),c;b.length&&!b.jqmData("transition")&&(c=a.mobile.urlHistory.getActive()||{},b.attr("data-"+a.mobile.ns+"transition",c.transition||a.mobile.defaultDialogTransition).attr("data-"+a.mobile.ns+"direction","reverse"))}).bind("pagehide",function(){a(this).find("."+a.mobile.activeBtnClass).removeClass(a.mobile.activeBtnClass)}).bind("pagebeforeshow",function(){b.options.overlayTheme&&b.element.page("removeContainerBackground").page("setContainerBackground", -b.options.overlayTheme)})},close:function(){c.history.back()}});a(k).delegate(a.mobile.dialog.prototype.options.initSelector,"pagecreate",function(){a.mobile.dialog.prototype.enhance(this)})})(jQuery,this);(function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain ui-body ui-br")};a(k).bind("pagecreate create",function(c){a(":jqmData(role='fieldcontain')",c.target).jqmEnhanceable().fieldcontain()})})(jQuery);(function(a){a.fn.grid=function(c){return this.each(function(){var b= -a(this),e=a.extend({grid:null},c),f=b.children(),d={solo:1,a:2,b:3,c:4,d:5},e=e.grid;if(!e)if(f.length<=5)for(var g in d)d[g]===f.length&&(e=g);else e="a";d=d[e];b.addClass("ui-grid-"+e);f.filter(":nth-child("+d+"n+1)").addClass("ui-block-a");d>1&&f.filter(":nth-child("+d+"n+2)").addClass("ui-block-b");d>2&&f.filter(":nth-child(3n+3)").addClass("ui-block-c");d>3&&f.filter(":nth-child(4n+4)").addClass("ui-block-d");d>4&&f.filter(":nth-child(5n+5)").addClass("ui-block-e")})}})(jQuery);(function(a){a(k).bind("pagecreate create", -function(c){a(":jqmData(role='nojs')",c.target).addClass("ui-nojs")})})(jQuery);(function(a,c){function b(a){for(var b;a;){if((b=typeof a.className==="string"&&a.className+" ")&&b.indexOf("ui-btn ")>-1&&b.indexOf("ui-disabled ")<0)break;a=a.parentNode}return a}a.fn.buttonMarkup=function(b){for(var b=b&&a.type(b)=="object"?b:{},d=0;d<this.length;d++){var g=this.eq(d),h=g[0],j=a.extend({},a.fn.buttonMarkup.defaults,{icon:b.icon!==c?b.icon:g.jqmData("icon"),iconpos:b.iconpos!==c?b.iconpos:g.jqmData("iconpos"), -theme:b.theme!==c?b.theme:g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c"),inline:b.inline!==c?b.inline:g.jqmData("inline"),shadow:b.shadow!==c?b.shadow:g.jqmData("shadow"),corners:b.corners!==c?b.corners:g.jqmData("corners"),iconshadow:b.iconshadow!==c?b.iconshadow:g.jqmData("iconshadow"),mini:b.mini!==c?b.mini:g.jqmData("mini")},b),o="ui-btn-inner",m,p,l,r,n,q;a.each(j,function(b,c){h.setAttribute("data-"+a.mobile.ns+b,c);g.jqmData(b,c)});(q=a.data(h.tagName==="INPUT"||h.tagName==="BUTTON"? -h.parentNode:h,"buttonElements"))?(h=q.outer,g=a(h),l=q.inner,r=q.text,a(q.icon).remove(),q.icon=null):(l=k.createElement(j.wrapperEls),r=k.createElement(j.wrapperEls));n=j.icon?k.createElement("span"):null;e&&!q&&e();if(!j.theme)j.theme=a.mobile.getInheritedTheme(g,"c");m="ui-btn ui-btn-up-"+j.theme;m+=j.inline?" ui-btn-inline":"";m+=j.shadow?" ui-shadow":"";m+=j.corners?" ui-btn-corner-all":"";j.mini!==c&&(m+=j.mini?" ui-mini":" ui-fullsize");j.inline!==c&&(m+=j.inline===false?" ui-btn-block":" ui-btn-inline"); -if(j.icon)j.icon="ui-icon-"+j.icon,j.iconpos=j.iconpos||"left",p="ui-icon "+j.icon,j.iconshadow&&(p+=" ui-icon-shadow");j.iconpos&&(m+=" ui-btn-icon-"+j.iconpos,j.iconpos=="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText()));o+=j.corners?" ui-btn-corner-all":"";j.iconpos&&j.iconpos==="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText());q&&g.removeClass(q.bcls||"");g.removeClass("ui-link").addClass(m);l.className=o;r.className="ui-btn-text";q||l.appendChild(r);if(n&&(n.className= -p,!q||!q.icon))n.appendChild(k.createTextNode("\u00a0")),l.appendChild(n);for(;h.firstChild&&!q;)r.appendChild(h.firstChild);q||h.appendChild(l);q={bcls:m,outer:h,inner:l,text:r,icon:n};a.data(h,"buttonElements",q);a.data(l,"buttonElements",q);a.data(r,"buttonElements",q);n&&a.data(n,"buttonElements",q)}return this};a.fn.buttonMarkup.defaults={corners:true,shadow:true,iconshadow:true,wrapperEls:"span"};var e=function(){var c=a.mobile.buttonMarkup.hoverDelay,d,g;a(k).bind({"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart":function(e){var j, -k=a(b(e.target)),e=e.type;if(k.length)if(j=k.attr("data-"+a.mobile.ns+"theme"),e==="vmousedown")a.support.touch?d=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j)},c):k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j);else if(e==="vmousecancel"||e==="vmouseup")k.removeClass("ui-btn-down-"+j).addClass("ui-btn-up-"+j);else if(e==="vmouseover"||e==="focus")a.support.touch?g=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-hover-"+j)},c):k.removeClass("ui-btn-up-"+ -j).addClass("ui-btn-hover-"+j);else if(e==="vmouseout"||e==="blur"||e==="scrollstart")k.removeClass("ui-btn-hover-"+j+" ui-btn-down-"+j).addClass("ui-btn-up-"+j),d&&clearTimeout(d),g&&clearTimeout(g)},"focusin focus":function(c){a(b(c.target)).addClass(a.mobile.focusClass)},"focusout blur":function(c){a(b(c.target)).removeClass(a.mobile.focusClass)}});e=null};a(k).bind("pagecreate create",function(b){a(":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", -b.target).not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").buttonMarkup()})})(jQuery);(function(a){a.mobile.page.prototype.options.backBtnText="Back";a.mobile.page.prototype.options.addBackBtn=false;a.mobile.page.prototype.options.backBtnTheme=null;a.mobile.page.prototype.options.headerTheme="a";a.mobile.page.prototype.options.footerTheme="a";a.mobile.page.prototype.options.contentTheme=null;a(k).delegate(":jqmData(role='page'), :jqmData(role='dialog')","pagecreate",function(){var c=a(this), -b=c.data("page").options,e=c.jqmData("role"),f=b.theme;a(":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')",this).jqmEnhanceable().each(function(){var d=a(this),g=d.jqmData("role"),h=d.jqmData("theme"),j=h||b.contentTheme||e==="dialog"&&f,k;d.addClass("ui-"+g);if(g==="header"||g==="footer"){var m=h||(g==="header"?b.headerTheme:b.footerTheme)||f;d.addClass("ui-bar-"+m).attr("role",g==="header"?"banner":"contentinfo");g==="header"&&(h=d.children("a"),k=h.hasClass("ui-btn-left"), -j=h.hasClass("ui-btn-right"),k=k||h.eq(0).not(".ui-btn-right").addClass("ui-btn-left").length,j||h.eq(1).addClass("ui-btn-right"));b.addBackBtn&&g==="header"&&a(".ui-page").length>1&&c.jqmData("url")!==a.mobile.path.stripHash(location.hash)&&!k&&a("<a href='#' class='ui-btn-left' data-"+a.mobile.ns+"rel='back' data-"+a.mobile.ns+"icon='arrow-l'>"+b.backBtnText+"</a>").attr("data-"+a.mobile.ns+"theme",b.backBtnTheme||m).prependTo(d);d.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({role:"heading", -"aria-level":"1"})}else g==="content"&&(j&&d.addClass("ui-body-"+j),d.attr("role","main"))})})})(jQuery);(function(a){a.widget("mobile.collapsible",a.mobile.widget,{options:{expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsed:true,heading:"h1,h2,h3,h4,h5,h6,legend",theme:null,contentTheme:null,iconTheme:"d",mini:false,initSelector:":jqmData(role='collapsible')"},_create:function(){var c=this.element,b=this.options,e=c.addClass("ui-collapsible"),f=c.children(b.heading).first(), -d=e.wrapInner("<div class='ui-collapsible-content'></div>").find(".ui-collapsible-content"),g=c.closest(":jqmData(role='collapsible-set')").addClass("ui-collapsible-set");f.is("legend")&&(f=a("<div role='heading'>"+f.html()+"</div>").insertBefore(f),f.next().remove());if(g.length){if(!b.theme)b.theme=g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c");if(!b.contentTheme)b.contentTheme=g.jqmData("content-theme");if(!b.iconPos)b.iconPos=g.jqmData("iconpos");if(!b.mini)b.mini=g.jqmData("mini")}d.addClass(b.contentTheme? -"ui-body-"+b.contentTheme:"");f.insertBefore(d).addClass("ui-collapsible-heading").append("<span class='ui-collapsible-heading-status'></span>").wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().buttonMarkup({shadow:false,corners:false,iconpos:c.jqmData("iconpos")||b.iconPos||"left",icon:"plus",mini:b.mini,theme:b.theme}).add(".ui-btn-inner",c).addClass("ui-corner-top ui-corner-bottom");e.bind("expand collapse",function(c){if(!c.isDefaultPrevented()){c.preventDefault(); -var j=a(this),c=c.type==="collapse",k=b.contentTheme;f.toggleClass("ui-collapsible-heading-collapsed",c).find(".ui-collapsible-heading-status").text(c?b.expandCueText:b.collapseCueText).end().find(".ui-icon").toggleClass("ui-icon-minus",!c).toggleClass("ui-icon-plus",c);j.toggleClass("ui-collapsible-collapsed",c);d.toggleClass("ui-collapsible-content-collapsed",c).attr("aria-hidden",c);if(k&&(!g.length||e.jqmData("collapsible-last")))f.find("a").first().add(f.find(".ui-btn-inner")).toggleClass("ui-corner-bottom", -c),d.toggleClass("ui-corner-bottom",!c);d.trigger("updatelayout")}}).trigger(b.collapsed?"collapse":"expand");f.bind("click",function(a){var b=f.is(".ui-collapsible-heading-collapsed")?"expand":"collapse";e.trigger(b);a.preventDefault()})}});a(k).bind("pagecreate create",function(c){a.mobile.collapsible.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){a.widget("mobile.collapsibleset",a.mobile.widget,{options:{initSelector:":jqmData(role='collapsible-set')"},_create:function(){var b=this.element.addClass("ui-collapsible-set"), -e=this.options;if(!e.theme)e.theme=a.mobile.getInheritedTheme(b,"c");if(!e.contentTheme)e.contentTheme=b.jqmData("content-theme");if(!e.corners)e.corners=b.jqmData("corners")===c?true:false;b.jqmData("collapsiblebound")||b.jqmData("collapsiblebound",true).bind("expand collapse",function(b){var c=b.type==="collapse",b=a(b.target).closest(".ui-collapsible"),e=b.data("collapsible");e.options.contentTheme&&b.jqmData("collapsible-last")&&(b.find(e.options.heading).first().find("a").first().add(".ui-btn-inner").toggleClass("ui-corner-bottom", -c),b.find(".ui-collapsible-content").toggleClass("ui-corner-bottom",!c))}).bind("expand",function(b){a(b.target).closest(".ui-collapsible").siblings(".ui-collapsible").trigger("collapse")})},_init:function(){this.refresh()},refresh:function(){var b=this.options,c=this.element.children(":jqmData(role='collapsible')");a.mobile.collapsible.prototype.enhance(c.not(".ui-collapsible"));c.each(function(){a(this).find(a.mobile.collapsible.prototype.options.heading).find("a").first().add(".ui-btn-inner").removeClass("ui-corner-top ui-corner-bottom")}); -c.first().find("a").first().addClass(b.corners?"ui-corner-top":"").find(".ui-btn-inner").addClass("ui-corner-top");c.last().jqmData("collapsible-last",true).find("a").first().addClass(b.corners?"ui-corner-bottom":"").find(".ui-btn-inner").addClass("ui-corner-bottom")}});a(k).bind("pagecreate create",function(b){a.mobile.collapsibleset.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.navbar",a.mobile.widget,{options:{iconpos:"top",grid:null,initSelector:":jqmData(role='navbar')"}, -_create:function(){var b=this.element,e=b.find("a"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:c;b.addClass("ui-navbar").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid});f||b.addClass("ui-navbar-noicons");e.buttonMarkup({corners:false,shadow:false,inline:true,iconpos:f});b.delegate("a","vclick",function(b){a(b.target).hasClass("ui-disabled")||(e.removeClass(a.mobile.activeBtnClass),a(this).addClass(a.mobile.activeBtnClass))});b.closest(".ui-page").bind("pagebeforeshow", -function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}});a(k).bind("pagecreate create",function(b){a.mobile.navbar.prototype.enhanceWithin(b.target)})})(jQuery);(function(a){var c={};a.widget("mobile.listview",a.mobile.widget,{options:{theme:null,countTheme:"c",headerTheme:"b",dividerTheme:"b",splitIcon:"arrow-r",splitTheme:"b",mini:false,inset:false,initSelector:":jqmData(role='listview')"},_create:function(){var a="";a+=this.options.inset?" ui-listview-inset ui-corner-all ui-shadow ": -"";a+=this.element.jqmData("mini")||this.options.mini===true?" ui-mini":"";this.element.addClass(function(c,f){return f+" ui-listview "+a});this.refresh(true)},_removeCorners:function(a,c){a=a.add(a.find(".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb"));c==="top"?a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl"):c==="bottom"?a.removeClass("ui-corner-bottom ui-corner-br ui-corner-bl"):a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl ui-corner-bottom ui-corner-br ui-corner-bl")},_refreshCorners:function(a){var c, -f;this.options.inset&&(c=this.element.children("li"),f=a?c.not(".ui-screen-hidden"):c.filter(":visible"),this._removeCorners(c),c=f.first().addClass("ui-corner-top"),c.add(c.find(".ui-btn-inner").not(".ui-li-link-alt span:first-child")).addClass("ui-corner-top").end().find(".ui-li-link-alt, .ui-li-link-alt span:first-child").addClass("ui-corner-tr").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-tl"),f=f.last().addClass("ui-corner-bottom"),f.add(f.find(".ui-btn-inner")).find(".ui-li-link-alt").addClass("ui-corner-br").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-bl")); -a||this.element.trigger("updatelayout")},_findFirstElementByTagName:function(a,c,f,d){var g={};for(g[f]=g[d]=true;a;){if(g[a.nodeName])return a;a=a[c]}return null},_getChildrenByTagName:function(b,c,f){var d=[],g={};g[c]=g[f]=true;for(b=b.firstChild;b;)g[b.nodeName]&&d.push(b),b=b.nextSibling;return a(d)},_addThumbClasses:function(b){var c,f,d=b.length;for(c=0;c<d;c++)f=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),f.length&&(f.addClass("ui-li-thumb"),a(this._findFirstElementByTagName(f[0].parentNode, -"parentNode","li","LI")).addClass(f.is(".ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb"))},refresh:function(b){this.parentPage=this.element.closest(".ui-page");this._createSubPages();var c=this.options,f=this.element,d=f.jqmData("dividertheme")||c.dividerTheme,g=f.jqmData("splittheme"),h=f.jqmData("spliticon"),j=this._getChildrenByTagName(f[0],"li","LI"),o=a.support.cssPseudoElement||!a.nodeName(f[0],"ol")?0:1,m={},p,l,r,n,q,t,x;o&&f.find(".ui-li-dec").remove();if(!c.theme)c.theme=a.mobile.getInheritedTheme(this.element, -"c");for(var u=0,w=j.length;u<w;u++){p=j.eq(u);l="ui-li";if(b||!p.hasClass("ui-li"))r=p.jqmData("theme")||c.theme,n=this._getChildrenByTagName(p[0],"a","A"),n.length?(t=p.jqmData("icon"),p.buttonMarkup({wrapperEls:"div",shadow:false,corners:false,iconpos:"right",icon:n.length>1||t===false?false:t||"arrow-r",theme:r}),t!=false&&n.length==1&&p.addClass("ui-li-has-arrow"),n.first().removeClass("ui-link").addClass("ui-link-inherit"),n.length>1&&(l+=" ui-li-has-alt",n=n.last(),q=g||n.jqmData("theme")|| -c.splitTheme,x=n.jqmData("icon"),n.appendTo(p).attr("title",n.getEncodedText()).addClass("ui-li-link-alt").empty().buttonMarkup({shadow:false,corners:false,theme:r,icon:false,iconpos:false}).find(".ui-btn-inner").append(a(k.createElement("span")).buttonMarkup({shadow:true,corners:true,theme:q,iconpos:"notext",icon:x||t||h||c.splitIcon})))):p.jqmData("role")==="list-divider"?(l+=" ui-li-divider ui-bar-"+d,p.attr("role","heading"),o&&(o=1)):l+=" ui-li-static ui-body-"+r;o&&l.indexOf("ui-li-divider")< -0&&(r=p.is(".ui-li-static:first")?p:p.find(".ui-link-inherit"),r.addClass("ui-li-jsnumbering").prepend("<span class='ui-li-dec'>"+o++ +". </span>"));m[l]||(m[l]=[]);m[l].push(p[0])}for(l in m)a(m[l]).addClass(l).children(".ui-btn-inner").addClass(l);f.find("h1, h2, h3, h4, h5, h6").addClass("ui-li-heading").end().find("p, dl").addClass("ui-li-desc").end().find(".ui-li-aside").each(function(){var b=a(this);b.prependTo(b.parent())}).end().find(".ui-li-count").each(function(){a(this).closest("li").addClass("ui-li-has-count")}).addClass("ui-btn-up-"+ -(f.jqmData("counttheme")||this.options.countTheme)+" ui-btn-corner-all");this._addThumbClasses(j);this._addThumbClasses(f.find(".ui-link-inherit"));this._refreshCorners(b)},_idStringEscape:function(a){return a.replace(/[^a-zA-Z0-9]/g,"-")},_createSubPages:function(){var b=this.element,e=b.closest(".ui-page"),f=e.jqmData("url"),d=f||e[0][a.expando],g=b.attr("id"),h=this.options,j="data-"+a.mobile.ns,k=this,m=e.find(":jqmData(role='footer')").jqmData("id"),p;typeof c[d]==="undefined"&&(c[d]=-1);g=g|| -++c[d];a(b.find("li>ul, li>ol").toArray().reverse()).each(function(c){var d=a(this),e=d.attr("id")||g+"-"+c,c=d.parent(),k=a(d.prevAll().toArray().reverse()),k=k.length?k:a("<span>"+a.trim(c.contents()[0].nodeValue)+"</span>"),o=k.first().getEncodedText(),e=(f||"")+"&"+a.mobile.subPageUrlKey+"="+e,x=d.jqmData("theme")||h.theme,u=d.jqmData("counttheme")||b.jqmData("counttheme")||h.countTheme;p=true;d.detach().wrap("<div "+j+"role='page' "+j+"url='"+e+"' "+j+"theme='"+x+"' "+j+"count-theme='"+u+"'><div "+ -j+"role='content'></div></div>").parent().before("<div "+j+"role='header' "+j+"theme='"+h.headerTheme+"'><div class='ui-title'>"+o+"</div></div>").after(m?a("<div "+j+"role='footer' "+j+"id='"+m+"'>"):"").parent().appendTo(a.mobile.pageContainer).page();d=c.find("a:first");d.length||(d=a("<a/>").html(k||o).prependTo(c.empty()));d.attr("href","#"+e)}).listview();p&&e.is(":jqmData(external-page='true')")&&e.data("page").options.domCache===false&&e.unbind("pagehide.remove").bind("pagehide.remove",function(b, -c){var d=c.nextPage;c.nextPage&&(d=d.jqmData("url"),d.indexOf(f+"&"+a.mobile.subPageUrlKey)!==0&&(k.childPages().remove(),e.remove()))})},childPages:function(){var b=this.parentPage.jqmData("url");return a(":jqmData(url^='"+b+"&"+a.mobile.subPageUrlKey+"')")}});a(k).bind("pagecreate create",function(b){a.mobile.listview.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.checkboxradio",a.mobile.widget,{options:{theme:null,initSelector:"input[type='checkbox'],input[type='radio']"}, -_create:function(){var b=this,e=this.element,f=a(e).closest("label"),d=f.length?f:a(e).closest("form,fieldset,:jqmData(role='page'),:jqmData(role='dialog')").find("label").filter("[for='"+e[0].id+"']"),g=e[0].type,f=e.jqmData("mini")||e.closest("form,fieldset").jqmData("mini"),h=g+"-on",j=g+"-off",o=e.parents(":jqmData(type='horizontal')").length?c:j,m=e.jqmData("iconpos")||e.closest("form,fieldset").jqmData("iconpos");if(!(g!=="checkbox"&&g!=="radio")){a.extend(this,{label:d,inputtype:g,checkedClass:"ui-"+ -h+(o?"":" "+a.mobile.activeBtnClass),uncheckedClass:"ui-"+j,checkedicon:"ui-icon-"+h,uncheckedicon:"ui-icon-"+j});if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");d.buttonMarkup({theme:this.options.theme,icon:o,shadow:false,mini:f,iconpos:m});f=k.createElement("div");f.className="ui-"+g;e.add(d).wrapAll(f);d.bind({vmouseover:function(b){a(this).parent().is(".ui-disabled")&&b.stopPropagation()},vclick:function(a){if(e.is(":disabled"))a.preventDefault();else return b._cacheVals(), -e.prop("checked",g==="radio"&&true||!e.prop("checked")),e.triggerHandler("click"),b._getInputSet().not(e).prop("checked",false),b._updateAll(),false}});e.bind({vmousedown:function(){b._cacheVals()},vclick:function(){var c=a(this);c.is(":checked")?(c.prop("checked",true),b._getInputSet().not(c).prop("checked",false)):c.prop("checked",false);b._updateAll()},focus:function(){d.addClass(a.mobile.focusClass)},blur:function(){d.removeClass(a.mobile.focusClass)}});this.refresh()}},_cacheVals:function(){this._getInputSet().each(function(){a(this).jqmData("cacheVal", -this.checked)})},_getInputSet:function(){return this.inputtype==="checkbox"?this.element:this.element.closest("form,fieldset,:jqmData(role='page')").find("input[name='"+this.element[0].name+"'][type='"+this.inputtype+"']")},_updateAll:function(){var b=this;this._getInputSet().each(function(){var c=a(this);(this.checked||b.inputtype==="checkbox")&&c.trigger("change")}).checkboxradio("refresh")},refresh:function(){var a=this.element[0],c=this.label,f=c.find(".ui-icon");a.checked?(c.addClass(this.checkedClass).removeClass(this.uncheckedClass), -f.addClass(this.checkedicon).removeClass(this.uncheckedicon)):(c.removeClass(this.checkedClass).addClass(this.uncheckedClass),f.removeClass(this.checkedicon).addClass(this.uncheckedicon));a.disabled?this.disable():this.enable()},disable:function(){this.element.prop("disabled",true).parent().addClass("ui-disabled")},enable:function(){this.element.prop("disabled",false).parent().removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(b){a.mobile.checkboxradio.prototype.enhanceWithin(b.target, -true)})})(jQuery);(function(a,c){a.widget("mobile.button",a.mobile.widget,{options:{theme:null,icon:null,iconpos:null,inline:false,corners:true,shadow:true,iconshadow:true,initSelector:"button, [type='button'], [type='submit'], [type='reset'], [type='image']",mini:false},_create:function(){var b=this.element,e,f=this.options,d;d="";var g;if(b[0].tagName==="A")!b.hasClass("ui-btn")&&b.buttonMarkup();else{if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");~b[0].className.indexOf("ui-btn-left")&& -(d="ui-btn-left");~b[0].className.indexOf("ui-btn-right")&&(d="ui-btn-right");e=this.button=a("<div></div>").text(b.text()||b.val()).insertBefore(b).buttonMarkup({theme:f.theme,icon:f.icon,iconpos:f.iconpos,inline:f.inline,corners:f.corners,shadow:f.shadow,iconshadow:f.iconshadow,mini:f.mini}).addClass(d).append(b.addClass("ui-btn-hidden"));f=b.attr("type");d=b.attr("name");f!=="button"&&f!=="reset"&&d&&b.bind("vclick",function(){g===c&&(g=a("<input>",{type:"hidden",name:b.attr("name"),value:b.attr("value")}).insertBefore(b), -a(k).one("submit",function(){g.remove();g=c}))});b.bind({focus:function(){e.addClass(a.mobile.focusClass)},blur:function(){e.removeClass(a.mobile.focusClass)}});this.refresh()}},enable:function(){this.element.attr("disabled",false);this.button.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.button.addClass("ui-disabled").attr("aria-disabled",true);return this._setOption("disabled",true)},refresh:function(){var b= -this.element;b.prop("disabled")?this.disable():this.enable();a(this.button.data("buttonElements").text).text(b.text()||b.val())}});a(k).bind("pagecreate create",function(b){a.mobile.button.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.fn.controlgroup=function(c){function b(a,b){a.removeClass("ui-btn-corner-all ui-shadow").eq(0).addClass(b[0]).end().last().addClass(b[1]).addClass("ui-controlgroup-last")}return this.each(function(){var e=a(this),f=a.extend({direction:e.jqmData("type")|| -"vertical",shadow:false,excludeInvisible:true,mini:e.jqmData("mini")},c),d=e.children("legend"),g=f.direction=="horizontal"?["ui-corner-left","ui-corner-right"]:["ui-corner-top","ui-corner-bottom"];e.find("input").first().attr("type");d.length&&(e.wrapInner("<div class='ui-controlgroup-controls'></div>"),a("<div role='heading' class='ui-controlgroup-label'>"+d.html()+"</div>").insertBefore(e.children(0)),d.remove());e.addClass("ui-corner-all ui-controlgroup ui-controlgroup-"+f.direction);b(e.find(".ui-btn"+ -(f.excludeInvisible?":visible":"")).not(".ui-slider-handle"),g);b(e.find(".ui-btn-inner"),g);f.shadow&&e.addClass("ui-shadow");f.mini&&e.addClass("ui-mini")})}})(jQuery);(function(a){a(k).bind("pagecreate create",function(c){a(c.target).find("a").jqmEnhanceable().not(".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")})})(jQuery);(function(a){var c=a("meta[name=viewport]"),b=c.attr("content"),e=b+",maximum-scale=1, user-scalable=no",f=b+",maximum-scale=10, user-scalable=yes", -d=/(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(b);a.mobile.zoom=a.extend({},{enabled:!d,locked:false,disable:function(b){if(!d&&!a.mobile.zoom.locked)c.attr("content",e),a.mobile.zoom.enabled=false,a.mobile.zoom.locked=b||false},enable:function(b){if(!d&&(!a.mobile.zoom.locked||b===true))c.attr("content",f),a.mobile.zoom.enabled=true,a.mobile.zoom.locked=false},restore:function(){if(!d)c.attr("content",b),a.mobile.zoom.enabled=true}})})(jQuery);(function(a){a.widget("mobile.textinput", -a.mobile.widget,{options:{theme:null,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,initSelector:"input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type])", -clearSearchButtonText:"clear text"},_create:function(){var c=this.element,b=this.options,e=b.theme||a.mobile.getInheritedTheme(this.element,"c"),f=" ui-body-"+e,d=c.jqmData("mini")==true,g=d?" ui-mini":"",h,j;a("label[for='"+c.attr("id")+"']").addClass("ui-input-text");h=c.addClass("ui-input-text ui-body-"+e);typeof c[0].autocorrect!=="undefined"&&!a.support.touchOverflow&&(c[0].setAttribute("autocorrect","off"),c[0].setAttribute("autocomplete","off"));c.is("[type='search'],:jqmData(type='search')")? -(h=c.wrap("<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield"+f+g+"'></div>").parent(),j=a("<a href='#' class='ui-input-clear' title='"+b.clearSearchButtonText+"'>"+b.clearSearchButtonText+"</a>").bind("click",function(a){c.val("").focus().trigger("change");j.addClass("ui-input-clear-hidden");a.preventDefault()}).appendTo(h).buttonMarkup({icon:"delete",iconpos:"notext",corners:true,shadow:true,mini:d}),e=function(){setTimeout(function(){j.toggleClass("ui-input-clear-hidden", -!c.val())},0)},e(),c.bind("paste cut keyup focus change blur",e)):c.addClass("ui-corner-all ui-shadow-inset"+f+g);c.focus(function(){h.addClass(a.mobile.focusClass)}).blur(function(){h.removeClass(a.mobile.focusClass)}).bind("focus",function(){b.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("blur",function(){b.preventFocusZoom&&a.mobile.zoom.enable(true)});if(c.is("textarea")){var o=function(){var a=c[0].scrollHeight;c[0].clientHeight<a&&c.height(a+15)},m;c.keyup(function(){clearTimeout(m); -m=setTimeout(o,100)});a(k).one("pagechange",o);a.trim(c.val())&&a(s).load(o)}},disable:function(){(this.element.attr("disabled",true).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).addClass("ui-disabled")},enable:function(){(this.element.attr("disabled",false).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(c){a.mobile.textinput.prototype.enhanceWithin(c.target, -true)})})(jQuery);(function(a){a.mobile.listview.prototype.options.filter=false;a.mobile.listview.prototype.options.filterPlaceholder="Filter items...";a.mobile.listview.prototype.options.filterTheme="c";a.mobile.listview.prototype.options.filterCallback=function(a,b){return a.toLowerCase().indexOf(b)===-1};a(k).delegate(":jqmData(role='listview')","listviewcreate",function(){var c=a(this),b=c.data("listview");if(b.options.filter){var e=a("<form>",{"class":"ui-listview-filter ui-bar-"+b.options.filterTheme, -role:"search"});a("<input>",{placeholder:b.options.filterPlaceholder}).attr("data-"+a.mobile.ns+"type","search").jqmData("lastval","").bind("keyup change",function(){var e=a(this),d=this.value.toLowerCase(),g=null,g=e.jqmData("lastval")+"",h=false,j="";e.jqmData("lastval",d);g=d.length<g.length||d.indexOf(g)!==0?c.children():c.children(":not(.ui-screen-hidden)");if(d){for(var k=g.length-1;k>=0;k--)e=a(g[k]),j=e.jqmData("filtertext")||e.text(),e.is("li:jqmData(role=list-divider)")?(e.toggleClass("ui-filter-hidequeue", -!h),h=false):b.options.filterCallback(j,d)?e.toggleClass("ui-filter-hidequeue",true):h=true;g.filter(":not(.ui-filter-hidequeue)").toggleClass("ui-screen-hidden",false);g.filter(".ui-filter-hidequeue").toggleClass("ui-screen-hidden",true).toggleClass("ui-filter-hidequeue",false)}else g.toggleClass("ui-screen-hidden",false);b._refreshCorners()}).appendTo(e).textinput();b.options.inset&&e.addClass("ui-listview-filter-inset");e.bind("submit",function(){return false}).insertBefore(c)}})})(jQuery);(function(a, -c){a.widget("mobile.slider",a.mobile.widget,{options:{theme:null,trackTheme:null,disabled:false,initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",mini:false},_create:function(){var b=this,e=this.element,f=a.mobile.getInheritedTheme(e,"c"),d=this.options.theme||f,f=this.options.trackTheme||f,g=e[0].nodeName.toLowerCase(),h=g=="select"?"ui-slider-switch":"",j=e.attr("id"),o=j+"-label",j=a("[for='"+j+"']").attr("id",o),m=function(){return g=="input"?parseFloat(e.val()): -e[0].selectedIndex},p=g=="input"?parseFloat(e.attr("min")):0,l=g=="input"?parseFloat(e.attr("max")):e.find("option").length-1,r=s.parseFloat(e.attr("step")||1),n=this.options.inline||e.jqmData("inline")==true?" ui-slider-inline":"",q=this.options.mini||e.jqmData("mini")?" ui-slider-mini":"",t=k.createElement("a"),x=a(t),u=k.createElement("div"),w=a(u),v=e.jqmData("highlight")&&g!="select"?function(){var b=k.createElement("div");b.className="ui-slider-bg ui-btn-active ui-btn-corner-all";return a(b).prependTo(w)}(): -false;t.setAttribute("href","#");u.setAttribute("role","application");u.className=["ui-slider ",h," ui-btn-down-",f," ui-btn-corner-all",n,q].join("");t.className="ui-slider-handle";u.appendChild(t);x.buttonMarkup({corners:true,theme:d,shadow:true}).attr({role:"slider","aria-valuemin":p,"aria-valuemax":l,"aria-valuenow":m(),"aria-valuetext":m(),title:m(),"aria-labelledby":o});a.extend(this,{slider:w,handle:x,valuebg:v,dragging:false,beforeStart:null,userModified:false,mouseMoved:false});if(g=="select"){d= -k.createElement("div");d.className="ui-slider-inneroffset";h=0;for(o=u.childNodes.length;h<o;h++)d.appendChild(u.childNodes[h]);u.appendChild(d);x.addClass("ui-slider-handle-snapping");u=e.find("option");d=0;for(h=u.length;d<h;d++)o=!d?"b":"a",n=!d?" ui-btn-down-"+f:" "+a.mobile.activeBtnClass,k.createElement("div"),q=k.createElement("span"),q.className=["ui-slider-label ui-slider-label-",o,n," ui-btn-corner-all"].join(""),q.setAttribute("role","img"),q.appendChild(k.createTextNode(u[d].innerHTML)), -a(q).prependTo(w);b._labels=a(".ui-slider-label",w)}j.addClass("ui-slider");e.addClass(g==="input"?"ui-slider-input":"ui-slider-switch").change(function(){b.mouseMoved||b.refresh(m(),true)}).keyup(function(){b.refresh(m(),true,true)}).blur(function(){b.refresh(m(),true)});a(k).bind("vmousemove",function(a){if(b.dragging)return b.mouseMoved=true,g==="select"&&x.removeClass("ui-slider-handle-snapping"),b.refresh(a),b.userModified=b.beforeStart!==e[0].selectedIndex,false});w.bind("vmousedown",function(a){b.dragging= -true;b.userModified=false;b.mouseMoved=false;if(g==="select")b.beforeStart=e[0].selectedIndex;b.refresh(a);return false}).bind("vclick",false);w.add(k).bind("vmouseup",function(){if(b.dragging)return b.dragging=false,g==="select"&&(x.addClass("ui-slider-handle-snapping"),b.mouseMoved?b.userModified?b.refresh(b.beforeStart==0?1:0):b.refresh(b.beforeStart):b.refresh(b.beforeStart==0?1:0)),b.mouseMoved=false});w.insertAfter(e);g=="select"&&this.handle.bind({focus:function(){w.addClass(a.mobile.focusClass)}, -blur:function(){w.removeClass(a.mobile.focusClass)}});this.handle.bind({vmousedown:function(){a(this).focus()},vclick:false,keydown:function(c){var d=m();if(!b.options.disabled){switch(c.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:if(c.preventDefault(),!b._keySliding)b._keySliding=true,a(this).addClass("ui-state-active")}switch(c.keyCode){case a.mobile.keyCode.HOME:b.refresh(p); -break;case a.mobile.keyCode.END:b.refresh(l);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:b.refresh(d+r);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.refresh(d-r)}}},keyup:function(){if(b._keySliding)b._keySliding=false,a(this).removeClass("ui-state-active")}});this.refresh(c,c,true)},refresh:function(b,c,f){(this.options.disabled||this.element.attr("disabled"))&&this.disable();var d=this.element,g=d[0].nodeName.toLowerCase(), -h=g==="input"?parseFloat(d.attr("min")):0,j=g==="input"?parseFloat(d.attr("max")):d.find("option").length-1,k=g==="input"&&parseFloat(d.attr("step"))>0?parseFloat(d.attr("step")):1;if(typeof b==="object"){if(!this.dragging||b.pageX<this.slider.offset().left-8||b.pageX>this.slider.offset().left+this.slider.width()+8)return;b=Math.round((b.pageX-this.slider.offset().left)/this.slider.width()*100)}else b==null&&(b=g==="input"?parseFloat(d.val()||0):d[0].selectedIndex),b=(parseFloat(b)-h)/(j-h)*100;if(!isNaN(b)){b< -0&&(b=0);b>100&&(b=100);var m=b/100*(j-h)+h,p=(m-h)%k;m-=p;Math.abs(p)*2>=k&&(m+=p>0?k:-k);m=parseFloat(m.toFixed(5));m<h&&(m=h);m>j&&(m=j);this.handle.css("left",b+"%");this.handle.attr({"aria-valuenow":g==="input"?m:d.find("option").eq(m).attr("value"),"aria-valuetext":g==="input"?m:d.find("option").eq(m).getEncodedText(),title:g==="input"?m:d.find("option").eq(m).getEncodedText()});this.valuebg&&this.valuebg.css("width",b+"%");if(this._labels){var h=this.handle.width()/this.slider.width()*100, -l=b&&h+(100-h)*b/100,r=b===100?0:Math.min(h+100-l,100);this._labels.each(function(){var b=a(this).is(".ui-slider-label-a");a(this).width((b?l:r)+"%")})}if(!f)f=false,g==="input"?(f=d.val()!==m,d.val(m)):(f=d[0].selectedIndex!==m,d[0].selectedIndex=m),!c&&f&&d.trigger("change")}},enable:function(){this.element.attr("disabled",false);this.slider.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.slider.addClass("ui-disabled").attr("aria-disabled", -true);return this._setOption("disabled",true)}});a(k).bind("pagecreate create",function(b){a.mobile.slider.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.widget("mobile.selectmenu",a.mobile.widget,{options:{theme:null,disabled:false,icon:"arrow-d",iconpos:"right",inline:false,corners:true,shadow:true,iconshadow:true,overlayTheme:"a",hidePlaceholderMenuItems:true,closeText:"Close",nativeMenu:true,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")> --1,initSelector:"select:not(:jqmData(role='slider'))",mini:false},_button:function(){return a("<div/>")},_setDisabled:function(a){this.element.attr("disabled",a);this.button.attr("aria-disabled",a);return this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var c="";~this.element[0].className.indexOf("ui-btn-left")&&(c=" ui-btn-left");~this.element[0].className.indexOf("ui-btn-right")&& -(c=" ui-btn-right");this.select=this.element.wrap("<div class='ui-select"+c+"'>");this.selectID=this.select.attr("id");this.label=a("label[for='"+this.selectID+"']").addClass("ui-select");this.isMultiple=this.select[0].multiple;if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.select,"c")},_create:function(){this._preExtension();this._trigger("beforeCreate");this.button=this._button();var c=this,b=this.options,e=this.button.text(a(this.select[0].options.item(this.select[0].selectedIndex== --1?0:this.select[0].selectedIndex)).text()).insertBefore(this.select).buttonMarkup({theme:b.theme,icon:b.icon,iconpos:b.iconpos,inline:b.inline,corners:b.corners,shadow:b.shadow,iconshadow:b.iconshadow,mini:b.mini});b.nativeMenu&&s.opera&&s.opera.version&&this.select.addClass("ui-select-nativeonly");if(this.isMultiple)this.buttonCount=a("<span>").addClass("ui-li-count ui-btn-up-c ui-btn-corner-all").hide().appendTo(e.addClass("ui-li-has-count"));(b.disabled||this.element.attr("disabled"))&&this.disable(); -this.select.change(function(){c.refresh()});this.build()},build:function(){var c=this;this.select.appendTo(c.button).bind("vmousedown",function(){c.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){c.button.addClass(a.mobile.focusClass)}).bind("blur",function(){c.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){c.button.trigger("vmouseover")}).bind("vmousemove",function(){c.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){c.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}).bind("change blur", -function(){c.button.removeClass("ui-btn-down-"+c.options.theme)});c.button.bind("vmousedown",function(){c.options.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("mouseup",function(){c.options.preventFocusZoom&&a.mobile.zoom.enable(true)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var c=this,b=this.selected();this.button.find(".ui-btn-text").text(function(){return!c.isMultiple? -b.text():b.length?b.map(function(){return a(this).text()}).get().join(", "):c.placeholder})},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},refresh:function(){this.setButtonText();this.setButtonCount()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(true);this.button.addClass("ui-disabled")},enable:function(){this._setDisabled(false);this.button.removeClass("ui-disabled")}});a(k).bind("pagecreate create", -function(c){a.mobile.selectmenu.prototype.enhanceWithin(c.target,true)})})(jQuery);(function(a){var c=function(b){var c=b.selectID,f=b.label,d=b.select.closest(".ui-page"),g=a("<div>",{"class":"ui-selectmenu-screen ui-screen-hidden"}).appendTo(d),h=b._selectOptions(),j=b.isMultiple=b.select[0].multiple,o=c+"-button",m=c+"-menu",p=a("<div data-"+a.mobile.ns+"role='dialog' data-"+a.mobile.ns+"theme='"+b.options.theme+"' data-"+a.mobile.ns+"overlay-theme='"+b.options.overlayTheme+"'><div data-"+a.mobile.ns+ -"role='header'><div class='ui-title'>"+f.getEncodedText()+"</div></div><div data-"+a.mobile.ns+"role='content'></div></div>"),l=a("<div>",{"class":"ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-"+b.options.overlayTheme+" "+a.mobile.defaultDialogTransition}).insertAfter(g),r=a("<ul>",{"class":"ui-selectmenu-list",id:m,role:"listbox","aria-labelledby":o}).attr("data-"+a.mobile.ns+"theme",b.options.theme).appendTo(l),n=a("<div>",{"class":"ui-header ui-bar-"+b.options.theme}).prependTo(l), -q=a("<h1>",{"class":"ui-title"}).appendTo(n),t;b.isMultiple&&(t=a("<a>",{text:b.options.closeText,href:"#","class":"ui-btn-left"}).attr("data-"+a.mobile.ns+"iconpos","notext").attr("data-"+a.mobile.ns+"icon","delete").appendTo(n).buttonMarkup());a.extend(b,{select:b.select,selectID:c,buttonId:o,menuId:m,thisPage:d,menuPage:p,label:f,screen:g,selectOptions:h,isMultiple:j,theme:b.options.theme,listbox:l,list:r,header:n,headerTitle:q,headerClose:t,menuPageContent:void 0,menuPageClose:void 0,placeholder:"", -build:function(){var c=this;c.refresh();c.select.attr("tabindex","-1").focus(function(){a(this).blur();c.button.focus()});c.button.bind("vclick keydown",function(b){if(b.type=="vclick"||b.keyCode&&(b.keyCode===a.mobile.keyCode.ENTER||b.keyCode===a.mobile.keyCode.SPACE))c.open(),b.preventDefault()});c.list.attr("role","listbox").bind("focusin",function(b){a(b.target).attr("tabindex","0").trigger("vmouseover")}).bind("focusout",function(b){a(b.target).attr("tabindex","-1").trigger("vmouseout")}).delegate("li:not(.ui-disabled, .ui-li-divider)", -"click",function(b){var d=c.select[0].selectedIndex,e=c.list.find("li:not(.ui-li-divider)").index(this),f=c._selectOptions().eq(e)[0];f.selected=c.isMultiple?!f.selected:true;c.isMultiple&&a(this).find(".ui-icon").toggleClass("ui-icon-checkbox-on",f.selected).toggleClass("ui-icon-checkbox-off",!f.selected);(c.isMultiple||d!==e)&&c.select.trigger("change");c.isMultiple||c.close();b.preventDefault()}).keydown(function(c){var d=a(c.target),e=d.closest("li");switch(c.keyCode){case 38:return c=e.prev().not(".ui-selectmenu-placeholder"), -c.is(".ui-li-divider")&&(c=c.prev()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 40:return c=e.next(),c.is(".ui-li-divider")&&(c=c.next()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 13:case 32:return d.trigger("click"),false}});c.menuPage.bind("pagehide",function(){c.list.appendTo(c.listbox);c._focusButton();a.mobile._bindPageRemove.call(c.thisPage)}); -c.screen.bind("vclick",function(){c.close()});c.isMultiple&&c.headerClose.click(function(){if(c.menuType=="overlay")return c.close(),false});c.thisPage.addDependents(this.menuPage)},_isRebuildRequired:function(){var a=this.list.find("li");return this._selectOptions().text()!==a.text()},refresh:function(b){var c=this;this._selectOptions();this.selected();var d=this.selectedIndices();(b||this._isRebuildRequired())&&c._buildList();c.setButtonText();c.setButtonCount();c.list.find("li:not(.ui-li-divider)").removeClass(a.mobile.activeBtnClass).attr("aria-selected", -false).each(function(b){a.inArray(b,d)>-1&&(b=a(this),b.attr("aria-selected",true),c.isMultiple?b.find(".ui-icon").removeClass("ui-icon-checkbox-off").addClass("ui-icon-checkbox-on"):b.is(".ui-selectmenu-placeholder")?b.next().addClass(a.mobile.activeBtnClass):b.addClass(a.mobile.activeBtnClass))})},close:function(){if(!this.options.disabled&&this.isOpen)this.menuType=="page"?s.history.back():(this.screen.addClass("ui-screen-hidden"),this.listbox.addClass("ui-selectmenu-hidden").removeAttr("style").removeClass("in"), -this.list.appendTo(this.listbox),this._focusButton()),this.isOpen=false},open:function(){function b(){c.list.find("."+a.mobile.activeBtnClass+" a").focus()}if(!this.options.disabled){var c=this,d=a(s),e=c.list.parent(),f=e.outerHeight(),e=e.outerWidth();a(".ui-page-active");var g=d.scrollTop(),j=c.button.offset().top,h=d.height(),d=d.width();c.button.addClass(a.mobile.activeBtnClass);setTimeout(function(){c.button.removeClass(a.mobile.activeBtnClass)},300);if(f>h-80||!a.support.scrollTop){c.menuPage.appendTo(a.mobile.pageContainer).page(); -c.menuPageContent=p.find(".ui-content");c.menuPageClose=p.find(".ui-header a");c.thisPage.unbind("pagehide.remove");if(g==0&&j>h)c.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",j)});c.menuPage.one("pageshow",function(){b();c.isOpen=true});c.menuType="page";c.menuPageContent.append(c.list);c.menuPage.find("div .ui-title").text(c.label.text());a.mobile.changePage(c.menuPage,{transition:a.mobile.defaultDialogTransition})}else{c.menuType="overlay";c.screen.height(a(k).height()).removeClass("ui-screen-hidden"); -var l=j-g,m=g+h-j,n=f/2,o=parseFloat(c.list.parent().css("max-width")),f=l>f/2&&m>f/2?j+c.button.outerHeight()/2-n:l>m?g+h-f-30:g+30;e<o?g=(d-e)/2:(g=c.button.offset().left+c.button.outerWidth()/2-e/2,g<30?g=30:g+e>d&&(g=d-e-30));c.listbox.append(c.list).removeClass("ui-selectmenu-hidden").css({top:f,left:g}).addClass("in");b();c.isOpen=true}}},_buildList:function(){var b=this.options,c=this.placeholder,d=true,e=this.isMultiple?"checkbox-off":"false";this.list.empty().filter(".ui-listview").listview("destroy"); -var f=this.select.find("option"),g=f.length,j=this.select[0],h="data-"+a.mobile.ns,l=h+"option-index",m=h+"icon";h+="role";for(var n=k.createDocumentFragment(),o,p=0;p<g;p++){var r=f[p],q=a(r),s=r.parentNode,t=q.text(),D=k.createElement("a"),J=[];D.setAttribute("href","#");D.appendChild(k.createTextNode(t));s!==j&&s.nodeName.toLowerCase()==="optgroup"&&(s=s.getAttribute("label"),s!=o&&(o=k.createElement("li"),o.setAttribute(h,"list-divider"),o.setAttribute("role","option"),o.setAttribute("tabindex", -"-1"),o.appendChild(k.createTextNode(s)),n.appendChild(o),o=s));if(d&&(!r.getAttribute("value")||t.length==0||q.jqmData("placeholder")))if(d=false,b.hidePlaceholderMenuItems&&J.push("ui-selectmenu-placeholder"),!c)c=this.placeholder=t;q=k.createElement("li");r.disabled&&(J.push("ui-disabled"),q.setAttribute("aria-disabled",true));q.setAttribute(l,p);q.setAttribute(m,e);q.className=J.join(" ");q.setAttribute("role","option");D.setAttribute("tabindex","-1");q.appendChild(D);n.appendChild(q)}this.list[0].appendChild(n); -!this.isMultiple&&!c.length?this.header.hide():this.headerTitle.text(this.placeholder);this.list.listview()},_button:function(){return a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})}})};a(k).bind("selectmenubeforecreate",function(b){b=a(b.target).data("selectmenu");b.options.nativeMenu||c(b)})})(jQuery);(function(a){a.widget("mobile.fixedtoolbar",a.mobile.widget,{options:{visibleOnPageShow:true,disablePageZoom:true,transition:"slide",fullscreen:false, -tapToggle:true,tapToggleBlacklist:"a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",hideDuringFocus:"input, textarea, select",updatePagePadding:true,trackPersistentToolbars:true,supportBlacklist:function(){var a=s,b=navigator.userAgent,e=navigator.platform,f=b.match(/AppleWebKit\/([0-9]+)/),f=!!f&&f[1],d=b.match(/Fennec\/([0-9]+)/),d=!!d&&d[1],g=b.match(/Opera Mobi\/([0-9]+)/),h=!!g&&g[1];return(e.indexOf("iPhone")>-1||e.indexOf("iPad")>-1||e.indexOf("iPod")>-1)&&f&&f<534||a.operamini&& -{}.toString.call(a.operamini)==="[object OperaMini]"||g&&h<7458||b.indexOf("Android")>-1&&f&&f<533||d&&d<6||"palmGetResource"in s&&f&&f<534||b.indexOf("MeeGo")>-1&&b.indexOf("NokiaBrowser/8.5.0")>-1?true:false},initSelector:":jqmData(position='fixed')"},_create:function(){var a=this.options,b=this.element,e=b.is(":jqmData(role='header')")?"header":"footer",f=b.closest(".ui-page");a.supportBlacklist()?this.destroy():(b.addClass("ui-"+e+"-fixed"),a.fullscreen?(b.addClass("ui-"+e+"-fullscreen"),f.addClass("ui-page-"+ -e+"-fullscreen")):f.addClass("ui-page-"+e+"-fixed"),this._addTransitionClass(),this._bindPageEvents(),this._bindToggleHandlers())},_addTransitionClass:function(){var a=this.options.transition;a&&a!=="none"&&(a==="slide"&&(a=this.element.is(".ui-header")?"slidedown":"slideup"),this.element.addClass(a))},_bindPageEvents:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("pagebeforeshow",function(){b.disablePageZoom&&a.mobile.zoom.disable(true);b.visibleOnPageShow||c.hide(true)}).bind("webkitAnimationStart animationstart updatelayout", -function(){b.updatePagePadding&&c.updatePagePadding()}).bind("pageshow",function(){c.updatePagePadding();b.updatePagePadding&&a(s).bind("throttledresize."+c.widgetName,function(){c.updatePagePadding()})}).bind("pagebeforehide",function(e,f){b.disablePageZoom&&a.mobile.zoom.enable(true);b.updatePagePadding&&a(s).unbind("throttledresize."+c.widgetName);if(b.trackPersistentToolbars){var d=a(".ui-footer-fixed:jqmData(id)",this),g=a(".ui-header-fixed:jqmData(id)",this),h=d.length&&f.nextPage&&a(".ui-footer-fixed:jqmData(id='"+ -d.jqmData("id")+"')",f.nextPage),j=g.length&&f.nextPage&&a(".ui-header-fixed:jqmData(id='"+g.jqmData("id")+"')",f.nextPage),h=h||a();if(h.length||j.length)h.add(j).appendTo(a.mobile.pageContainer),f.nextPage.one("pageshow",function(){h.add(j).appendTo(this)})}})},_visible:true,updatePagePadding:function(){var a=this.element,b=a.is(".ui-header");this.options.fullscreen||a.closest(".ui-page").css("padding-"+(b?"top":"bottom"),a.outerHeight())},_useTransition:function(c){var b=this.element,e=a(s).scrollTop(), -f=b.height(),d=b.closest(".ui-page").height(),g=a.mobile.getScreenHeight(),b=b.is(":jqmData(role='header')")?"header":"footer";return!c&&(this.options.transition&&this.options.transition!=="none"&&(b==="header"&&!this.options.fullscreen&&e>f||b==="footer"&&!this.options.fullscreen&&e+g<d-f)||this.options.fullscreen)},show:function(a){var b=this.element;this._useTransition(a)?b.removeClass("out ui-fixed-hidden").addClass("in"):b.removeClass("ui-fixed-hidden");this._visible=true},hide:function(a){var b= -this.element,e="out"+(this.options.transition==="slide"?" reverse":"");this._useTransition(a)?b.addClass(e).removeClass("in").animationComplete(function(){b.addClass("ui-fixed-hidden").removeClass(e)}):b.addClass("ui-fixed-hidden").removeClass(e);this._visible=false},toggle:function(){this[this._visible?"hide":"show"]()},_bindToggleHandlers:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("vclick",function(e){b.tapToggle&&!a(e.target).closest(b.tapToggleBlacklist).length&&c.toggle()}).bind("focusin focusout", -function(e){if(screen.width<500&&a(e.target).is(b.hideDuringFocus)&&!a(e.target).closest(".ui-header-fixed, .ui-footer-fixed").length)c[e.type==="focusin"&&c._visible?"hide":"show"]()})},destroy:function(){this.element.removeClass("ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden");this.element.closest(".ui-page").removeClass("ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen")}});a(k).bind("pagecreate create", -function(c){a(c.target).jqmData("fullscreen")&&a(a.mobile.fixedtoolbar.prototype.options.initSelector,c.target).not(":jqmData(fullscreen)").jqmData("fullscreen",true);a.mobile.fixedtoolbar.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){if(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1){var b=a.mobile.zoom,e,f,d,g,h;a(c).bind("orientationchange.iosorientationfix",b.enable).bind("devicemotion.iosorientationfix",function(a){e=a.originalEvent; -h=e.accelerationIncludingGravity;f=Math.abs(h.x);d=Math.abs(h.y);g=Math.abs(h.z);!c.orientation&&(f>7||(g>6&&d<8||g<8&&d>6)&&f>5)?b.enabled&&b.disable():b.enabled||b.enable()})}})(jQuery,this);(function(a,c){function b(){var b=a("."+a.mobile.activeBtnClass).first();h.css({top:a.support.scrollTop&&g.scrollTop()+g.height()/2||b.length&&b.offset().top||100})}function e(){var c=h.offset(),d=g.scrollTop(),f=a.mobile.getScreenHeight();if(c.top<d||c.top-d>f)h.addClass("ui-loader-fakefix"),b(),g.unbind("scroll", -e).bind("scroll",b)}function f(){d.removeClass("ui-mobile-rendering")}var d=a("html");a("head");var g=a(c);a(c.document).trigger("mobileinit");if(a.mobile.gradeA()){if(a.mobile.ajaxBlacklist)a.mobile.ajaxEnabled=false;d.addClass("ui-mobile ui-mobile-rendering");setTimeout(f,5E3);var h=a("<div class='ui-loader'><span class='ui-icon ui-icon-loading'></span><h1></h1></div>");a.extend(a.mobile,{showPageLoadingMsg:function(b,c,f){d.addClass("ui-loading");if(a.mobile.loadingMessage){var k=f||a.mobile.loadingMessageTextVisible; -b=b||a.mobile.loadingMessageTheme;h.attr("class","ui-loader ui-corner-all ui-body-"+(b||"a")+" ui-loader-"+(k?"verbose":"default")+(f?" ui-loader-textonly":"")).find("h1").text(c||a.mobile.loadingMessage).end().appendTo(a.mobile.pageContainer);e();g.bind("scroll",e)}},hidePageLoadingMsg:function(){d.removeClass("ui-loading");a.mobile.loadingMessage&&h.removeClass("ui-loader-fakefix");a(c).unbind("scroll",b);a(c).unbind("scroll",e)},initializePage:function(){var b=a(":jqmData(role='page'), :jqmData(role='dialog')"); -b.length||(b=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0));b.each(function(){var b=a(this);b.jqmData("url")||b.attr("data-"+a.mobile.ns+"url",b.attr("id")||location.pathname+location.search)});a.mobile.firstPage=b.first();a.mobile.pageContainer=b.first().parent().addClass("ui-mobile-viewport");g.trigger("pagecontainercreate");a.mobile.showPageLoadingMsg();f();!a.mobile.hashListeningEnabled||!a.mobile.path.stripHash(location.hash)?a.mobile.changePage(a.mobile.firstPage, -{transition:"none",reverse:true,changeHash:false,fromHashChange:true}):g.trigger("hashchange",[true])}});a.mobile._registerInternalEvents();a(function(){c.scrollTo(0,1);a.mobile.defaultHomeScroll=!a.support.scrollTop||a(c).scrollTop()===1?0:1;a.fn.controlgroup&&a(k).bind("pagecreate create",function(b){a(":jqmData(role='controlgroup')",b.target).jqmEnhanceable().controlgroup({excludeInvisible:false})});a.mobile.autoInitializePage&&a.mobile.initializePage();g.load(a.mobile.silentScroll)})}})(jQuery, -this)});
--- a/PalanthirExplorer/libs/jquery.mobile.simpledialog.min.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -/* - * jQuery Mobile Framework : plugin to provide a simple Dialog widget. - * Copyright (c) JTSage - * CC 3.0 Attribution. May be relicensed without permission/notifcation. - * https://github.com/jtsage/jquery-mobile-simpledialog - */ - -.ui-simpledialog-header h4{margin-top:5px;margin-bottom:5px;text-align:center}.ui-simpledialog-container{border:5px solid #111!important;width:85%;max-width:500px}.ui-simpledialog-screen{position:absolute;top:0;left:0;width:100%;height:100%}.ui-simpledialog-hidden{display:none}.ui-simpledialog-input{width:85%!important;display:block!important;margin-left:auto;margin-right:auto}.ui-simpledialog-screen-modal{background-color:black;-moz-opacity:.8;opacity:.80;filter:alpha(opacity=80)}.ui-simpledialog-subtitle{text-align:center}.ui-simpledialog-controls .buttons-separator{min-height:.6em}.ui-simpledialog-controls .button-hidden{display:none}.ui-dialog .ui-simpledialog-container{border:none!important}.ui-dialog-simpledialog .ui-content{padding:5px!important} \ No newline at end of file
--- a/PalanthirExplorer/libs/jquery.mobile.simpledialog2.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -/* - * jQuery Mobile Framework : plugin to provide a dialogs Widget. ver2 - * Copyright (c) JTSage - * CC 3.0 Attribution. May be relicensed without permission/notifcation. - * https://github.com/jtsage/jquery-mobile-simpledialog - * - * Modifications by Sebastien Jodogne - */ - -(function($, undefined ) { - $.widget( "mobile.simpledialog2", $.mobile.widget, { - options: { - version: '1.0.1-2012061300', // jQueryMobile-YrMoDaySerial - mode: 'blank', // or 'button' - themeDialog: 'b', - themeInput: false, - themeButtonDefault: false, - themeHeader: 'a', - - fullScreen: false, - fullScreenForce: false, - dialogAllow: false, - dialogForce: false, - - headerText: false, - headerClose: false, - buttonPrompt: false, - buttonInput: false, - buttonInputDefault: false, - buttonPassword: false, - blankContent: false, - blankContentAdopt: false, - - resizeListener: true, - safeNuke: true, - forceInput: true, - showModal: true, - animate: true, - transition: 'pop', - clickEvent: 'click', - zindex: '500', - width: '280px', - left: false, - top: false, - - callbackOpen: false, - callbackOpenArgs: [], - callbackClose: false, - callbackCloseArgs: [] - }, - _eventHandler: function(e,p) { - // Handle the triggers - var self = e.data.widget, - o = e.data.widget.options; - - if ( ! e.isPropagationStopped() ) { - switch (p.method) { - case 'close': - self.close(); - break; - case 'html': - self.updateBlank(p.source); - break; - } - } - }, - _create: function () { - var self = this, - o = $.extend(this.options, this.element.jqmData('options')), - initDate = new Date(), - content = $("<div class='ui-simpledialog-container ui-overlay-shadow ui-corner-all ui-simpledialog-hidden " + - ((o.animate === true) ? o.transition : '') + " ui-body-" + o.themeDialog + "'></div>"); - - if ( o.themeButtonDefault === false ) { o.themeButtonDefault = o.themeDialog; } - if ( o.themeInput === false ) { o.themeInput = o.themeDialog; } - $.mobile.sdCurrentDialog = self; - if ( typeof $.mobile.sdLastInput !== 'undefined' ) { delete $.mobile.sdLastInput; } - self.internalID = initDate.getTime(); - self.displayAnchor = $.mobile.activePage.children('.ui-content').first(); - if ( self.displayAnchor.length === 0 ) { self.displayAnchor = $.mobile.activePage; } - - self.dialogPage = $("<div data-role='dialog' data-theme='" + o.themeDialog + "'><div data-role='header'></div><div data-role='content'></div></div>"); - self.sdAllContent = self.dialogPage.find('[data-role=content]'); - - content.appendTo(self.sdAllContent); - - self.sdIntContent = self.sdAllContent.find('.ui-simpledialog-container'); - self.sdIntContent.css('width', o.width); - - if ( o.headerText !== false || o.headerClose !== false ) { - self.sdHeader = $('<div style="margin-bottom: 4px;" class="ui-header ui-bar-'+o.themeHeader+'"></div>'); - if ( o.headerClose === true ) { - $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); - } - $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); - self.sdHeader.appendTo(self.sdIntContent); - } - - if ( o.mode === 'blank' ) { - if ( o.blankContent === true ) { - if ( o.blankContentAdopt === true ) { - o.blankContent = self.element.children(); - } else { - o.blankContent = self.element.html(); - } - } - $(o.blankContent).appendTo(self.sdIntContent); - } else if ( o.mode === 'button' ) { - self._makeButtons().appendTo(self.sdIntContent); - } - - self.sdIntContent.appendTo(self.displayAnchor.parent()); - - self.dialogPage.appendTo( $.mobile.pageContainer ) - .page().css('minHeight', '0px').css('zIndex', o.zindex); - - if ( o.animate === true ) { self.dialogPage.addClass(o.transition); } - - self.screen = $("<div>", {'class':'ui-simpledialog-screen ui-simpledialog-hidden'}) - .css('z-index', (o.zindex-1)) - .appendTo(self.displayAnchor.parent()) - .bind(o.clickEvent, function(event){ - if ( !o.forceInput ) { - self.close(); - } - event.preventDefault(); - }); - - if ( o.showModal ) { self.screen.addClass('ui-simpledialog-screen-modal'); } - - $(document).bind('simpledialog.'+self.internalID, {widget:self}, function(e,p) { self._eventHandler(e,p); }); - }, - _makeButtons: function () { - var self = this, - o = self.options, - buttonHTML = $('<div></div>'), - pickerInput = $("<div class='ui-simpledialog-controls'><input class='ui-simpledialog-input ui-input-text ui-shadow-inset ui-corner-all ui-body-"+o.themeInput+"' type='"+((o.buttonPassword===true)?"password":"text")+"' value='"+((o.buttonInputDefault!==false)?o.buttonInputDefault.replace( '"', """ ).replace( "'", "'" ):"")+"' name='pickin' /></div>"), - pickerChoice = $("<div>", { "class":'ui-simpledialog-controls' }); - - - if ( o.buttonPrompt !== false ) { - self.buttonPromptText = $("<p class='ui-simpledialog-subtitle'>"+o.buttonPrompt+"</p>").appendTo(buttonHTML); - } - - if ( o.buttonInput !== false ) { - $.mobile.sdLastInput = ""; - pickerInput.appendTo(buttonHTML); - pickerInput.find('input').bind('change', function () { - $.mobile.sdLastInput = pickerInput.find('input').first().val(); - self.thisInput = pickerInput.find('input').first().val(); - }); - } - - pickerChoice.appendTo(buttonHTML); - - self.butObj = []; - - $.each(o.buttons, function(name, props) { - props = $.isFunction( props ) ? { click: props } : props; - props = $.extend({ - text : name, - id : name + self.internalID, - theme : o.themeButtonDefault, - icon : 'check', - iconpos: 'left', - corners: 'true', - shadow : 'true', - args : [], - close : true - }, props); - - self.butObj.push($("<a href='#'>"+name+"</a>") - .appendTo(pickerChoice) - .attr('id', props.id) - .buttonMarkup({ - theme : props.theme, - icon : props.icon, - iconpos: props.iconpos, - corners: props.corners, - shadow : props.shadow - }).unbind("vclick click") - .bind(o.clickEvent, function() { - if ( o.buttonInput ) { self.sdIntContent.find('input [name=pickin]').trigger('change'); } - var returnValue = props.click.apply(self, $.merge(arguments, props.args)); - if ( returnValue !== false && props.close === true ) { - self.close(); - } - }) - ); - }); - - return buttonHTML; - }, - _getCoords: function(widget) { - var self = widget, - docWinWidth = $.mobile.activePage.width(), - docWinHighOff = $(window).scrollTop(), - docWinHigh = $(window).height(), - diaWinWidth = widget.sdIntContent.innerWidth(), - diaWinHigh = widget.sdIntContent.outerHeight(), - - coords = { - 'high' : $(window).height(), - 'width' : $.mobile.activePage.width(), - 'fullTop' : $(window).scrollTop(), - 'fullLeft': $(window).scrollLeft(), - 'winTop' : docWinHighOff + ((widget.options.top !== false) ? widget.options.top : (( docWinHigh / 2 ) - ( diaWinHigh / 2 ) )), - 'winLeft' : ((widget.options.left !== false) ? widget.options.left : (( docWinWidth / 2 ) - ( diaWinWidth / 2 ) )) - }; - - if ( coords.winTop < 45 ) { coords.winTop = 45; } - - return coords; - }, - _orientChange: function(e) { - var self = e.data.widget, - o = e.data.widget.options, - coords = e.data.widget._getCoords(e.data.widget); - - e.stopPropagation(); - - if ( self.isDialog === true ) { - return true; - } else { - if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { - self.sdIntContent.css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); - } else { - self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); - } - } - }, - repos: function() { - var bsEvent = { data: {widget:this}, stopPropagation: function () { return true; }}; - this._orientChange(bsEvent); - }, - open: function() { - var self = this, - o = this.options, - coords = this._getCoords(this); - - self.sdAllContent.find('.ui-btn-active').removeClass('ui-btn-active'); - self.sdIntContent.delegate('[rel=close]', o.clickEvent, function (e) { e.preventDefault(); self.close(); }); - - if ( ( o.dialogAllow === true && coords.width < 400 ) || o.dialogForce ) { - self.isDialog = true; - - if ( o.mode === 'blank' ) { // Custom selects do not play well with dialog mode - so, we turn them off. - self.sdIntContent.find('select').each(function () { - $(this).jqmData('nativeMenu', true); - }); - } - - self.displayAnchor.parent().unbind("pagehide.remove"); - self.sdAllContent.append(self.sdIntContent); - self.sdAllContent.trigger('create'); - if ( o.headerText !== false ) { - self.sdHeader.find('h1').appendTo(self.dialogPage.find('[data-role=header]')); - self.sdIntContent.find('.ui-header').empty().removeClass(); - } - if ( o.headerClose === true ) { - self.dialogPage.find('.ui-header a').bind('click', function () { - setTimeout("$.mobile.sdCurrentDialog.destroy();", 1000); - }); - } else { - self.dialogPage.find('.ui-header a').remove(); - } - - self.sdIntContent.removeClass().css({'top': 'auto', 'width': 'auto', 'left': 'auto', 'marginLeft': 'auto', 'marginRight': 'auto', 'zIndex': o.zindex}); - $.mobile.changePage(self.dialogPage, {'transition': (o.animate === true) ? o.transition : 'none'}); - } else { - self.isDialog = false; - self.selects = []; - - if ( o.fullScreen === false ) { - if ( o.showModal === true && o.animate === true ) { self.screen.fadeIn('slow'); } - else { self.screen.removeClass('ui-simpledialog-hidden'); } - } - - self.sdIntContent.addClass('ui-overlay-shadow in').css('zIndex', o.zindex).trigger('create'); - - if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { - self.sdIntContent.removeClass('ui-simpledialog-container').css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); - } else { - self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); - } - - $(document).bind('orientationchange.simpledialog', {widget:self}, function(e) { self._orientChange(e); }); - if ( o.resizeListener === true ) { - $(window).bind('resize.simpledialog', {widget:self}, function (e) { self._orientChange(e); }); - } - } - if ( $.isFunction(o.callbackOpen) ) { - o.callbackOpen.apply(self, o.callbackOpenArgs); - } - }, - close: function() { - var self = this, o = this.options, retty; - - if ( $.isFunction(self.options.callbackClose) ) { - retty = self.options.callbackClose.apply(self, self.options.callbackCloseArgs); - if ( retty === false ) { return false; } - } - - if ( self.isDialog ) { - $(self.dialogPage).dialog('close'); - self.sdIntContent.addClass('ui-simpledialog-hidden'); - self.sdIntContent.appendTo(self.displayAnchor.parent()); - if ( $.mobile.activePage.jqmData("page").options.domCache != true && $.mobile.activePage.is(":jqmData(external-page='true')") ) { - $.mobile.activePage.bind("pagehide.remove", function () { - $(this).remove(); - }); - } - } else { - if ( self.options.showModal === true && self.options.animate === true ) { - self.screen.fadeOut('slow'); - } else { - self.screen.addClass('ui-simpledialog-hidden'); - } - self.sdIntContent.addClass('ui-simpledialog-hidden').removeClass('in'); - $(document).unbind('orientationchange.simpledialog'); - if ( self.options.resizeListener === true ) { $(window).unbind('resize.simpledialog'); } - } - - if ( o.mode === 'blank' && o.blankContent !== false && o.blankContentAdopt === true ) { - self.element.append(o.blankContent); - o.blankContent = true; - } - - if ( self.isDialog === true || self.options.animate === true ) { - setTimeout(function(that) { return function () { that.destroy(); };}(self), 1000); - } else { - self.destroy(); - } - }, - destroy: function() { - var self = this, - ele = self.element; - - if ( self.options.mode === 'blank' ) { - $.mobile.sdCurrentDialog.sdIntContent.find('select').each(function() { - if ( $(this).data('nativeMenu') == false ) { - $(this).data('selectmenu').menuPage.remove(); - $(this).data('selectmenu').screen.remove(); - $(this).data('selectmenu').listbox.remove(); - } - }); - } - - $(self.sdIntContent).remove(); - $(self.dialogPage).remove(); - $(self.screen).remove(); - $(document).unbind('simpledialog.'+self.internalID); - delete $.mobile.sdCurrentDialog; - $.Widget.prototype.destroy.call(self); - if ( self.options.safeNuke === true && $(ele).parents().length === 0 && $(ele).contents().length === 0 ) { - ele.remove(); - } - }, - updateBlank: function (newHTML) { - var self = this, - o = this.options; - - self.sdIntContent.empty(); - - if ( o.headerText !== false || o.headerClose !== false ) { - self.sdHeader = $('<div class="ui-header ui-bar-'+o.themeHeader+'"></div>'); - if ( o.headerClose === true ) { - $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); - } - $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); - self.sdHeader.appendTo(self.sdIntContent); - } - - $(newHTML).appendTo(self.sdIntContent); - self.sdIntContent.trigger('create'); - $(document).trigger('orientationchange.simpledialog'); - }, - _init: function() { - this.open(); - } - }); -})( jQuery );
--- a/PalanthirExplorer/libs/jquery.mobile.structure-1.1.0.min.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ -.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- a/PalanthirExplorer/libs/jquery.mobile.theme-1.1.0.min.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ -.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted} \ No newline at end of file
--- a/PalanthirExplorer/libs/slimbox2.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -/*! - Slimbox v2.04 - The ultimate lightweight Lightbox clone for jQuery - (c) 2007-2010 Christophe Beyls <http://www.digitalia.be> - MIT-style license. -*/ - -(function($) { - - // Global variables, accessible to Slimbox only - var win = $(window), options, images, activeImage = -1, activeURL, prevImage, nextImage, compatibleOverlay, middle, centerWidth, centerHeight, - ie6 = !window.XMLHttpRequest, hiddenElements = [], documentElement = document.documentElement, - - // Preload images - preload = {}, preloadPrev = new Image(), preloadNext = new Image(), - - // DOM elements - overlay, center, image, sizer, prevLink, nextLink, bottomContainer, bottom, caption, number; - - /* - Initialization - */ - - $(function() { - // Append the Slimbox HTML code at the bottom of the document - $("body").append( - $([ - overlay = $('<div id="lbOverlay" />')[0], - center = $('<div id="lbCenter" />')[0], - bottomContainer = $('<div id="lbBottomContainer" />')[0] - ]).css("display", "none") - ); - - image = $('<div id="lbImage" />').appendTo(center).append( - sizer = $('<div style="position: relative;" />').append([ - prevLink = $('<a id="lbPrevLink" href="#" />').click(previous)[0], - nextLink = $('<a id="lbNextLink" href="#" />').click(next)[0] - ])[0] - )[0]; - - bottom = $('<div id="lbBottom" />').appendTo(bottomContainer).append([ - $('<a id="lbCloseLink" href="#" />').add(overlay).click(close)[0], - caption = $('<div id="lbCaption" />')[0], - number = $('<div id="lbNumber" />')[0], - $('<div style="clear: both;" />')[0] - ])[0]; - }); - - - /* - API - */ - - // Open Slimbox with the specified parameters - $.slimbox = function(_images, startImage, _options) { - options = $.extend({ - loop: false, // Allows to navigate between first and last images - overlayOpacity: 0.8, // 1 is opaque, 0 is completely transparent (change the color in the CSS file) - overlayFadeDuration: 400, // Duration of the overlay fade-in and fade-out animations (in milliseconds) - resizeDuration: 400, // Duration of each of the box resize animations (in milliseconds) - resizeEasing: "swing", // "swing" is jQuery's default easing - initialWidth: 250, // Initial width of the box (in pixels) - initialHeight: 250, // Initial height of the box (in pixels) - imageFadeDuration: 400, // Duration of the image fade-in animation (in milliseconds) - captionAnimationDuration: 400, // Duration of the caption animation (in milliseconds) - counterText: "Image {x} of {y}", // Translate or change as you wish, or set it to false to disable counter text for image groups - closeKeys: [27, 88, 67], // Array of keycodes to close Slimbox, default: Esc (27), 'x' (88), 'c' (67) - previousKeys: [37, 80], // Array of keycodes to navigate to the previous image, default: Left arrow (37), 'p' (80) - nextKeys: [39, 78] // Array of keycodes to navigate to the next image, default: Right arrow (39), 'n' (78) - }, _options); - - // The function is called for a single image, with URL and Title as first two arguments - if (typeof _images == "string") { - _images = [[_images, startImage]]; - startImage = 0; - } - - middle = win.scrollTop() + (win.height() / 2); - centerWidth = options.initialWidth; - centerHeight = options.initialHeight; - $(center).css({top: Math.max(0, middle - (centerHeight / 2)), width: centerWidth, height: centerHeight, marginLeft: -centerWidth/2}).show(); - compatibleOverlay = ie6 || (overlay.currentStyle && (overlay.currentStyle.position != "fixed")); - if (compatibleOverlay) overlay.style.position = "absolute"; - $(overlay).css("opacity", options.overlayOpacity).fadeIn(options.overlayFadeDuration); - position(); - setup(1); - - images = _images; - options.loop = options.loop && (images.length > 1); - return changeImage(startImage); - }; - - /* - options: Optional options object, see jQuery.slimbox() - linkMapper: Optional function taking a link DOM element and an index as arguments and returning an array containing 2 elements: - the image URL and the image caption (may contain HTML) - linksFilter: Optional function taking a link DOM element and an index as arguments and returning true if the element is part of - the image collection that will be shown on click, false if not. "this" refers to the element that was clicked. - This function must always return true when the DOM element argument is "this". - */ - $.fn.slimbox = function(_options, linkMapper, linksFilter) { - linkMapper = linkMapper || function(el) { - return [el.href, el.title]; - }; - - linksFilter = linksFilter || function() { - return true; - }; - - var links = this; - - return links.unbind("click").click(function() { - // Build the list of images that will be displayed - var link = this, startIndex = 0, filteredLinks, i = 0, length; - filteredLinks = $.grep(links, function(el, i) { - return linksFilter.call(link, el, i); - }); - - // We cannot use jQuery.map() because it flattens the returned array - for (length = filteredLinks.length; i < length; ++i) { - if (filteredLinks[i] == link) startIndex = i; - filteredLinks[i] = linkMapper(filteredLinks[i], i); - } - - return $.slimbox(filteredLinks, startIndex, _options); - }); - }; - - - /* - Internal functions - */ - - function position() { - var l = win.scrollLeft(), w = win.width(); - $([center, bottomContainer]).css("left", l + (w / 2)); - if (compatibleOverlay) $(overlay).css({left: l, top: win.scrollTop(), width: w, height: win.height()}); - } - - function setup(open) { - if (open) { - $("object").add(ie6 ? "select" : "embed").each(function(index, el) { - hiddenElements[index] = [el, el.style.visibility]; - el.style.visibility = "hidden"; - }); - } else { - $.each(hiddenElements, function(index, el) { - el[0].style.visibility = el[1]; - }); - hiddenElements = []; - } - var fn = open ? "bind" : "unbind"; - win[fn]("scroll resize", position); - $(document)[fn]("keydown", keyDown); - } - - function keyDown(event) { - var code = event.keyCode, fn = $.inArray; - // Prevent default keyboard action (like navigating inside the page) - return (fn(code, options.closeKeys) >= 0) ? close() - : (fn(code, options.nextKeys) >= 0) ? next() - : (fn(code, options.previousKeys) >= 0) ? previous() - : false; - } - - function previous() { - return changeImage(prevImage); - } - - function next() { - return changeImage(nextImage); - } - - function changeImage(imageIndex) { - if (imageIndex >= 0) { - activeImage = imageIndex; - activeURL = images[activeImage][0]; - prevImage = (activeImage || (options.loop ? images.length : 0)) - 1; - nextImage = ((activeImage + 1) % images.length) || (options.loop ? 0 : -1); - - stop(); - center.className = "lbLoading"; - - preload = new Image(); - preload.onload = animateBox; - preload.src = activeURL; - } - - return false; - } - - function animateBox() { - center.className = ""; - $(image).css({backgroundImage: "url(" + activeURL + ")", visibility: "hidden", display: "" }); - $(sizer).width(preload.width); - $([sizer, prevLink, nextLink]).height(preload.height); - - $(caption).html(images[activeImage][1] || ""); - $(number).html((((images.length > 1) && options.counterText) || "").replace(/{x}/, activeImage + 1).replace(/{y}/, images.length)); - - if (prevImage >= 0) preloadPrev.src = images[prevImage][0]; - if (nextImage >= 0) preloadNext.src = images[nextImage][0]; - - centerWidth = image.offsetWidth; - centerHeight = image.offsetHeight; - var top = Math.max(0, middle - (centerHeight / 2)); - if (center.offsetHeight != centerHeight) { - $(center).animate({height: centerHeight, top: top}, options.resizeDuration, options.resizeEasing); - } - if (center.offsetWidth != centerWidth) { - $(center).animate({width: centerWidth, marginLeft: -centerWidth/2}, options.resizeDuration, options.resizeEasing); - } - $(center).queue(function() { - $(bottomContainer).css({width: centerWidth, top: top + centerHeight, marginLeft: -centerWidth/2, visibility: "hidden", display: ""}); - animateCaption(); - $(image).css({display: "none", visibility: "", opacity: ""}).fadeIn(options.imageFadeDuration, animateCaption); - }); - } - - function animateCaption() { - if (prevImage >= 0) $(prevLink).show(); - if (nextImage >= 0) $(nextLink).show(); - $(bottom).css("marginTop", -bottom.offsetHeight).animate({marginTop: 0}, options.captionAnimationDuration); - bottomContainer.style.visibility = ""; - } - - function stop() { - preload.onload = null; - preload.src = preloadPrev.src = preloadNext.src = activeURL; - $([center, image, bottom]).stop(true); - $([prevLink, nextLink, image, bottomContainer]).hide(); - } - - function close() { - if (activeImage >= 0) { - stop(); - activeImage = prevImage = nextImage = -1; - $(center).hide(); - $(overlay).stop().fadeOut(options.overlayFadeDuration, setup); - } - - return false; - } - -})(jQuery); \ No newline at end of file
--- a/PalanthirExplorer/libs/slimbox2/slimbox2-rtl.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* SLIMBOX */ - -#lbOverlay { - position: fixed; - z-index: 9999; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: #000; - cursor: pointer; -} - -#lbCenter, #lbBottomContainer { - position: absolute; - z-index: 9999; - overflow: hidden; - background-color: #fff; -} - -.lbLoading { - background: #fff url(loading.gif) no-repeat center; -} - -#lbImage { - position: absolute; - left: 0; - top: 0; - border: 10px solid #fff; - background-repeat: no-repeat; -} - -#lbPrevLink, #lbNextLink { - display: block; - position: absolute; - top: 0; - width: 50%; - outline: none; -} - -#lbPrevLink { - right: 0; -} - -#lbPrevLink:hover { - background: transparent url(prevlabel.gif) no-repeat 100% 15%; -} - -#lbNextLink { - left: 0; -} - -#lbNextLink:hover { - background: transparent url(nextlabel.gif) no-repeat 0 15%; -} - -#lbBottom { - font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; - font-size: 10px; - color: #666; - line-height: 1.4em; - text-align: right; - border: 10px solid #fff; - border-top-style: none; - direction: rtl; -} - -#lbCloseLink { - display: block; - float: left; - width: 66px; - height: 22px; - background: transparent url(closelabel.gif) no-repeat center; - margin: 5px 0; - outline: none; -} - -#lbCaption, #lbNumber { - margin-left: 71px; -} - -#lbCaption { - font-weight: bold; -}
--- a/PalanthirExplorer/libs/slimbox2/slimbox2.css Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* SLIMBOX */ - -#lbOverlay { - position: fixed; - z-index: 9999; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: #000; - cursor: pointer; -} - -#lbCenter, #lbBottomContainer { - position: absolute; - z-index: 9999; - overflow: hidden; - background-color: #fff; -} - -.lbLoading { - background: #fff url(loading.gif) no-repeat center; -} - -#lbImage { - position: absolute; - left: 0; - top: 0; - border: 10px solid #fff; - background-repeat: no-repeat; -} - -#lbPrevLink, #lbNextLink { - display: block; - position: absolute; - top: 0; - width: 50%; - outline: none; -} - -#lbPrevLink { - left: 0; -} - -#lbPrevLink:hover { - background: transparent url(prevlabel.gif) no-repeat 0 15%; -} - -#lbNextLink { - right: 0; -} - -#lbNextLink:hover { - background: transparent url(nextlabel.gif) no-repeat 100% 15%; -} - -#lbBottom { - font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; - font-size: 10px; - color: #666; - line-height: 1.4em; - text-align: left; - border: 10px solid #fff; - border-top-style: none; -} - -#lbCloseLink { - display: block; - float: right; - width: 66px; - height: 22px; - background: transparent url(closelabel.gif) no-repeat center; - margin: 5px 0; - outline: none; -} - -#lbCaption, #lbNumber { - margin-right: 71px; -} - -#lbCaption { - font-weight: bold; -}
--- a/PalanthirExplorer/libs/tree.jquery.js Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1837 +0,0 @@ -// Generated by CoffeeScript 1.3.3 - -/* -Copyright 2012 Marco Braak - -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() { - var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, Json, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, Tree, html_escape, indexOf, toJson, - __slice = [].slice, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - $ = this.jQuery; - - SimpleWidget = (function() { - - SimpleWidget.prototype.defaults = {}; - - function SimpleWidget(el, options) { - this.$el = $(el); - this.options = $.extend({}, this.defaults, options); - this._init(); - } - - SimpleWidget.prototype.destroy = function() { - return this._deinit(); - }; - - SimpleWidget.prototype._init = function() { - return null; - }; - - SimpleWidget.prototype._deinit = function() { - return null; - }; - - SimpleWidget.register = function(widget_class, widget_name) { - var callFunction, createWidget, destroyWidget, getDataKey; - getDataKey = function() { - return "simple_widget_" + widget_name; - }; - createWidget = function($el, options) { - var data_key; - data_key = getDataKey(); - $el.each(function() { - var widget; - widget = new widget_class(this, options); - if (!$.data(this, data_key)) { - return $.data(this, data_key, widget); - } - }); - return $el; - }; - destroyWidget = function($el) { - var data_key; - data_key = getDataKey(); - return $el.each(function() { - var widget; - widget = $.data(this, data_key); - if (widget && (widget instanceof SimpleWidget)) { - widget.destroy(); - } - return $.removeData(this, data_key); - }); - }; - callFunction = function($el, function_name, args) { - var result; - result = null; - $el.each(function() { - var widget, widget_function; - widget = $.data(this, getDataKey()); - if (widget && (widget instanceof SimpleWidget)) { - widget_function = widget[function_name]; - if (widget_function && (typeof widget_function === 'function')) { - return result = widget_function.apply(widget, args); - } - } - }); - return result; - }; - return $.fn[widget_name] = function() { - var $el, args, argument1, function_name, options; - argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - $el = this; - if (argument1 === void 0 || typeof argument1 === 'object') { - options = argument1; - return createWidget($el, options); - } else if (typeof argument1 === 'string' && argument1[0] !== '_') { - function_name = argument1; - if (function_name === 'destroy') { - return destroyWidget($el); - } else { - return callFunction($el, function_name, args); - } - } - }; - }; - - return SimpleWidget; - - })(); - - this.SimpleWidget = SimpleWidget; - - /* - This widget does the same a the mouse widget in jqueryui. - */ - - - MouseWidget = (function(_super) { - - __extends(MouseWidget, _super); - - function MouseWidget() { - return MouseWidget.__super__.constructor.apply(this, arguments); - } - - MouseWidget.is_mouse_handled = false; - - MouseWidget.prototype._init = function() { - this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this)); - return this.is_mouse_started = false; - }; - - MouseWidget.prototype._deinit = function() { - var $document; - this.$el.unbind('mousedown.mousewidget'); - $document = $(document); - $document.unbind('mousemove.mousewidget'); - return $document.unbind('mouseup.mousewidget'); - }; - - MouseWidget.prototype._mouseDown = function(e) { - var $document; - if (MouseWidget.is_mouse_handled) { - return; - } - if (!this.is_mouse_started) { - this._mouseUp(e); - } - if (e.which !== 1) { - return; - } - if (!this._mouseCapture(e)) { - return; - } - this.mouse_down_event = e; - $document = $(document); - $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this)); - $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this)); - e.preventDefault(); - this.is_mouse_handled = true; - return true; - }; - - MouseWidget.prototype._mouseMove = function(e) { - if (this.is_mouse_started) { - this._mouseDrag(e); - return e.preventDefault(); - } - this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false; - if (this.is_mouse_started) { - this._mouseDrag(e); - } else { - this._mouseUp(e); - } - return !this.is_mouse_started; - }; - - MouseWidget.prototype._mouseUp = function(e) { - var $document; - $document = $(document); - $document.unbind('mousemove.mousewidget'); - $document.unbind('mouseup.mousewidget'); - if (this.is_mouse_started) { - this.is_mouse_started = false; - this._mouseStop(e); - } - return false; - }; - - MouseWidget.prototype._mouseCapture = function(e) { - return true; - }; - - MouseWidget.prototype._mouseStart = function(e) { - return null; - }; - - MouseWidget.prototype._mouseDrag = function(e) { - return null; - }; - - MouseWidget.prototype._mouseStop = function(e) { - return null; - }; - - return MouseWidget; - - })(SimpleWidget); - - /* - Copyright 2012 Marco Braak - - 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. - */ - - - this.Tree = {}; - - $ = this.jQuery; - - indexOf = function(array, item) { - var i, value, _i, _len; - if (array.indexOf) { - return array.indexOf(item); - } else { - for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) { - value = array[i]; - if (value === item) { - return i; - } - } - return -1; - } - }; - - this.Tree.indexOf = indexOf; - - Json = {}; - - Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - - Json.meta = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - - Json.quote = function(string) { - Json.escapable.lastIndex = 0; - if (Json.escapable.test(string)) { - return '"' + string.replace(Json.escapable, function(a) { - var c; - c = Json.meta[a]; - return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); - }) + '"'; - } else { - return '"' + string + '"'; - } - }; - - Json.str = function(key, holder) { - var i, k, partial, v, value, _i, _len; - value = holder[key]; - switch (typeof value) { - case 'string': - return Json.quote(value); - case 'number': - if (isFinite(value)) { - return String(value); - } else { - return 'null'; - } - case 'boolean': - case 'null': - return String(value); - case 'object': - if (!value) { - return 'null'; - } - partial = []; - if (Object.prototype.toString.apply(value) === '[object Array]') { - for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { - v = value[i]; - partial[i] = Json.str(i, value) || 'null'; - } - return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); - } - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = Json.str(k, value); - if (v) { - partial.push(Json.quote(k) + ':' + v); - } - } - } - return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); - } - }; - - toJson = function(value) { - return Json.str('', { - '': value - }); - }; - - this.Tree.toJson = toJson; - - html_escape = function(string) { - return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); - }; - - Position = { - getName: function(position) { - if (position === Position.BEFORE) { - return 'before'; - } else if (position === Position.AFTER) { - return 'after'; - } else if (position === Position.INSIDE) { - return 'inside'; - } else { - return 'none'; - } - } - }; - - Position.BEFORE = 1; - - Position.AFTER = 2; - - Position.INSIDE = 3; - - Position.NONE = 4; - - this.Tree.Position = Position; - - Node = (function() { - - function Node(o) { - this.setData(o); - } - - Node.prototype.setData = function(o) { - var key, value; - if (typeof o !== 'object') { - this.name = o; - } else { - for (key in o) { - value = o[key]; - if (key === 'label') { - this.name = value; - } else { - this[key] = value; - } - } - } - this.children = []; - return this.parent = null; - }; - - Node.prototype.initFromData = function(data) { - var addChildren, addNode, - _this = this; - addNode = function(node_data) { - _this.setData(node_data); - if (node_data.children) { - return addChildren(node_data.children); - } - }; - addChildren = function(children_data) { - var child, node, _i, _len; - for (_i = 0, _len = children_data.length; _i < _len; _i++) { - child = children_data[_i]; - node = new Node(''); - node.initFromData(child); - _this.addChild(node); - } - return null; - }; - addNode(data); - return null; - }; - - /* - Create tree from data. - - Structure of data is: - [ - { - label: 'node1', - children: [ - { label: 'child1' }, - { label: 'child2' } - ] - }, - { - label: 'node2' - } - ] - */ - - - Node.prototype.loadFromData = function(data) { - var node, o, _i, _len; - this.children = []; - for (_i = 0, _len = data.length; _i < _len; _i++) { - o = data[_i]; - node = new Node(o); - this.addChild(node); - if (typeof o === 'object' && o.children) { - node.loadFromData(o.children); - } - } - return null; - }; - - /* - Add child. - - tree.addChild( - new Node('child1') - ); - */ - - - Node.prototype.addChild = function(node) { - this.children.push(node); - return node._setParent(this); - }; - - /* - Add child at position. Index starts at 0. - - tree.addChildAtPosition( - new Node('abc'), - 1 - ); - */ - - - Node.prototype.addChildAtPosition = function(node, index) { - this.children.splice(index, 0, node); - return node._setParent(this); - }; - - Node.prototype._setParent = function(parent) { - this.parent = parent; - this.tree = parent.tree; - return this.tree.addNodeToIndex(this); - }; - - /* - Remove child. - - tree.removeChild(tree.children[0]); - */ - - - Node.prototype.removeChild = function(node) { - this.children.splice(this.getChildIndex(node), 1); - return this.tree.removeNodeFromIndex(node); - }; - - /* - Get child index. - - var index = getChildIndex(node); - */ - - - Node.prototype.getChildIndex = function(node) { - return $.inArray(node, this.children); - }; - - /* - Does the tree have children? - - if (tree.hasChildren()) { - // - } - */ - - - Node.prototype.hasChildren = function() { - return this.children.length !== 0; - }; - - /* - Iterate over all the nodes in the tree. - - Calls callback with (node, level). - - The callback must return true to continue the iteration on current node. - - tree.iterate( - function(node, level) { - console.log(node.name); - - // stop iteration after level 2 - return (level <= 2); - } - ); - */ - - - Node.prototype.iterate = function(callback) { - var _iterate, - _this = this; - _iterate = function(node, level) { - var child, result, _i, _len, _ref; - if (node.children) { - _ref = node.children; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - result = callback(child, level); - if (_this.hasChildren() && result) { - _iterate(child, level + 1); - } - } - return null; - } - }; - _iterate(this, 0); - return null; - }; - - /* - Move node relative to another node. - - Argument position: Position.BEFORE, Position.AFTER or Position.Inside - - // move node1 after node2 - tree.moveNode(node1, node2, Position.AFTER); - */ - - - Node.prototype.moveNode = function(moved_node, target_node, position) { - moved_node.parent.removeChild(moved_node); - if (position === Position.AFTER) { - return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); - } else if (position === Position.BEFORE) { - return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); - } else if (position === Position.INSIDE) { - return target_node.addChildAtPosition(moved_node, 0); - } - }; - - /* - Get the tree as data. - */ - - - Node.prototype.getData = function() { - var getDataFromNodes, - _this = this; - getDataFromNodes = function(nodes) { - var data, k, node, tmp_node, v, _i, _len; - data = []; - for (_i = 0, _len = nodes.length; _i < _len; _i++) { - node = nodes[_i]; - tmp_node = {}; - for (k in node) { - v = node[k]; - if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) { - tmp_node[k] = v; - } - } - if (node.hasChildren()) { - tmp_node.children = getDataFromNodes(node.children); - } - data.push(tmp_node); - } - return data; - }; - return getDataFromNodes(this.children); - }; - - Node.prototype.getNodeByName = function(name) { - var result; - result = null; - this.iterate(function(node) { - if (node.name === name) { - result = node; - return false; - } else { - return true; - } - }); - return result; - }; - - Node.prototype.addAfter = function(node_info) { - var child_index, node; - if (!this.parent) { - return null; - } else { - node = new Node(node_info); - child_index = this.parent.getChildIndex(this); - this.parent.addChildAtPosition(node, child_index + 1); - return node; - } - }; - - Node.prototype.addBefore = function(node_info) { - var child_index, node; - if (!this.parent) { - return null; - } else { - node = new Node(node_info); - child_index = this.parent.getChildIndex(this); - return this.parent.addChildAtPosition(node, child_index); - } - }; - - Node.prototype.addParent = function(node_info) { - var child, new_parent, original_parent, _i, _len, _ref; - if (!this.parent) { - return null; - } else { - new_parent = new Node(node_info); - new_parent._setParent(this.tree); - original_parent = this.parent; - _ref = original_parent.children; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - new_parent.addChild(child); - } - original_parent.children = []; - original_parent.addChild(new_parent); - return new_parent; - } - }; - - Node.prototype.remove = function() { - if (this.parent) { - this.parent.removeChild(this); - return this.parent = null; - } - }; - - Node.prototype.append = function(node_info) { - var node; - node = new Node(node_info); - this.addChild(node); - return node; - }; - - Node.prototype.prepend = function(node_info) { - var node; - node = new Node(node_info); - this.addChildAtPosition(node, 0); - return node; - }; - - return Node; - - })(); - - Tree = (function(_super) { - - __extends(Tree, _super); - - function Tree(o) { - Tree.__super__.constructor.call(this, o, null, true); - this.id_mapping = {}; - this.tree = this; - } - - Tree.prototype.getNodeById = function(node_id) { - return this.id_mapping[node_id]; - }; - - Tree.prototype.addNodeToIndex = function(node) { - if (node.id) { - return this.id_mapping[node.id] = node; - } - }; - - Tree.prototype.removeNodeFromIndex = function(node) { - if (node.id) { - return delete this.id_mapping[node.id]; - } - }; - - return Tree; - - })(Node); - - this.Tree.Tree = Tree; - - JqTreeWidget = (function(_super) { - - __extends(JqTreeWidget, _super); - - function JqTreeWidget() { - return JqTreeWidget.__super__.constructor.apply(this, arguments); - } - - JqTreeWidget.prototype.defaults = { - autoOpen: false, - saveState: false, - dragAndDrop: false, - selectable: false, - onCanSelectNode: null, - onSetStateFromStorage: null, - onGetStateFromStorage: null, - onCreateLi: null, - onIsMoveHandle: null, - onCanMove: null, - onCanMoveTo: null, - autoEscape: true, - dataUrl: null - }; - - JqTreeWidget.prototype.toggle = function(node) { - if (node.hasChildren()) { - new FolderElement(node, this.element).toggle(); - } - return this._saveState(); - }; - - JqTreeWidget.prototype.getTree = function() { - return this.tree; - }; - - JqTreeWidget.prototype.selectNode = function(node, must_open_parents) { - return this.select_node_handler.selectNode(node, must_open_parents); - }; - - JqTreeWidget.prototype.getSelectedNode = function() { - return this.selected_node || false; - }; - - JqTreeWidget.prototype.toJson = function() { - return toJson(this.tree.getData()); - }; - - JqTreeWidget.prototype.loadData = function(data, parent_node) { - var child, subtree, _i, _len, _ref; - if (!parent_node) { - this._initTree(data); - } else { - subtree = new Node(''); - subtree._setParent(parent_node.tree); - subtree.loadFromData(data); - _ref = subtree.children; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - parent_node.addChild(child); - } - this._refreshElements(parent_node.parent); - } - if (this.is_dragging) { - return this.dnd_handler.refreshHitAreas(); - } - }; - - JqTreeWidget.prototype.getNodeById = function(node_id) { - return this.tree.getNodeById(node_id); - }; - - JqTreeWidget.prototype.getNodeByName = function(name) { - return this.tree.getNodeByName(name); - }; - - JqTreeWidget.prototype.openNode = function(node, skip_slide) { - if (node.hasChildren()) { - new FolderElement(node, this.element).open(null, skip_slide); - return this._saveState(); - } - }; - - JqTreeWidget.prototype.closeNode = function(node, skip_slide) { - if (node.hasChildren()) { - new FolderElement(node, this.element).close(skip_slide); - return this._saveState(); - } - }; - - JqTreeWidget.prototype.isDragging = function() { - return this.is_dragging; - }; - - JqTreeWidget.prototype.refreshHitAreas = function() { - return this.dnd_handler.refreshHitAreas(); - }; - - JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) { - var new_node; - new_node = existing_node.addAfter(new_node_info); - this._refreshElements(existing_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) { - var new_node; - new_node = existing_node.addBefore(new_node_info); - this._refreshElements(existing_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) { - var new_node; - new_node = existing_node.addParent(new_node_info); - this._refreshElements(new_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.removeNode = function(node) { - var parent; - parent = node.parent; - if (parent) { - node.remove(); - return this._refreshElements(parent.parent); - } - }; - - JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { - var is_already_root_node, node; - if (!parent_node) { - parent_node = this.tree; - } - is_already_root_node = parent_node.hasChildren(); - node = parent_node.append(new_node_info); - if (is_already_root_node) { - this._refreshElements(parent_node); - } else { - this._refreshElements(parent_node.parent); - } - return node; - }; - - JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { - var node; - if (!parent_node) { - parent_node = this.tree; - } - node = parent_node.prepend(new_node_info); - this._refreshElements(parent_node); - return node; - }; - - JqTreeWidget.prototype._init = function() { - JqTreeWidget.__super__._init.call(this); - this.element = this.$el; - this._initData(); - this.element.click($.proxy(this._click, this)); - return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); - }; - - JqTreeWidget.prototype._deinit = function() { - this.element.empty(); - this.element.unbind(); - this.tree = null; - return JqTreeWidget.__super__._deinit.call(this); - }; - - JqTreeWidget.prototype._initData = function() { - var data_url, - _this = this; - if (this.options.data) { - return this._initTree(this.options.data); - } else { - data_url = this.options.dataUrl || this.element.data('url'); - if (data_url) { - return $.ajax({ - url: data_url, - cache: false, - success: function(response) { - var data; - if ($.isArray(response) || typeof response === 'object') { - data = response; - } else { - data = $.parseJSON(response); - } - return _this._initTree(data); - } - }); - } - } - }; - - JqTreeWidget.prototype._initTree = function(data) { - var event; - this.tree = new Tree(); - this.tree.loadFromData(data); - this.selected_node = null; - this.save_state_handler = new SaveStateHandler(this); - this.select_node_handler = new SelectNodeHandler(this); - this.dnd_handler = new DragAndDropHandler(this); - this._openNodes(); - this._refreshElements(); - this.select_node_handler.selectCurrentNode(); - event = $.Event('tree.init'); - return this.element.trigger(event); - }; - - JqTreeWidget.prototype._openNodes = function() { - var max_level; - if (this.options.saveState) { - if (this.save_state_handler.restoreState()) { - return; - } - } - if (this.options.autoOpen === false) { - return; - } else if (this.options.autoOpen === true) { - max_level = -1; - } else { - max_level = parseInt(this.options.autoOpen); - } - return this.tree.iterate(function(node, level) { - node.is_open = true; - return level !== max_level; - }); - }; - - JqTreeWidget.prototype._refreshElements = function(from_node) { - var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element, - _this = this; - if (from_node == null) { - from_node = null; - } - escapeIfNecessary = function(value) { - if (_this.options.autoEscape) { - return html_escape(value); - } else { - return value; - } - }; - createUl = function(is_root_node) { - var class_string; - if (is_root_node) { - class_string = ' class="tree"'; - } else { - class_string = ''; - } - return $("<ul" + class_string + "></ul>"); - }; - createLi = function(node) { - var $li; - if (node.hasChildren()) { - $li = createFolderLi(node); - } else { - $li = createNodeLi(node); - } - if (_this.options.onCreateLi) { - _this.options.onCreateLi(node, $li); - } - return $li; - }; - createNodeLi = function(node) { - var escaped_name; - escaped_name = escapeIfNecessary(node.name); - return $("<li><div><span class=\"title\">" + escaped_name + "</span></div></li>"); - }; - createFolderLi = function(node) { - var button_class, escaped_name, folder_class, getButtonClass, getFolderClass; - getButtonClass = function() { - var classes; - classes = ['toggler']; - if (!node.is_open) { - classes.push('closed'); - } - return classes.join(' '); - }; - getFolderClass = function() { - var classes; - classes = ['folder']; - if (!node.is_open) { - classes.push('closed'); - } - return classes.join(' '); - }; - button_class = getButtonClass(); - folder_class = getFolderClass(); - escaped_name = escapeIfNecessary(node.name); - return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">»</a><span class=\"title\">" + escaped_name + "</span></div></li>"); - }; - doCreateDomElements = function($element, children, is_root_node, is_open) { - var $li, $ul, child, _i, _len; - $ul = createUl(is_root_node); - $element.append($ul); - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - $li = createLi(child); - $ul.append($li); - child.element = $li[0]; - $li.data('node', child); - if (child.hasChildren()) { - doCreateDomElements($li, child.children, false, child.is_open); - } - } - return null; - }; - if (from_node && from_node.parent) { - is_root_node = false; - node_element = this._getNodeElementForNode(from_node); - node_element.getUl().remove(); - $element = node_element.$element; - } else { - from_node = this.tree; - $element = this.element; - $element.empty(); - is_root_node = true; - } - return doCreateDomElements($element, from_node.children, is_root_node, is_root_node); - }; - - JqTreeWidget.prototype._click = function(e) { - var $target, event, node, node_element; - if (e.ctrlKey) { - return; - } - $target = $(e.target); - if ($target.is('.toggler')) { - node_element = this._getNodeElement($target); - if (node_element && node_element.node.hasChildren()) { - node_element.toggle(); - this._saveState(); - e.preventDefault(); - return e.stopPropagation(); - } - } else if ($target.is('div') || $target.is('span')) { - node = this._getNode($target); - if (node) { - if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) { - this.selectNode(node); - event = $.Event('tree.click'); - event.node = node; - return this.element.trigger(event); - } - } - } - }; - - JqTreeWidget.prototype._getNode = function($element) { - var $li; - $li = $element.closest('li'); - if ($li.length === 0) { - return null; - } else { - return $li.data('node'); - } - }; - - JqTreeWidget.prototype._getNodeElementForNode = function(node) { - if (node.hasChildren()) { - return new FolderElement(node, this.element); - } else { - return new NodeElement(node, this.element); - } - }; - - JqTreeWidget.prototype._getNodeElement = function($element) { - var node; - node = this._getNode($element); - if (node) { - return this._getNodeElementForNode(node); - } else { - return null; - } - }; - - JqTreeWidget.prototype._contextmenu = function(e) { - var $div, event, node; - $div = $(e.target).closest('ul.tree div'); - if ($div.length) { - node = this._getNode($div); - if (node) { - e.preventDefault(); - e.stopPropagation(); - event = $.Event('tree.contextmenu'); - event.node = node; - event.click_event = e; - this.element.trigger(event); - return false; - } - } - }; - - JqTreeWidget.prototype._saveState = function() { - if (this.options.saveState) { - return this.save_state_handler.saveState(); - } - }; - - JqTreeWidget.prototype._mouseCapture = function(event) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseCapture(event); - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseStart = function(event) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseStart(event); - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseDrag = function(event) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseDrag(event); - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseStop = function() { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseStop(); - } else { - return false; - } - }; - - JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { - this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); - this.dnd_handler.generateHitAreas(); - return this.dnd_handler.hit_areas; - }; - - return JqTreeWidget; - - })(MouseWidget); - - SimpleWidget.register(JqTreeWidget, 'tree'); - - GhostDropHint = (function() { - - function GhostDropHint(node, $element, position) { - this.$element = $element; - this.node = node; - this.$ghost = $('<li class="ghost"><span class="circle"></span><span class="line"></span></li>'); - if (position === Position.AFTER) { - this.moveAfter(); - } else if (position === Position.BEFORE) { - this.moveBefore(); - } else if (position === Position.INSIDE) { - if (node.hasChildren() && node.is_open) { - this.moveInsideOpenFolder(); - } else { - this.moveInside(); - } - } - } - - GhostDropHint.prototype.remove = function() { - return this.$ghost.remove(); - }; - - GhostDropHint.prototype.moveAfter = function() { - return this.$element.after(this.$ghost); - }; - - GhostDropHint.prototype.moveBefore = function() { - return this.$element.before(this.$ghost); - }; - - GhostDropHint.prototype.moveInsideOpenFolder = function() { - return $(this.node.children[0].element).before(this.$ghost); - }; - - GhostDropHint.prototype.moveInside = function() { - this.$element.after(this.$ghost); - return this.$ghost.addClass('inside'); - }; - - return GhostDropHint; - - })(); - - BorderDropHint = (function() { - - function BorderDropHint($element) { - var $div, width; - $div = $element.children('div'); - width = $element.width() - 4; - this.$hint = $('<span class="border"></span>'); - $div.append(this.$hint); - this.$hint.css({ - width: width, - height: $div.height() - 4 - }); - } - - BorderDropHint.prototype.remove = function() { - return this.$hint.remove(); - }; - - return BorderDropHint; - - })(); - - NodeElement = (function() { - - function NodeElement(node, tree_element) { - this.init(node, tree_element); - } - - NodeElement.prototype.init = function(node, tree_element) { - this.node = node; - this.tree_element = tree_element; - return this.$element = $(node.element); - }; - - NodeElement.prototype.getUl = function() { - return this.$element.children('ul:first'); - }; - - NodeElement.prototype.getSpan = function() { - return this.$element.children('div').find('span.title'); - }; - - NodeElement.prototype.getLi = function() { - return this.$element; - }; - - NodeElement.prototype.addDropHint = function(position) { - if (position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - NodeElement.prototype.select = function() { - return this.getLi().addClass('selected'); - }; - - NodeElement.prototype.deselect = function() { - return this.getLi().removeClass('selected'); - }; - - return NodeElement; - - })(); - - FolderElement = (function(_super) { - - __extends(FolderElement, _super); - - function FolderElement() { - return FolderElement.__super__.constructor.apply(this, arguments); - } - - FolderElement.prototype.toggle = function() { - if (this.node.is_open) { - return this.close(); - } else { - return this.open(); - } - }; - - FolderElement.prototype.open = function(on_finished, skip_slide) { - var doOpen, - _this = this; - if (!this.node.is_open) { - this.node.is_open = true; - this.getButton().removeClass('closed'); - doOpen = function() { - var event; - _this.getLi().removeClass('closed'); - if (on_finished) { - on_finished(); - } - event = $.Event('tree.open'); - event.node = _this.node; - return _this.tree_element.trigger(event); - }; - if (skip_slide) { - return doOpen(); - } else { - return this.getUl().slideDown('fast', doOpen); - } - } - }; - - FolderElement.prototype.close = function(skip_slide) { - var doClose, - _this = this; - if (this.node.is_open) { - this.node.is_open = false; - this.getButton().addClass('closed'); - doClose = function() { - var event; - _this.getLi().addClass('closed'); - event = $.Event('tree.close'); - event.node = _this.node; - return _this.tree_element.trigger(event); - }; - if (skip_slide) { - return doClose(); - } else { - return this.getUl().slideUp('fast', doClose); - } - } - }; - - FolderElement.prototype.getButton = function() { - return this.$element.children('div').find('a.toggler'); - }; - - FolderElement.prototype.addDropHint = function(position) { - if (!this.node.is_open && position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - return FolderElement; - - })(NodeElement); - - DragElement = (function() { - - function DragElement(node, offset_x, offset_y, $tree) { - this.offset_x = offset_x; - this.offset_y = offset_y; - this.$element = $("<span class=\"title tree-dragging\">" + node.name + "</span>"); - this.$element.css("position", "absolute"); - $tree.append(this.$element); - } - - DragElement.prototype.move = function(page_x, page_y) { - return this.$element.offset({ - left: page_x - this.offset_x, - top: page_y - this.offset_y - }); - }; - - DragElement.prototype.remove = function() { - return this.$element.remove(); - }; - - return DragElement; - - })(); - - SaveStateHandler = (function() { - - function SaveStateHandler(tree_widget) { - this.tree_widget = tree_widget; - } - - SaveStateHandler.prototype.saveState = function() { - if (this.tree_widget.options.onSetStateFromStorage) { - return this.tree_widget.options.onSetStateFromStorage(this.getState()); - } else if (typeof localStorage !== "undefined" && localStorage !== null) { - return localStorage.setItem(this.getCookieName(), this.getState()); - } else if ($.cookie) { - return $.cookie(this.getCookieName(), this.getState(), { - path: '/' - }); - } - }; - - SaveStateHandler.prototype.restoreState = function() { - var state; - if (this.tree_widget.options.onGetStateFromStorage) { - state = this.tree_widget.options.onGetStateFromStorage(); - } else if (typeof localStorage !== "undefined" && localStorage !== null) { - state = localStorage.getItem(this.getCookieName()); - } else if ($.cookie) { - state = $.cookie(this.getCookieName(), { - path: '/' - }); - } else { - state = null; - } - if (!state) { - return false; - } else { - this.setState(state); - return true; - } - }; - - SaveStateHandler.prototype.getState = function() { - var open_nodes, selected_node, - _this = this; - open_nodes = []; - this.tree_widget.tree.iterate(function(node) { - if (node.is_open && node.id && node.hasChildren()) { - open_nodes.push(node.id); - } - return true; - }); - selected_node = ''; - if (this.tree_widget.selected_node) { - selected_node = this.tree_widget.selected_node.id; - } - return toJson({ - open_nodes: open_nodes, - selected_node: selected_node - }); - }; - - SaveStateHandler.prototype.setState = function(state) { - var data, open_nodes, selected_node_id, - _this = this; - data = $.parseJSON(state); - if (data) { - open_nodes = data.open_nodes; - selected_node_id = data.selected_node; - return this.tree_widget.tree.iterate(function(node) { - if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { - node.is_open = true; - } - if (selected_node_id && (node.id === selected_node_id)) { - _this.tree_widget.selected_node = node; - } - return true; - }); - } - }; - - SaveStateHandler.prototype.getCookieName = function() { - if (typeof this.tree_widget.options.saveState === 'string') { - return this.tree_widget.options.saveState; - } else { - return 'tree'; - } - }; - - return SaveStateHandler; - - })(); - - SelectNodeHandler = (function() { - - function SelectNodeHandler(tree_widget) { - this.tree_widget = tree_widget; - } - - SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) { - var parent; - if (this.tree_widget.options.selectable) { - if (this.tree_widget.selected_node) { - this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node).deselect(); - this.tree_widget.selected_node = null; - } - if (node) { - this.tree_widget._getNodeElementForNode(node).select(); - this.tree_widget.selected_node = node; - if (must_open_parents) { - parent = this.tree_widget.selected_node.parent; - while (parent) { - if (!parent.is_open) { - this.tree_widget.openNode(parent, true); - } - parent = parent.parent; - } - } - } - if (this.tree_widget.options.saveState) { - return this.tree_widget.save_state_handler.saveState(); - } - } - }; - - SelectNodeHandler.prototype.selectCurrentNode = function() { - var node_element; - if (this.tree_widget.selected_node) { - node_element = this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node); - if (node_element) { - return node_element.select(); - } - } - }; - - return SelectNodeHandler; - - })(); - - DragAndDropHandler = (function() { - - function DragAndDropHandler(tree_widget) { - this.tree_widget = tree_widget; - this.hovered_area = null; - this.$ghost = null; - this.hit_areas = []; - this.is_dragging = false; - } - - DragAndDropHandler.prototype.mouseCapture = function(event) { - var $element, node_element; - $element = $(event.target); - if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) { - return null; - } - node_element = this.tree_widget._getNodeElement($element); - if (node_element && this.tree_widget.options.onCanMove) { - if (!this.tree_widget.options.onCanMove(node_element.node)) { - node_element = null; - } - } - this.current_item = node_element; - return this.current_item !== null; - }; - - DragAndDropHandler.prototype.mouseStart = function(event) { - var offsetX, offsetY, _ref; - this.refreshHitAreas(); - _ref = this.getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; - this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element); - this.is_dragging = true; - this.current_item.$element.addClass('moving'); - return true; - }; - - DragAndDropHandler.prototype.mouseDrag = function(event) { - var area, position_name; - this.drag_element.move(event.pageX, event.pageY); - area = this.findHoveredArea(event.pageX, event.pageY); - if (area && this.tree_widget.options.onCanMoveTo) { - position_name = Position.getName(area.position); - if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { - area = null; - } - } - if (!area) { - this.removeDropHint(); - this.removeHover(); - this.stopOpenFolderTimer(); - } else { - if (this.hovered_area !== area) { - this.hovered_area = area; - this.updateDropHint(); - } - } - return true; - }; - - DragAndDropHandler.prototype.mouseStop = function() { - this.moveItem(); - this.clear(); - this.removeHover(); - this.removeDropHint(); - this.removeHitAreas(); - this.current_item.$element.removeClass('moving'); - this.is_dragging = false; - return false; - }; - - DragAndDropHandler.prototype.getOffsetFromEvent = function(event) { - var element_offset; - element_offset = $(event.target).offset(); - return [event.pageX - element_offset.left, event.pageY - element_offset.top]; - }; - - DragAndDropHandler.prototype.refreshHitAreas = function() { - this.removeHitAreas(); - return this.generateHitAreas(); - }; - - DragAndDropHandler.prototype.removeHitAreas = function() { - return this.hit_areas = []; - }; - - DragAndDropHandler.prototype.clear = function() { - this.drag_element.remove(); - return this.drag_element = null; - }; - - DragAndDropHandler.prototype.removeDropHint = function() { - if (this.previous_ghost) { - return this.previous_ghost.remove(); - } - }; - - DragAndDropHandler.prototype.removeHover = function() { - return this.hovered_area = null; - }; - - DragAndDropHandler.prototype.generateHitAreas = function() { - var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, - _this = this; - positions = []; - last_top = 0; - getTop = function($element) { - return $element.offset().top; - }; - addPosition = function(node, position, top) { - positions.push({ - top: top, - node: node, - position: position - }); - return last_top = top; - }; - groupPositions = function(handle_group) { - var group, position, previous_top, _i, _len; - previous_top = -1; - group = []; - for (_i = 0, _len = positions.length; _i < _len; _i++) { - position = positions[_i]; - if (position.top !== previous_top) { - if (group.length) { - handle_group(group, previous_top, position.top); - } - previous_top = position.top; - group = []; - } - group.push(position); - } - return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height()); - }; - handleNode = function(node, next_node, $element) { - var top; - top = getTop($element); - if (node === _this.current_item.node) { - addPosition(node, Position.NONE, top); - } else { - addPosition(node, Position.INSIDE, top); - } - if (next_node === _this.current_item.node || node === _this.current_item.node) { - return addPosition(node, Position.NONE, top); - } else { - return addPosition(node, Position.AFTER, top); - } - }; - handleOpenFolder = function(node, $element) { - if (node === _this.current_item.node) { - return false; - } - if (node.children[0] !== _this.current_item.node) { - addPosition(node, Position.INSIDE, getTop($element)); - } - return true; - }; - handleAfterOpenFolder = function(node, next_node, $element) { - if (node === _this.current_item.node || next_node === _this.current_item.node) { - return addPosition(node, Position.NONE, last_top); - } else { - return addPosition(node, Position.AFTER, last_top); - } - }; - handleClosedFolder = function(node, next_node, $element) { - var top; - top = getTop($element); - if (node === _this.current_item.node) { - return addPosition(node, Position.NONE, top); - } else { - addPosition(node, Position.INSIDE, top); - if (next_node !== _this.current_item.node) { - return addPosition(node, Position.AFTER, top); - } - } - }; - handleFirstNode = function(node, $element) { - if (node !== _this.current_item.node) { - return addPosition(node, Position.BEFORE, getTop($(node.element))); - } - }; - this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); - hit_areas = []; - groupPositions(function(positions_in_group, top, bottom) { - var area_height, area_top, position, _i, _len; - area_height = (bottom - top) / positions_in_group.length; - area_top = top; - for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { - position = positions_in_group[_i]; - hit_areas.push({ - top: area_top, - bottom: area_top + area_height, - node: position.node, - position: position.position - }); - area_top += area_height; - } - return null; - }); - return this.hit_areas = hit_areas; - }; - - DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { - var is_first_node, iterate, - _this = this; - is_first_node = true; - iterate = function(node, next_node) { - var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref; - must_iterate_inside = (node.is_open || !node.element) && node.hasChildren(); - if (node.element) { - $element = $(node.element); - if (!$element.is(':visible')) { - return; - } - if (is_first_node) { - handle_first_node(node, $element); - is_first_node = false; - } - if (!node.hasChildren()) { - handle_node(node, next_node, $element); - } else if (node.is_open) { - if (!handle_open_folder(node, $element)) { - must_iterate_inside = false; - } - } else { - handle_closed_folder(node, next_node, $element); - } - } - if (must_iterate_inside) { - children_length = node.children.length; - _ref = node.children; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - child = _ref[i]; - if (i === (children_length - 1)) { - iterate(node.children[i], null); - } else { - iterate(node.children[i], node.children[i + 1]); - } - } - if (node.is_open) { - return handle_after_open_folder(node, next_node, $element); - } - } - }; - return iterate(this.tree_widget.tree); - }; - - DragAndDropHandler.prototype.findHoveredArea = function(x, y) { - var area, high, low, mid, tree_offset; - tree_offset = this.tree_widget.element.offset(); - if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) { - return null; - } - low = 0; - high = this.hit_areas.length; - while (low < high) { - mid = (low + high) >> 1; - area = this.hit_areas[mid]; - if (y < area.top) { - high = mid; - } else if (y > area.bottom) { - low = mid + 1; - } else { - return area; - } - } - return null; - }; - - DragAndDropHandler.prototype.updateDropHint = function() { - var node, node_element; - this.stopOpenFolderTimer(); - if (!this.hovered_area) { - return; - } - node = this.hovered_area.node; - if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) { - this.startOpenFolderTimer(node); - } - this.removeDropHint(); - node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node); - return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); - }; - - DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { - var openFolder, - _this = this; - openFolder = function() { - return _this.tree_widget._getNodeElementForNode(folder).open(function() { - _this.refreshHitAreas(); - return _this.updateDropHint(); - }); - }; - return this.open_folder_timer = setTimeout(openFolder, 500); - }; - - DragAndDropHandler.prototype.stopOpenFolderTimer = function() { - if (this.open_folder_timer) { - clearTimeout(this.open_folder_timer); - return this.open_folder_timer = null; - } - }; - - DragAndDropHandler.prototype.moveItem = function() { - var doMove, event, moved_node, position, previous_parent, target_node, - _this = this; - if (this.hovered_area && this.hovered_area.position !== Position.NONE) { - moved_node = this.current_item.node; - target_node = this.hovered_area.node; - position = this.hovered_area.position; - previous_parent = moved_node.parent; - if (position === Position.INSIDE) { - this.hovered_area.node.is_open = true; - } - doMove = function() { - _this.tree_widget.tree.moveNode(moved_node, target_node, position); - _this.tree_widget.element.empty(); - return _this.tree_widget._refreshElements(); - }; - event = $.Event('tree.move'); - event.move_info = { - moved_node: moved_node, - target_node: target_node, - position: Position.getName(position), - previous_parent: previous_parent, - do_move: doMove - }; - this.tree_widget.element.trigger(event); - if (!event.isDefaultPrevented()) { - return doMove(); - } - } - }; - - return DragAndDropHandler; - - })(); - - this.Tree.Node = Node; - -}).call(this);
--- a/PalanthirServer/DicomIntegerPixelAccessor.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomIntegerPixelAccessor.h" - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#include "../Core/PalanthirException.h" -#include "FromDcmtkBridge.h" -#include <boost/lexical_cast.hpp> -#include <limits> - -namespace Palanthir -{ - DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values, - const void* pixelData, - size_t size) : - pixelData_(pixelData), - size_(size) - { - unsigned int bitsAllocated; - unsigned int bitsStored; - unsigned int highBit; - unsigned int pixelRepresentation; - - try - { - width_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Columns").AsString()); - height_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Rows").AsString()); - samplesPerPixel_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "SamplesPerPixel").AsString()); - bitsAllocated = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsAllocated").AsString()); - bitsStored = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsStored").AsString()); - highBit = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "HighBit").AsString()); - pixelRepresentation = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "PixelRepresentation").AsString()); - } - catch (boost::bad_lexical_cast) - { - throw PalanthirException(ErrorCode_NotImplemented); - } - - frame_ = 0; - try - { - numberOfFrames_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "NumberOfFrames").AsString()); - } - catch (PalanthirException) - { - // If the tag "NumberOfFrames" is absent, assume there is a single frame - numberOfFrames_ = 1; - } - catch (boost::bad_lexical_cast) - { - throw PalanthirException(ErrorCode_NotImplemented); - } - - if ((bitsAllocated != 8 && bitsAllocated != 16 && - bitsAllocated != 24 && bitsAllocated != 32) || - numberOfFrames_ == 0) - { - throw PalanthirException(ErrorCode_NotImplemented); - } - - if (bitsAllocated > 32 || - bitsStored >= 32) - { - // Not available, as the accessor internally uses int32_t values - throw PalanthirException(ErrorCode_NotImplemented); - } - - if (samplesPerPixel_ != 1) - { - throw PalanthirException(ErrorCode_NotImplemented); - } - - if (width_ * height_ * bitsAllocated / 8 * numberOfFrames_ != size) - { - throw PalanthirException(ErrorCode_NotImplemented); - } - - /*printf("%d %d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated, - bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/ - - bytesPerPixel_ = bitsAllocated / 8; - shift_ = highBit + 1 - bitsStored; - - if (pixelRepresentation) - { - mask_ = (1 << (bitsStored - 1)) - 1; - signMask_ = (1 << (bitsStored - 1)); - } - else - { - mask_ = (1 << bitsStored) - 1; - signMask_ = 0; - } - - rowOffset_ = width_ * bytesPerPixel_; - frameOffset_ = height_ * width_ * bytesPerPixel_; - } - - - void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min, - int32_t& max) const - { - if (height_ == 0 || width_ == 0) - { - min = max = 0; - return; - } - - min = std::numeric_limits<int32_t>::max(); - max = std::numeric_limits<int32_t>::min(); - - for (unsigned int y = 0; y < height_; y++) - { - for (unsigned int x = 0; x < width_; x++) - { - int32_t v = GetValue(x, y); - if (v < min) - min = v; - if (v > max) - max = v; - } - } - } - - - int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, unsigned int y) const - { - assert(x < width_ && y < height_); - - const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + - y * rowOffset_ + x * bytesPerPixel_ + frame_ * frameOffset_; - - int32_t v; - v = pixel[0]; - if (bytesPerPixel_ >= 2) - v = v + (static_cast<int32_t>(pixel[1]) << 8); - if (bytesPerPixel_ >= 3) - v = v + (static_cast<int32_t>(pixel[2]) << 16); - if (bytesPerPixel_ >= 4) - v = v + (static_cast<int32_t>(pixel[3]) << 24); - - v = (v >> shift_) & mask_; - - if (v & signMask_) - { - // Signed value: Not implemented yet - //throw PalanthirException(ErrorCode_NotImplemented); - v = 0; - } - - return v; - } - - - void DicomIntegerPixelAccessor::SetCurrentFrame(unsigned int frame) - { - if (frame >= numberOfFrames_) - { - throw PalanthirException(ErrorCode_ParameterOutOfRange); - } - - frame_ = frame; - } - -}
--- a/PalanthirServer/DicomIntegerPixelAccessor.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Core/DicomFormat/DicomMap.h" - -#include <stdint.h> - -namespace Palanthir -{ - class DicomIntegerPixelAccessor - { - private: - unsigned int width_; - unsigned int height_; - unsigned int samplesPerPixel_; - unsigned int numberOfFrames_; - const void* pixelData_; - size_t size_; - - uint8_t shift_; - uint32_t signMask_; - uint32_t mask_; - size_t bytesPerPixel_; - unsigned int frame_; - - size_t frameOffset_; - size_t rowOffset_; - - public: - DicomIntegerPixelAccessor(const DicomMap& values, - const void* pixelData, - size_t size); - - unsigned int GetWidth() const - { - return width_; - } - - unsigned int GetHeight() const - { - return height_; - } - - unsigned int GetNumberOfFrames() const - { - return numberOfFrames_; - } - - unsigned int GetCurrentFrame() const - { - return frame_; - } - - void SetCurrentFrame(unsigned int frame); - - void GetExtremeValues(int32_t& min, - int32_t& max) const; - - int32_t GetValue(unsigned int x, unsigned int y) const; - }; -}
--- a/PalanthirServer/DicomProtocol/DicomFindAnswers.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomFindAnswers.h" - -#include "../FromDcmtkBridge.h" - -namespace Palanthir -{ - void DicomFindAnswers::Clear() - { - for (size_t i = 0; i < items_.size(); i++) - { - delete items_[i]; - } - } - - void DicomFindAnswers::Reserve(size_t size) - { - if (size > items_.size()) - { - items_.reserve(size); - } - } - - void DicomFindAnswers::ToJson(Json::Value& target) const - { - target = Json::arrayValue; - - for (size_t i = 0; i < GetSize(); i++) - { - Json::Value answer(Json::objectValue); - FromDcmtkBridge::ToJson(answer, GetAnswer(i)); - target.append(answer); - } - } -}
--- a/PalanthirServer/DicomProtocol/DicomFindAnswers.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Core/DicomFormat/DicomMap.h" - -#include <vector> -#include <json/json.h> - -namespace Palanthir -{ - class DicomFindAnswers - { - private: - std::vector<DicomMap*> items_; - - public: - ~DicomFindAnswers() - { - Clear(); - } - - void Clear(); - - void Reserve(size_t index); - - void Add(const DicomMap& map) - { - items_.push_back(map.Clone()); - } - - size_t GetSize() const - { - return items_.size(); - } - - const DicomMap& GetAnswer(size_t index) const - { - return *items_.at(index); - } - - void ToJson(Json::Value& target) const; - }; -}
--- a/PalanthirServer/DicomProtocol/DicomServer.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,305 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomServer.h" - -#include "../../Core/PalanthirException.h" -#include "../../Core/Toolbox.h" -#include "../Internals/CommandDispatcher.h" - -#include <boost/thread.hpp> -#include <dcmtk/dcmdata/dcdict.h> - - -namespace Palanthir -{ - struct DicomServer::PImpl - { - boost::thread thread_; - - //std::set< - }; - - - namespace Internals - { - OFLogger Logger = OFLog::getLogger("dcmtk.apps.storescp"); - } - - - void DicomServer::ServerThread(DicomServer* server) - { - /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */ - dcmDisableGethostbyaddr.set(OFTrue); - - /* make sure data dictionary is loaded */ - if (!dcmDataDict.isDictionaryLoaded()) - { - OFLOG_WARN(Internals::Logger, "no data dictionary loaded, check environment variable: " - << DCM_DICT_ENVIRONMENT_VARIABLE); - } - - /* initialize network, i.e. create an instance of T_ASC_Network*. */ - T_ASC_Network *net; - OFCondition cond = ASC_initializeNetwork - (NET_ACCEPTOR, OFstatic_cast(int, server->port_), /*opt_acse_timeout*/ 30, &net); - if (cond.bad()) - { - OFString temp_str; - OFLOG_ERROR(Internals::Logger, "cannot create network: " << DimseCondition::dump(temp_str, cond)); - throw PalanthirException("Cannot create network"); - } - - OFLOG_WARN(Internals::Logger, "DICOM server started"); - - server->started_ = true; - - while (server->continue_) - { - /* receive an association and acknowledge or reject it. If the association was */ - /* acknowledged, offer corresponding services and invoke one or more if required. */ - std::auto_ptr<Internals::CommandDispatcher> dispatcher(Internals::AcceptAssociation(*server, net)); - - if (dispatcher.get() != NULL) - { - if (server->isThreaded_) - { - server->bagOfDispatchers_.Add(dispatcher.release()); - } - else - { - IRunnableBySteps::RunUntilDone(*dispatcher); - } - } - } - - OFLOG_WARN(Internals::Logger, "DICOM server stopping"); - - /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ - /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ - cond = ASC_dropNetwork(&net); - if (cond.bad()) - { - OFString temp_str; - OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); - } - } - - - DicomServer::DicomServer() : pimpl_(new PImpl) - { - aet_ = "ANY-SCP"; - port_ = 104; - findRequestHandlerFactory_ = NULL; - moveRequestHandlerFactory_ = NULL; - storeRequestHandlerFactory_ = NULL; - applicationEntityFilter_ = NULL; - checkCalledAet_ = true; - clientTimeout_ = 30; - isThreaded_ = true; - } - - DicomServer::~DicomServer() - { - Stop(); - } - - void DicomServer::SetPortNumber(uint16_t port) - { - Stop(); - port_ = port; - } - - uint16_t DicomServer::GetPortNumber() const - { - return port_; - } - - void DicomServer::SetThreaded(bool isThreaded) - { - Stop(); - isThreaded_ = isThreaded; - } - - bool DicomServer::IsThreaded() const - { - return isThreaded_; - } - - void DicomServer::SetClientTimeout(uint32_t timeout) - { - Stop(); - clientTimeout_ = timeout; - } - - uint32_t DicomServer::GetClientTimeout() const - { - return clientTimeout_; - } - - - void DicomServer::SetCalledApplicationEntityTitleCheck(bool check) - { - Stop(); - checkCalledAet_ = check; - } - - bool DicomServer::HasCalledApplicationEntityTitleCheck() const - { - return checkCalledAet_; - } - - void DicomServer::SetApplicationEntityTitle(const std::string& aet) - { - if (aet.size() == 0) - { - throw PalanthirException("Too short AET"); - } - - for (size_t i = 0; i < aet.size(); i++) - { - if (!isalnum(aet[i]) && aet[i] != '-') - { - throw PalanthirException("Only alphanumeric characters are allowed in AET"); - } - } - - Stop(); - aet_ = aet; - } - - const std::string& DicomServer::GetApplicationEntityTitle() const - { - return aet_; - } - - void DicomServer::SetFindRequestHandlerFactory(IFindRequestHandlerFactory& factory) - { - Stop(); - findRequestHandlerFactory_ = &factory; - } - - bool DicomServer::HasFindRequestHandlerFactory() const - { - return (findRequestHandlerFactory_ != NULL); - } - - IFindRequestHandlerFactory& DicomServer::GetFindRequestHandlerFactory() const - { - if (HasFindRequestHandlerFactory()) - { - return *findRequestHandlerFactory_; - } - else - { - throw PalanthirException("No C-FIND request handler factory"); - } - } - - void DicomServer::SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& factory) - { - Stop(); - moveRequestHandlerFactory_ = &factory; - } - - bool DicomServer::HasMoveRequestHandlerFactory() const - { - return (moveRequestHandlerFactory_ != NULL); - } - - IMoveRequestHandlerFactory& DicomServer::GetMoveRequestHandlerFactory() const - { - if (HasMoveRequestHandlerFactory()) - { - return *moveRequestHandlerFactory_; - } - else - { - throw PalanthirException("No C-MOVE request handler factory"); - } - } - - void DicomServer::SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& factory) - { - Stop(); - storeRequestHandlerFactory_ = &factory; - } - - bool DicomServer::HasStoreRequestHandlerFactory() const - { - return (storeRequestHandlerFactory_ != NULL); - } - - IStoreRequestHandlerFactory& DicomServer::GetStoreRequestHandlerFactory() const - { - if (HasStoreRequestHandlerFactory()) - { - return *storeRequestHandlerFactory_; - } - else - { - throw PalanthirException("No C-STORE request handler factory"); - } - } - - void DicomServer::SetApplicationEntityFilter(IApplicationEntityFilter& factory) - { - Stop(); - applicationEntityFilter_ = &factory; - } - - bool DicomServer::HasApplicationEntityFilter() const - { - return (applicationEntityFilter_ != NULL); - } - - IApplicationEntityFilter& DicomServer::GetApplicationEntityFilter() const - { - if (HasApplicationEntityFilter()) - { - return *applicationEntityFilter_; - } - else - { - throw PalanthirException("No application entity filter"); - } - } - - void DicomServer::Start() - { - Stop(); - continue_ = true; - started_ = false; - pimpl_->thread_ = boost::thread(ServerThread, this); - - while (!started_) - { - Toolbox::USleep(50000); // Wait 50ms - } - } - - void DicomServer::Stop() - { - continue_ = false; - pimpl_->thread_.join(); - - bagOfDispatchers_.StopAll(); - } -}
--- a/PalanthirServer/DicomProtocol/DicomServer.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IFindRequestHandlerFactory.h" -#include "IMoveRequestHandlerFactory.h" -#include "IStoreRequestHandlerFactory.h" -#include "IApplicationEntityFilter.h" -#include "../../Core/MultiThreading/BagOfRunnablesBySteps.h" - -#include <boost/shared_ptr.hpp> -#include <boost/noncopyable.hpp> - -namespace Palanthir -{ - class DicomServer : public boost::noncopyable - { - private: - struct PImpl; - boost::shared_ptr<PImpl> pimpl_; - - bool checkCalledAet_; - std::string aet_; - uint16_t port_; - bool continue_; - bool started_; - uint32_t clientTimeout_; - bool isThreaded_; - IFindRequestHandlerFactory* findRequestHandlerFactory_; - IMoveRequestHandlerFactory* moveRequestHandlerFactory_; - IStoreRequestHandlerFactory* storeRequestHandlerFactory_; - IApplicationEntityFilter* applicationEntityFilter_; - - BagOfRunnablesBySteps bagOfDispatchers_; // This is used iff the server is threaded - - static void ServerThread(DicomServer* server); - - public: - DicomServer(); - - ~DicomServer(); - - void SetPortNumber(uint16_t port); - uint16_t GetPortNumber() const; - - void SetThreaded(bool isThreaded); - bool IsThreaded() const; - - void SetClientTimeout(uint32_t timeout); - uint32_t GetClientTimeout() const; - - void SetCalledApplicationEntityTitleCheck(bool check); - bool HasCalledApplicationEntityTitleCheck() const; - - void SetApplicationEntityTitle(const std::string& aet); - const std::string& GetApplicationEntityTitle() const; - - void SetFindRequestHandlerFactory(IFindRequestHandlerFactory& handler); - bool HasFindRequestHandlerFactory() const; - IFindRequestHandlerFactory& GetFindRequestHandlerFactory() const; - - void SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& handler); - bool HasMoveRequestHandlerFactory() const; - IMoveRequestHandlerFactory& GetMoveRequestHandlerFactory() const; - - void SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& handler); - bool HasStoreRequestHandlerFactory() const; - IStoreRequestHandlerFactory& GetStoreRequestHandlerFactory() const; - - void SetApplicationEntityFilter(IApplicationEntityFilter& handler); - bool HasApplicationEntityFilter() const; - IApplicationEntityFilter& GetApplicationEntityFilter() const; - - void Start(); - - void Stop(); - }; - -}
--- a/PalanthirServer/DicomProtocol/DicomUserConnection.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,639 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomUserConnection.h" - -#include "../../Core/PalanthirException.h" -#include "../ToDcmtkBridge.h" -#include "../FromDcmtkBridge.h" - -#include <dcmtk/dcmnet/assoc.h> -#include <dcmtk/dcmnet/dimse.h> -#include <dcmtk/dcmdata/dcistrmb.h> -#include <dcmtk/dcmdata/dcistrmf.h> -#include <dcmtk/dcmdata/dcfilefo.h> -#include <dcmtk/dcmnet/diutil.h> - -#include <set> - - - -#ifdef _WIN32 -/** - * "The maximum length, in bytes, of the string returned in the buffer - * pointed to by the name parameter is dependent on the namespace provider, - * but this string must be 256 bytes or less. - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms738527(v=vs.85).aspx - **/ -#define HOST_NAME_MAX 256 -#endif - - -namespace Palanthir -{ - struct DicomUserConnection::PImpl - { - // Connection state - T_ASC_Network* net_; - T_ASC_Parameters* params_; - T_ASC_Association* assoc_; - - bool IsOpen() const - { - return assoc_ != NULL; - } - - void CheckIsOpen() const; - - void Store(DcmInputStream& is); - }; - - - static void Check(const OFCondition& cond) - { - if (cond.bad()) - { - throw PalanthirException("DicomUserConnection: " + std::string(cond.text())); - } - } - - void DicomUserConnection::PImpl::CheckIsOpen() const - { - if (!IsOpen()) - { - throw PalanthirException("DicomUserConnection: First open the connection"); - } - } - - - void DicomUserConnection::CheckIsOpen() const - { - pimpl_->CheckIsOpen(); - } - - - void DicomUserConnection::CopyParameters(const DicomUserConnection& other) - { - Close(); - localAet_ = other.localAet_; - distantAet_ = other.distantAet_; - distantHost_ = other.distantHost_; - distantPort_ = other.distantPort_; - } - - - void DicomUserConnection::SetupPresentationContexts() - { - // The preferred abstract syntax - std::string preferredSyntax = UID_LittleEndianImplicitTransferSyntax; - - // Fallback abstract syntaxes - std::set<std::string> abstractSyntaxes; - abstractSyntaxes.insert(UID_LittleEndianExplicitTransferSyntax); - abstractSyntaxes.insert(UID_BigEndianExplicitTransferSyntax); - abstractSyntaxes.insert(UID_LittleEndianImplicitTransferSyntax); - abstractSyntaxes.erase(preferredSyntax); - assert(abstractSyntaxes.size() == 2); - - // Transfer syntaxes for C-ECHO, C-FIND and C-MOVE - std::vector<std::string> transferSyntaxes; - transferSyntaxes.push_back(UID_VerificationSOPClass); - transferSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); - transferSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); - transferSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); - - // TODO: Allow the set below to be configured - std::set<std::string> uselessSyntaxes; - uselessSyntaxes.insert(UID_BlendingSoftcopyPresentationStateStorage); - uselessSyntaxes.insert(UID_GrayscaleSoftcopyPresentationStateStorage); - uselessSyntaxes.insert(UID_ColorSoftcopyPresentationStateStorage); - uselessSyntaxes.insert(UID_PseudoColorSoftcopyPresentationStateStorage); - - // Add the transfer syntaxes for C-STORE - for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs - 1; i++) - { - // Test to make some room to allow the ECHO and FIND requests - if (uselessSyntaxes.find(dcmShortSCUStorageSOPClassUIDs[i]) == uselessSyntaxes.end()) - { - transferSyntaxes.push_back(dcmShortSCUStorageSOPClassUIDs[i]); - } - } - - // Flatten the fallback abstract syntaxes array - const char* asPreferred[1] = { preferredSyntax.c_str() }; - const char* asFallback[2]; - std::set<std::string>::const_iterator it = abstractSyntaxes.begin(); - asFallback[0] = it->c_str(); - it++; - asFallback[1] = it->c_str(); - - unsigned int presentationContextId = 1; - for (size_t i = 0; i < transferSyntaxes.size(); i++) - { - Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, - transferSyntaxes[i].c_str(), asPreferred, 1)); - presentationContextId += 2; - - Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, - transferSyntaxes[i].c_str(), asFallback, 2)); - presentationContextId += 2; - } - } - - - void DicomUserConnection::PImpl::Store(DcmInputStream& is) - { - CheckIsOpen(); - - DcmFileFormat dcmff; - Check(dcmff.read(is, EXS_Unknown, EGL_noChange, DCM_MaxReadLength)); - - // Figure out which SOP class and SOP instance is encapsulated in the file - DIC_UI sopClass; - DIC_UI sopInstance; - if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) - { - throw PalanthirException("DicomUserConnection: Unable to find the SOP class and instance"); - } - - // Figure out which of the accepted presentation contexts should be used - int presID = ASC_findAcceptedPresentationContextID(assoc_, sopClass); - if (presID == 0) - { - const char *modalityName = dcmSOPClassUIDToModality(sopClass); - if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); - if (!modalityName) modalityName = "unknown SOP class"; - throw PalanthirException("DicomUserConnection: No presentation context for modality " + - std::string(modalityName)); - } - - // Prepare the transmission of data - T_DIMSE_C_StoreRQ req; - memset(&req, 0, sizeof(req)); - req.MessageID = assoc_->nextMsgID++; - strcpy(req.AffectedSOPClassUID, sopClass); - strcpy(req.AffectedSOPInstanceUID, sopInstance); - req.DataSetType = DIMSE_DATASET_PRESENT; - req.Priority = DIMSE_PRIORITY_MEDIUM; - - // Finally conduct transmission of data - T_DIMSE_C_StoreRSP rsp; - DcmDataset* statusDetail = NULL; - Check(DIMSE_storeUser(assoc_, presID, &req, - NULL, dcmff.getDataset(), /*progressCallback*/ NULL, NULL, - /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, - &rsp, &statusDetail, NULL)); - - if (statusDetail != NULL) - { - delete statusDetail; - } - } - - - static void FindCallback( - /* in */ - void *callbackData, - T_DIMSE_C_FindRQ *request, /* original find request */ - int responseCount, - T_DIMSE_C_FindRSP *response, /* pending response received */ - DcmDataset *responseIdentifiers /* pending response identifiers */ - ) - { - DicomFindAnswers& answers = *(DicomFindAnswers*) callbackData; - - if (responseIdentifiers != NULL) - { - DicomMap m; - FromDcmtkBridge::Convert(m, *responseIdentifiers); - answers.Add(m); - } - } - - void DicomUserConnection::Find(DicomFindAnswers& result, - FindRootModel model, - const DicomMap& fields) - { - CheckIsOpen(); - - const char* sopClass; - std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); - switch (model) - { - case FindRootModel_Patient: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); - sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; - - // Accession number - if (!fields.HasTag(0x0008, 0x0050)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); - - // Patient ID - if (!fields.HasTag(0x0010, 0x0020)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); - - break; - - case FindRootModel_Study: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); - sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; - - // Accession number - if (!fields.HasTag(0x0008, 0x0050)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); - - // Study instance UID - if (!fields.HasTag(0x0020, 0x000d)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); - - break; - - case FindRootModel_Series: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); - sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; - - // Accession number - if (!fields.HasTag(0x0008, 0x0050)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); - - // Study instance UID - if (!fields.HasTag(0x0020, 0x000d)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); - - // Series instance UID - if (!fields.HasTag(0x0020, 0x000e)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); - - break; - - case FindRootModel_Instance: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); - sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; - - // Accession number - if (!fields.HasTag(0x0008, 0x0050)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); - - // Study instance UID - if (!fields.HasTag(0x0020, 0x000d)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); - - // Series instance UID - if (!fields.HasTag(0x0020, 0x000e)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); - - // SOP Instance UID - if (!fields.HasTag(0x0008, 0x0018)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); - - break; - - default: - throw PalanthirException(ErrorCode_ParameterOutOfRange); - } - - // Figure out which of the accepted presentation contexts should be used - int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); - if (presID == 0) - { - throw PalanthirException("DicomUserConnection: The C-FIND command is not supported by the distant AET"); - } - - T_DIMSE_C_FindRQ request; - memset(&request, 0, sizeof(request)); - request.MessageID = pimpl_->assoc_->nextMsgID++; - strcpy(request.AffectedSOPClassUID, sopClass); - request.DataSetType = DIMSE_DATASET_PRESENT; - request.Priority = DIMSE_PRIORITY_MEDIUM; - - T_DIMSE_C_FindRSP response; - DcmDataset* statusDetail = NULL; - OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(), - FindCallback, &result, - /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, - &response, &statusDetail); - - if (statusDetail) - { - delete statusDetail; - } - - Check(cond); - } - - - void DicomUserConnection::FindPatient(DicomFindAnswers& result, - const DicomMap& fields) - { - // Only keep the filters from "fields" that are related to the patient - DicomMap s; - fields.ExtractPatientInformation(s); - Find(result, FindRootModel_Patient, s); - } - - void DicomUserConnection::FindStudy(DicomFindAnswers& result, - const DicomMap& fields) - { - // Only keep the filters from "fields" that are related to the study - DicomMap s; - fields.ExtractStudyInformation(s); - - s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); - s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); - - Find(result, FindRootModel_Study, s); - } - - void DicomUserConnection::FindSeries(DicomFindAnswers& result, - const DicomMap& fields) - { - // Only keep the filters from "fields" that are related to the series - DicomMap s; - fields.ExtractSeriesInformation(s); - - s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); - s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); - s.CopyTagIfExists(fields, DicomTag::STUDY_UID); - - Find(result, FindRootModel_Series, s); - } - - void DicomUserConnection::FindInstance(DicomFindAnswers& result, - const DicomMap& fields) - { - // Only keep the filters from "fields" that are related to the instance - DicomMap s; - fields.ExtractInstanceInformation(s); - - s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); - s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); - s.CopyTagIfExists(fields, DicomTag::STUDY_UID); - s.CopyTagIfExists(fields, DicomTag::SERIES_UID); - - Find(result, FindRootModel_Instance, s); - } - - - void DicomUserConnection::Move(const std::string& targetAet, - const DicomMap& fields) - { - CheckIsOpen(); - - const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; - std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); - - // Figure out which of the accepted presentation contexts should be used - int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); - if (presID == 0) - { - throw PalanthirException("DicomUserConnection: The C-MOVE command is not supported by the distant AET"); - } - - T_DIMSE_C_MoveRQ request; - memset(&request, 0, sizeof(request)); - request.MessageID = pimpl_->assoc_->nextMsgID++; - strcpy(request.AffectedSOPClassUID, sopClass); - request.DataSetType = DIMSE_DATASET_PRESENT; - request.Priority = DIMSE_PRIORITY_MEDIUM; - strncpy(request.MoveDestination, targetAet.c_str(), sizeof(DIC_AE) / sizeof(char)); - - T_DIMSE_C_MoveRSP response; - DcmDataset* statusDetail = NULL; - DcmDataset* responseIdentifiers = NULL; - OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset.get(), - NULL, NULL, - /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, - pimpl_->net_, NULL, NULL, - &response, &statusDetail, &responseIdentifiers); - - if (statusDetail) - { - delete statusDetail; - } - - if (responseIdentifiers) - { - delete responseIdentifiers; - } - - Check(cond); - } - - - DicomUserConnection::DicomUserConnection() : pimpl_(new PImpl) - { - localAet_ = "STORESCU"; - distantAet_ = "ANY-SCP"; - distantPort_ = 104; - distantHost_ = "127.0.0.1"; - - pimpl_->net_ = NULL; - pimpl_->params_ = NULL; - pimpl_->assoc_ = NULL; - } - - DicomUserConnection::~DicomUserConnection() - { - Close(); - } - - void DicomUserConnection::SetLocalApplicationEntityTitle(const std::string& aet) - { - Close(); - localAet_ = aet; - } - - void DicomUserConnection::SetDistantApplicationEntityTitle(const std::string& aet) - { - Close(); - distantAet_ = aet; - } - - - void DicomUserConnection::SetDistantHost(const std::string& host) - { - if (host.size() > HOST_NAME_MAX - 10) - { - throw PalanthirException("Distant host name is too long"); - } - - Close(); - distantHost_ = host; - } - - void DicomUserConnection::SetDistantPort(uint16_t port) - { - Close(); - distantPort_ = port; - } - - void DicomUserConnection::Open() - { - Close(); - - Check(ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ 30, &pimpl_->net_)); - Check(ASC_createAssociationParameters(&pimpl_->params_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU)); - - // Set this application's title and the called application's title in the params - Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), distantAet_.c_str(), NULL)); - - // Set the network addresses of the local and distant entities - char localHost[HOST_NAME_MAX]; - gethostname(localHost, HOST_NAME_MAX - 1); - - char distantHostAndPort[HOST_NAME_MAX]; - -#ifdef _MSC_VER - _snprintf -#else - snprintf -#endif - (distantHostAndPort, HOST_NAME_MAX - 1, "%s:%d", distantHost_.c_str(), distantPort_); - - Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, distantHostAndPort)); - - // Set various options - Check(ASC_setTransportLayerType(pimpl_->params_, /*opt_secureConnection*/ false)); - - SetupPresentationContexts(); - - // Do the association - Check(ASC_requestAssociation(pimpl_->net_, pimpl_->params_, &pimpl_->assoc_)); - - if (ASC_countAcceptedPresentationContexts(pimpl_->params_) == 0) - { - throw PalanthirException("DicomUserConnection: No Acceptable Presentation Contexts"); - } - } - - void DicomUserConnection::Close() - { - if (pimpl_->assoc_ != NULL) - { - ASC_releaseAssociation(pimpl_->assoc_); - ASC_destroyAssociation(&pimpl_->assoc_); - pimpl_->assoc_ = NULL; - pimpl_->params_ = NULL; - } - else - { - if (pimpl_->params_ != NULL) - { - ASC_destroyAssociationParameters(&pimpl_->params_); - pimpl_->params_ = NULL; - } - } - - if (pimpl_->net_ != NULL) - { - ASC_dropNetwork(&pimpl_->net_); - pimpl_->net_ = NULL; - } - } - - bool DicomUserConnection::IsOpen() const - { - return pimpl_->IsOpen(); - } - - void DicomUserConnection::Store(const char* buffer, size_t size) - { - // Prepare an input stream for the memory buffer - DcmInputBufferStream is; - if (size > 0) - is.setBuffer(buffer, size); - is.setEos(); - - pimpl_->Store(is); - } - - void DicomUserConnection::Store(const std::string& buffer) - { - if (buffer.size() > 0) - Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); - else - Store(NULL, 0); - } - - void DicomUserConnection::StoreFile(const std::string& path) - { - // Prepare an input stream for the file - DcmInputFileStream is(path.c_str()); - pimpl_->Store(is); - } - - bool DicomUserConnection::Echo() - { - CheckIsOpen(); - DIC_US status; - Check(DIMSE_echoUser(pimpl_->assoc_, pimpl_->assoc_->nextMsgID++, - /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, - &status, NULL)); - return status == STATUS_Success; - } - - - void DicomUserConnection::MoveSeries(const std::string& targetAet, - const DicomMap& findResult) - { - DicomMap simplified; - simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); - simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); - Move(targetAet, simplified); - } - - void DicomUserConnection::MoveSeries(const std::string& targetAet, - const std::string& studyUid, - const std::string& seriesUid) - { - DicomMap map; - map.SetValue(DicomTag::STUDY_UID, studyUid); - map.SetValue(DicomTag::SERIES_UID, seriesUid); - Move(targetAet, map); - } - - void DicomUserConnection::MoveInstance(const std::string& targetAet, - const DicomMap& findResult) - { - DicomMap simplified; - simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); - simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); - simplified.SetValue(DicomTag::INSTANCE_UID, findResult.GetValue(DicomTag::INSTANCE_UID)); - Move(targetAet, simplified); - } - - void DicomUserConnection::MoveInstance(const std::string& targetAet, - const std::string& studyUid, - const std::string& seriesUid, - const std::string& instanceUid) - { - DicomMap map; - map.SetValue(DicomTag::STUDY_UID, studyUid); - map.SetValue(DicomTag::SERIES_UID, seriesUid); - map.SetValue(DicomTag::INSTANCE_UID, instanceUid); - Move(targetAet, map); - } - - void DicomUserConnection::SetConnectionTimeout(uint32_t seconds) - { - dcmConnectionTimeout.set(seconds); - } - -}
--- a/PalanthirServer/DicomProtocol/DicomUserConnection.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "DicomFindAnswers.h" - -#include <stdint.h> -#include <boost/shared_ptr.hpp> -#include <boost/noncopyable.hpp> - -namespace Palanthir -{ - class DicomUserConnection : public boost::noncopyable - { - private: - enum FindRootModel - { - FindRootModel_Patient, - FindRootModel_Study, - FindRootModel_Series, - FindRootModel_Instance - }; - - struct PImpl; - boost::shared_ptr<PImpl> pimpl_; - - // Connection parameters - std::string localAet_; - std::string distantAet_; - std::string distantHost_; - uint16_t distantPort_; - - void CheckIsOpen() const; - - void SetupPresentationContexts(); - - void Find(DicomFindAnswers& result, - FindRootModel model, - const DicomMap& fields); - - void Move(const std::string& targetAet, - const DicomMap& fields); - - public: - DicomUserConnection(); - - ~DicomUserConnection(); - - void CopyParameters(const DicomUserConnection& other); - - void SetLocalApplicationEntityTitle(const std::string& aet); - - const std::string& GetLocalApplicationEntityTitle() const - { - return localAet_; - } - - void SetDistantApplicationEntityTitle(const std::string& aet); - - const std::string& GetDistantApplicationEntityTitle() const - { - return distantAet_; - } - - void SetDistantHost(const std::string& host); - - const std::string& GetDistantHost() const - { - return distantHost_; - } - - void SetDistantPort(uint16_t port); - - uint16_t GetDistantPort() const - { - return distantPort_; - } - - void Open(); - - void Close(); - - bool IsOpen() const; - - bool Echo(); - - void Store(const char* buffer, size_t size); - - void Store(const std::string& buffer); - - void StoreFile(const std::string& path); - - void FindPatient(DicomFindAnswers& result, - const DicomMap& fields); - - void FindStudy(DicomFindAnswers& result, - const DicomMap& fields); - - void FindSeries(DicomFindAnswers& result, - const DicomMap& fields); - - void FindInstance(DicomFindAnswers& result, - const DicomMap& fields); - - void MoveSeries(const std::string& targetAet, - const DicomMap& findResult); - - void MoveSeries(const std::string& targetAet, - const std::string& studyUid, - const std::string& seriesUid); - - void MoveInstance(const std::string& targetAet, - const DicomMap& findResult); - - void MoveInstance(const std::string& targetAet, - const std::string& studyUid, - const std::string& seriesUid, - const std::string& instanceUid); - - static void SetConnectionTimeout(uint32_t seconds); - }; -}
--- a/PalanthirServer/DicomProtocol/IApplicationEntityFilter.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <string> - -namespace Palanthir -{ - class IApplicationEntityFilter - { - public: - virtual ~IApplicationEntityFilter() - { - } - - virtual bool IsAllowed(const std::string& callingIp, - const std::string& callingAet) = 0; - }; -}
--- a/PalanthirServer/DicomProtocol/IFindRequestHandler.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "DicomFindAnswers.h" - -#include <vector> -#include <string> - - -namespace Palanthir -{ - class IFindRequestHandler - { - public: - virtual ~IFindRequestHandler() - { - } - - virtual void Handle(const DicomMap& input, - DicomFindAnswers& answers) = 0; - }; -}
--- a/PalanthirServer/DicomProtocol/IFindRequestHandlerFactory.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IFindRequestHandler.h" - -namespace Palanthir -{ - class IFindRequestHandlerFactory - { - public: - virtual ~IFindRequestHandlerFactory() - { - } - - virtual IFindRequestHandler* ConstructFindRequestHandler() = 0; - }; -}
--- a/PalanthirServer/DicomProtocol/IMoveRequestHandler.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Core/DicomFormat/DicomMap.h" - -#include <vector> -#include <string> - - -namespace Palanthir -{ - class IMoveRequestIterator - { - public: - enum Status - { - Status_Success, - Status_Failure, - Status_Warning - }; - - virtual ~IMoveRequestIterator() - { - } - - virtual unsigned int GetSubOperationCount() const = 0; - - virtual Status DoNext() = 0; - }; - - - class IMoveRequestHandler - { - public: - virtual ~IMoveRequestHandler() - { - } - - virtual IMoveRequestIterator* Handle(const std::string& target, - const DicomMap& input) = 0; - }; - -}
--- a/PalanthirServer/DicomProtocol/IMoveRequestHandlerFactory.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IMoveRequestHandler.h" - -namespace Palanthir -{ - class IMoveRequestHandlerFactory - { - public: - virtual ~IMoveRequestHandlerFactory() - { - } - - virtual IMoveRequestHandler* ConstructMoveRequestHandler() = 0; - }; -}
--- a/PalanthirServer/DicomProtocol/IStoreRequestHandler.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Core/DicomFormat/DicomMap.h" - -#include <vector> -#include <string> -#include <json/json.h> - -namespace Palanthir -{ - class IStoreRequestHandler - { - public: - virtual ~IStoreRequestHandler() - { - } - - virtual void Handle(const std::vector<uint8_t>& dicomFile, - const DicomMap& dicomSummary, - const Json::Value& dicomJson, - const std::string& distantAet) = 0; - }; -}
--- a/PalanthirServer/DicomProtocol/IStoreRequestHandlerFactory.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IStoreRequestHandler.h" - -namespace Palanthir -{ - class IStoreRequestHandlerFactory - { - public: - virtual ~IStoreRequestHandlerFactory() - { - } - - virtual IStoreRequestHandler* ConstructStoreRequestHandler() = 0; - }; -}
--- a/PalanthirServer/FromDcmtkBridge.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,599 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "FromDcmtkBridge.h" - -#include "ToDcmtkBridge.h" -#include "DicomIntegerPixelAccessor.h" -#include "../Core/PalanthirException.h" -#include "../Core/PngWriter.h" -#include "../Core/DicomFormat/DicomString.h" -#include "../Core/DicomFormat/DicomNullValue.h" - -#include <boost/locale.hpp> -#include <boost/lexical_cast.hpp> - -#include <dcmtk/dcmdata/dcdicent.h> -#include <dcmtk/dcmdata/dcdict.h> -#include <dcmtk/dcmdata/dcelem.h> -#include <dcmtk/dcmdata/dcfilefo.h> -#include <dcmtk/dcmdata/dcistrmb.h> -#include <dcmtk/dcmdata/dcsequen.h> -#include <dcmtk/dcmdata/dcvrfd.h> -#include <dcmtk/dcmdata/dcvrfl.h> -#include <dcmtk/dcmdata/dcvrsl.h> -#include <dcmtk/dcmdata/dcvrss.h> -#include <dcmtk/dcmdata/dcvrul.h> -#include <dcmtk/dcmdata/dcvrus.h> - -#include <boost/math/special_functions/round.hpp> - -namespace Palanthir -{ - void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset) - { - target.Clear(); - for (unsigned long i = 0; i < dataset.card(); i++) - { - DcmElement* element = dataset.getElement(i); - if (element && element->isLeaf()) - { - target.SetValue(element->getTag().getGTag(), - element->getTag().getETag(), - ConvertLeafElement(*element)); - } - } - } - - - DicomTag FromDcmtkBridge::GetTag(const DcmElement& element) - { - return DicomTag(element.getGTag(), element.getETag()); - } - - - DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element) - { - if (!element.isLeaf()) - { - throw PalanthirException("Only applicable to leaf elements"); - } - - if (element.isaString()) - { - char *c; - if (element.getString(c).good() && - c != NULL) - { - std::string s(c); - std::string utf8; - try - { - utf8 = boost::locale::conv::to_utf<char>(s, "ISO-8859-1"); // TODO Parameter? - } - catch (std::runtime_error&) - { - // Bad input string or bad encoding - utf8 = s; - } - - return new DicomString(utf8); - } - else - { - return new DicomNullValue; - } - } - - try - { - // http://support.dcmtk.org/docs/dcvr_8h-source.html - switch (element.getVR()) - { - - /** - * TODO. - **/ - - case EVR_DS: // decimal string - case EVR_IS: // integer string - case EVR_OB: // other byte - case EVR_OF: // other float - case EVR_OW: // other word - case EVR_AS: // age string - case EVR_AT: // attribute tag - case EVR_DA: // date string - case EVR_DT: // date time string - case EVR_TM: // time string - case EVR_UN: // unknown value representation - return new DicomNullValue(); - - - /** - * String types, should never happen at this point because of - * "element.isaString()". - **/ - - case EVR_AE: // application entity title - case EVR_CS: // code string - case EVR_SH: // short string - case EVR_LO: // long string - case EVR_ST: // short text - case EVR_LT: // long text - case EVR_UT: // unlimited text - case EVR_PN: // person name - case EVR_UI: // unique identifier - return new DicomNullValue(); - - - /** - * Numerical types - **/ - - case EVR_SL: // signed long - { - Sint32 f; - if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - case EVR_SS: // signed short - { - Sint16 f; - if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - case EVR_UL: // unsigned long - { - Uint32 f; - if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - case EVR_US: // unsigned short - { - Uint16 f; - if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - case EVR_FL: // float single-precision - { - Float32 f; - if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - case EVR_FD: // float double-precision - { - Float64 f; - if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) - { - return new DicomString(boost::lexical_cast<std::string>(f)); - } - else - { - return new DicomNullValue(); - } - } - - - /** - * Sequence types, should never occur at this point because of - * "element.isLeaf()". - **/ - - case EVR_SQ: // sequence of items - return new DicomNullValue; - - - /** - * Internal to DCMTK. - **/ - - case EVR_ox: // OB or OW depending on context - case EVR_xs: // SS or US depending on context - case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) - case EVR_na: // na="not applicable", for data which has no VR - case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor - case EVR_item: // used internally for items - case EVR_metainfo: // used internally for meta info datasets - case EVR_dataset: // used internally for datasets - case EVR_fileFormat: // used internally for DICOM files - case EVR_dicomDir: // used internally for DICOMDIR objects - case EVR_dirRecord: // used internally for DICOMDIR records - case EVR_pixelSQ: // used internally for pixel sequences in a compressed image - case EVR_pixelItem: // used internally for pixel items in a compressed image - case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) - case EVR_PixelData: // used internally for uncompressed pixeld data - case EVR_OverlayData: // used internally for overlay data - case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR - return new DicomNullValue; - - - /** - * Default case. - **/ - - default: - return new DicomNullValue; - } - } - catch (boost::bad_lexical_cast) - { - return new DicomNullValue; - } - } - - - static void StoreElement(Json::Value& target, - DcmElement& element, - unsigned int maxStringLength); - - static void StoreItem(Json::Value& target, - DcmItem& item, - unsigned int maxStringLength) - { - target = Json::Value(Json::objectValue); - - for (unsigned long i = 0; i < item.card(); i++) - { - DcmElement* element = item.getElement(i); - StoreElement(target, *element, maxStringLength); - } - } - - - static void StoreElement(Json::Value& target, - DcmElement& element, - unsigned int maxStringLength) - { - assert(target.type() == Json::objectValue); - - DicomTag tag(FromDcmtkBridge::GetTag(element)); - const std::string tagName = FromDcmtkBridge::GetName(tag); - const std::string formattedTag = tag.Format(); - - if (element.isLeaf()) - { - Json::Value value(Json::objectValue); - value["Name"] = tagName; - - std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); - if (v->IsNull()) - { - value["Type"] = "Null"; - value["Value"] = Json::nullValue; - } - else - { - std::string s = v->AsString(); - if (maxStringLength == 0 || - s.size() <= maxStringLength) - { - value["Type"] = "String"; - value["Value"] = s; - } - else - { - value["Type"] = "TooLong"; - value["Value"] = Json::nullValue; - } - } - - target[formattedTag] = value; - } - else - { - Json::Value children(Json::arrayValue); - - // "All subclasses of DcmElement except for DcmSequenceOfItems - // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset - // etc. are not." The following cast is thus OK. - DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element); - - for (unsigned long i = 0; i < sequence.card(); i++) - { - DcmItem* child = sequence.getItem(i); - Json::Value& v = children.append(Json::objectValue); - StoreItem(v, *child, maxStringLength); - } - - target[formattedTag]["Name"] = tagName; - target[formattedTag]["Type"] = "Sequence"; - target[formattedTag]["Value"] = children; - } - } - - - void FromDcmtkBridge::ToJson(Json::Value& root, - DcmDataset& dataset, - unsigned int maxStringLength) - { - StoreItem(root, dataset, maxStringLength); - } - - - - void FromDcmtkBridge::ToJson(Json::Value& target, - const std::string& path, - unsigned int maxStringLength) - { - DcmFileFormat dicom; - if (!dicom.loadFile(path.c_str()).good()) - { - throw PalanthirException(ErrorCode_BadFileFormat); - } - else - { - FromDcmtkBridge::ToJson(target, *dicom.getDataset(), maxStringLength); - } - } - - - static void ExtractPngImagePreview(std::string& result, - DicomIntegerPixelAccessor& accessor) - { - PngWriter w; - - int32_t min, max; - accessor.GetExtremeValues(min, max); - - std::vector<uint8_t> image(accessor.GetWidth() * accessor.GetHeight(), 0); - if (min != max) - { - uint8_t* pixel = &image[0]; - for (unsigned int y = 0; y < accessor.GetHeight(); y++) - { - for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) - { - int32_t v = accessor.GetValue(x, y); - *pixel = static_cast<uint8_t>( - boost::math::lround(static_cast<float>(v - min) / - static_cast<float>(max - min) * 255.0f)); - } - } - } - - w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), - accessor.GetWidth(), PixelFormat_Grayscale8, &image[0]); - } - - - template <typename T> - static void ExtractPngImageTruncate(std::string& result, - DicomIntegerPixelAccessor& accessor, - PixelFormat format) - { - PngWriter w; - - std::vector<T> image(accessor.GetWidth() * accessor.GetHeight(), 0); - T* pixel = &image[0]; - for (unsigned int y = 0; y < accessor.GetHeight(); y++) - { - for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) - { - int32_t v = accessor.GetValue(x, y); - if (v < std::numeric_limits<T>::min()) - *pixel = std::numeric_limits<T>::min(); - else if (v > std::numeric_limits<T>::max()) - *pixel = std::numeric_limits<T>::max(); - else - *pixel = static_cast<T>(v); - } - } - - w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), - accessor.GetWidth() * sizeof(T), format, &image[0]); - } - - - void FromDcmtkBridge::ExtractPngImage(std::string& result, - DcmDataset& dataset, - unsigned int frame, - ImageExtractionMode mode) - { - // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data - - std::auto_ptr<DicomIntegerPixelAccessor> accessor; - - DicomMap m; - FromDcmtkBridge::Convert(m, dataset); - - DcmElement* e; - if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DicomTag::PIXEL_DATA), e).good() && - e != NULL) - { - Uint8* pixData = NULL; - if (e->getUint8Array(pixData) == EC_Normal) - { - accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); - accessor->SetCurrentFrame(frame); - } - } - - PixelFormat format; - switch (mode) - { - case ImageExtractionMode_Preview: - case ImageExtractionMode_UInt8: - format = PixelFormat_Grayscale8; - break; - - case ImageExtractionMode_UInt16: - format = PixelFormat_Grayscale16; - break; - - default: - throw PalanthirException(ErrorCode_NotImplemented); - } - - if (accessor.get() == NULL || - accessor->GetWidth() == 0 || - accessor->GetHeight() == 0) - { - PngWriter w; - w.WriteToMemory(result, 0, 0, 0, format, NULL); - } - else - { - switch (mode) - { - case ImageExtractionMode_Preview: - ExtractPngImagePreview(result, *accessor); - break; - - case ImageExtractionMode_UInt8: - ExtractPngImageTruncate<uint8_t>(result, *accessor, format); - break; - - case ImageExtractionMode_UInt16: - ExtractPngImageTruncate<uint16_t>(result, *accessor, format); - break; - - default: - throw PalanthirException(ErrorCode_NotImplemented); - } - } - } - - - void FromDcmtkBridge::ExtractPngImage(std::string& result, - const std::string& dicomContent, - unsigned int frame, - ImageExtractionMode mode) - { - DcmInputBufferStream is; - if (dicomContent.size() > 0) - { - is.setBuffer(&dicomContent[0], dicomContent.size()); - } - is.setEos(); - - DcmFileFormat dicom; - if (dicom.read(is).good()) - { - ExtractPngImage(result, *dicom.getDataset(), frame, mode); - } - else - { - throw PalanthirException(ErrorCode_BadFileFormat); - } - } - - - - std::string FromDcmtkBridge::GetName(const DicomTag& t) - { - DcmTagKey tag(t.GetGroup(), t.GetElement()); - const DcmDataDictionary& dict = dcmDataDict.rdlock(); - const DcmDictEntry* entry = dict.findEntry(tag, NULL); - - std::string s("Unknown"); - if (entry != NULL) - { - s = std::string(entry->getTagName()); - } - - dcmDataDict.unlock(); - return s; - } - - - DicomTag FromDcmtkBridge::FindTag(const char* name) - { - const DcmDataDictionary& dict = dcmDataDict.rdlock(); - const DcmDictEntry* entry = dict.findEntry(name); - - if (entry == NULL) - { - dcmDataDict.unlock(); - throw PalanthirException("Unknown DICOM tag"); - } - else - { - DcmTagKey key = entry->getKey(); - DicomTag tag(key.getGroup(), key.getElement()); - dcmDataDict.unlock(); - return tag; - } - } - - - void FromDcmtkBridge::Print(FILE* fp, const DicomMap& m) - { - for (DicomMap::Map::const_iterator - it = m.map_.begin(); it != m.map_.end(); it++) - { - DicomTag t = it->first; - std::string s = it->second->AsString(); - printf("0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); - } - } - - - void FromDcmtkBridge::ToJson(Json::Value& result, - const DicomMap& values) - { - if (result.type() != Json::objectValue) - { - throw PalanthirException(ErrorCode_BadParameterType); - } - - result.clear(); - - for (DicomMap::Map::const_iterator - it = values.map_.begin(); it != values.map_.end(); it++) - { - result[GetName(it->first)] = it->second->AsString(); - } - } -}
--- a/PalanthirServer/FromDcmtkBridge.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Core/DicomFormat/DicomMap.h" -#include <dcmtk/dcmdata/dcdatset.h> -#include <json/json.h> - -namespace Palanthir -{ - enum ImageExtractionMode - { - ImageExtractionMode_Preview, - ImageExtractionMode_UInt8, - ImageExtractionMode_UInt16 - }; - - class FromDcmtkBridge - { - public: - static void Convert(DicomMap& target, DcmDataset& dataset); - - static DicomTag GetTag(const DcmElement& element); - - static DicomValue* ConvertLeafElement(DcmElement& element); - - static void ToJson(Json::Value& target, - DcmDataset& dataset, - unsigned int maxStringLength = 256); - - static void ToJson(Json::Value& target, - const std::string& path, - unsigned int maxStringLength = 256); - - static void ExtractPngImage(std::string& result, - DcmDataset& dataset, - unsigned int frame, - ImageExtractionMode mode); - - static void ExtractPngImage(std::string& result, - const std::string& dicomContent, - unsigned int frame, - ImageExtractionMode mode); - - static std::string GetName(const DicomTag& tag); - - static DicomTag FindTag(const char* name); - - static DicomTag FindTag(const std::string& name) - { - return FindTag(name.c_str()); - } - - static bool HasTag(const DicomMap& fields, - const std::string& tagName) - { - return fields.HasTag(FindTag(tagName)); - } - - static const DicomValue& GetValue(const DicomMap& fields, - const std::string& tagName) - { - return fields.GetValue(FindTag(tagName)); - } - - static void SetValue(DicomMap& target, - const std::string& tagName, - DicomValue* value) - { - target.SetValue(FindTag(tagName), value); - } - - static void Print(FILE* fp, - const DicomMap& m); - - static void ToJson(Json::Value& result, - const DicomMap& values); - }; -}
--- a/PalanthirServer/Internals/CommandDispatcher.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,403 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "CommandDispatcher.h" - -#include "FindScp.h" -#include "StoreScp.h" -#include "MoveScp.h" -#include "../../Core/Toolbox.h" - -#include <dcmtk/dcmnet/dcasccfg.h> /* for class DcmAssociationConfiguration */ - -static OFBool opt_rejectWithoutImplementationUID = OFFalse; - - -namespace Palanthir -{ - namespace Internals - { - extern OFLogger Logger; - - - - OFCondition AssociationCleanup(T_ASC_Association *assoc) - { - OFString temp_str; - OFCondition cond = ASC_dropSCPAssociation(assoc); - if (cond.bad()) - { - OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); - return cond; - } - - cond = ASC_destroyAssociation(&assoc); - if (cond.bad()) - { - OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); - return cond; - } - - return cond; - } - - - - CommandDispatcher* AcceptAssociation(const DicomServer& server, T_ASC_Network *net) - { - DcmAssociationConfiguration asccfg; - char buf[BUFSIZ]; - T_ASC_Association *assoc; - OFCondition cond; - OFString sprofile; - OFString temp_str; - - std::vector<const char*> knownAbstractSyntaxes; - - // For C-STORE - if (server.HasStoreRequestHandlerFactory()) - { - knownAbstractSyntaxes.push_back(UID_VerificationSOPClass); - } - - // For C-FIND - if (server.HasFindRequestHandlerFactory()) - { - knownAbstractSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); - knownAbstractSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); - } - - // For C-MOVE - if (server.HasMoveRequestHandlerFactory()) - { - knownAbstractSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); - } - - const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - int numTransferSyntaxes = 0; - - cond = ASC_receiveAssociation(net, &assoc, - /*opt_maxPDU*/ ASC_DEFAULTMAXPDU, - NULL, NULL, - /*opt_secureConnection*/ OFFalse, - DUL_NOBLOCK, 1); - - if (cond == DUL_NOASSOCIATIONREQUEST) - { - // Timeout - AssociationCleanup(assoc); - return NULL; - } - - // if some kind of error occured, take care of it - if (cond.bad()) - { - OFLOG_ERROR(Internals::Logger, "Receiving Association failed: " << DimseCondition::dump(temp_str, cond)); - // no matter what kind of error occurred, we need to do a cleanup - AssociationCleanup(assoc); - return NULL; - } - - OFLOG_INFO(Internals::Logger, "Association Received"); - - transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; - transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; - transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; - numTransferSyntaxes = 3; - - /* accept the Verification SOP Class if presented */ - cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), transferSyntaxes, numTransferSyntaxes); - if (cond.bad()) - { - OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); - AssociationCleanup(assoc); - return NULL; - } - - /* the array of Storage SOP Class UIDs comes from dcuid.h */ - cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes); - if (cond.bad()) - { - OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); - AssociationCleanup(assoc); - return NULL; - } - - /* set our app title */ - ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); - - /* acknowledge or reject this association */ - cond = ASC_getApplicationContextName(assoc->params, buf); - if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) - { - /* reject: the application context name is not supported */ - T_ASC_RejectParameters rej = - { - ASC_RESULT_REJECTEDPERMANENT, - ASC_SOURCE_SERVICEUSER, - ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED - }; - - OFLOG_INFO(Internals::Logger, "Association Rejected: Bad Application Context Name: " << buf); - cond = ASC_rejectAssociation(assoc, &rej); - if (cond.bad()) - { - OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); - } - AssociationCleanup(assoc); - return NULL; - } - - /* check the AETs */ - { - DIC_AE callingTitle_C; - DIC_AE calledTitle_C; - DIC_AE callingIP_C; - DIC_AE calledIP_C; - if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() || - ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad()) - { - T_ASC_RejectParameters rej = - { - ASC_RESULT_REJECTEDPERMANENT, - ASC_SOURCE_SERVICEUSER, - ASC_REASON_SU_NOREASON - }; - ASC_rejectAssociation(assoc, &rej); - AssociationCleanup(assoc); - return NULL; - } - - std::string callingIP(OFSTRING_GUARD(callingIP_C)); - std::string callingTitle(OFSTRING_GUARD(callingTitle_C)); - std::string calledTitle(OFSTRING_GUARD(calledTitle_C)); - Toolbox::ToUpperCase(callingIP); - Toolbox::ToUpperCase(callingTitle); - Toolbox::ToUpperCase(calledTitle); - - if (server.HasCalledApplicationEntityTitleCheck() && - calledTitle != server.GetApplicationEntityTitle()) - { - T_ASC_RejectParameters rej = - { - ASC_RESULT_REJECTEDPERMANENT, - ASC_SOURCE_SERVICEUSER, - ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED - }; - ASC_rejectAssociation(assoc, &rej); - AssociationCleanup(assoc); - return NULL; - } - - if (server.HasApplicationEntityFilter() && - !server.GetApplicationEntityFilter().IsAllowed(callingIP, callingTitle)) - { - T_ASC_RejectParameters rej = - { - ASC_RESULT_REJECTEDPERMANENT, - ASC_SOURCE_SERVICEUSER, - ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED - }; - ASC_rejectAssociation(assoc, &rej); - AssociationCleanup(assoc); - return NULL; - } - } - - if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0) - { - /* reject: the no implementation Class UID provided */ - T_ASC_RejectParameters rej = - { - ASC_RESULT_REJECTEDPERMANENT, - ASC_SOURCE_SERVICEUSER, - ASC_REASON_SU_NOREASON - }; - - OFLOG_INFO(Internals::Logger, "Association Rejected: No Implementation Class UID provided"); - cond = ASC_rejectAssociation(assoc, &rej); - if (cond.bad()) - { - OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); - } - AssociationCleanup(assoc); - return NULL; - } - - { - cond = ASC_acknowledgeAssociation(assoc); - if (cond.bad()) - { - OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); - AssociationCleanup(assoc); - return NULL; - } - OFLOG_INFO(Internals::Logger, "Association Acknowledged (Max Send PDV: " << assoc->sendPDVLength << ")"); - if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) - OFLOG_INFO(Internals::Logger, " (but no valid presentation contexts)"); - } - - return new CommandDispatcher(server, assoc); - } - - bool CommandDispatcher::Step() - /* - * This function receives DIMSE commmands over the network connection - * and handles these commands correspondingly. Note that in case of - * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed. - */ - { - bool finished = false; - - // receive a DIMSE command over the network, with a timeout of 1 second - DcmDataset *statusDetail = NULL; - T_ASC_PresentationContextID presID = 0; - T_DIMSE_Message msg; - - OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail); - elapsedTimeSinceLastCommand_++; - - // if the command which was received has extra status - // detail information, dump this information - if (statusDetail != NULL) - { - OFLOG_WARN(Internals::Logger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } - - if (cond == DIMSE_OUTOFRESOURCES) - { - finished = true; - } - else if (cond == DIMSE_NODATAAVAILABLE) - { - // Timeout due to DIMSE_NONBLOCKING - if (clientTimeout_ != 0 && - elapsedTimeSinceLastCommand_ >= clientTimeout_) - { - // This timeout is actually a client timeout - finished = true; - } - } - else if (cond == EC_Normal) - { - // Reset the client timeout counter - elapsedTimeSinceLastCommand_ = 0; - - // in case we received a valid message, process this command - // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ - switch (msg.CommandField) - { - case DIMSE_C_ECHO_RQ: - // process C-ECHO-Request - cond = EchoScp(assoc_, &msg, presID); - break; - - case DIMSE_C_STORE_RQ: - // process C-STORE-Request - if (server_.HasStoreRequestHandlerFactory()) - { - std::auto_ptr<IStoreRequestHandler> handler - (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler()); - cond = Internals::storeScp(assoc_, &msg, presID, *handler); - } - else - cond = DIMSE_BADCOMMANDTYPE; // Should never happen - break; - - case DIMSE_C_MOVE_RQ: - // process C-MOVE-Request - if (server_.HasMoveRequestHandlerFactory()) - { - std::auto_ptr<IMoveRequestHandler> handler - (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler()); - cond = Internals::moveScp(assoc_, &msg, presID, *handler); - } - else - cond = DIMSE_BADCOMMANDTYPE; // Should never happen - break; - - case DIMSE_C_FIND_RQ: - // process C-FIND-Request - if (server_.HasFindRequestHandlerFactory()) - { - std::auto_ptr<IFindRequestHandler> handler - (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); - cond = Internals::findScp(assoc_, &msg, presID, *handler); - } - else - cond = DIMSE_BADCOMMANDTYPE; // Should never happen - break; - - default: - // we cannot handle this kind of message - cond = DIMSE_BADCOMMANDTYPE; - OFLOG_ERROR(Internals::Logger, "cannot handle command: 0x" - << STD_NAMESPACE hex << OFstatic_cast(unsigned, msg.CommandField)); - break; - } - } - else - { - // Bad status, which indicates the closing of the connection by - // the peer or a network error - finished = true; - } - - if (finished) - { - if (cond == DUL_PEERREQUESTEDRELEASE) - { - OFLOG_INFO(Internals::Logger, "Association Release"); - ASC_acknowledgeRelease(assoc_); - } - else if (cond == DUL_PEERABORTEDASSOCIATION) - { - OFLOG_INFO(Internals::Logger, "Association Aborted"); - } - else - { - OFString temp_str; - OFLOG_ERROR(Internals::Logger, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond)); - /* some kind of error so abort the association */ - ASC_abortAssociation(assoc_); - } - } - - return !finished; - } - - - OFCondition EchoScp( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID) - { - OFString temp_str; - OFLOG_INFO(Internals::Logger, "Received Echo Request"); - OFLOG_DEBUG(Internals::Logger, DIMSE_dumpMessage(temp_str, msg->msg.CEchoRQ, DIMSE_INCOMING, NULL, presID)); - - /* the echo succeeded !! */ - OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, &msg->msg.CEchoRQ, STATUS_Success, NULL); - if (cond.bad()) - { - OFLOG_ERROR(Internals::Logger, "Echo SCP Failed: " << DimseCondition::dump(temp_str, cond)); - } - return cond; - } - } -}
--- a/PalanthirServer/Internals/CommandDispatcher.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../DicomProtocol/DicomServer.h" -#include "../../Core/MultiThreading/IRunnableBySteps.h" - -#include <dcmtk/dcmnet/assoc.h> -#include <dcmtk/dcmnet/dimse.h> - -namespace Palanthir -{ - namespace Internals - { - OFCondition AssociationCleanup(T_ASC_Association *assoc); - - class CommandDispatcher : public IRunnableBySteps - { - private: - uint32_t clientTimeout_; - uint32_t elapsedTimeSinceLastCommand_; - const DicomServer& server_; - T_ASC_Association* assoc_; - - public: - CommandDispatcher(const DicomServer& server, - T_ASC_Association* assoc) : - server_(server), - assoc_(assoc) - { - clientTimeout_ = server.GetClientTimeout(); - elapsedTimeSinceLastCommand_ = 0; - } - - virtual ~CommandDispatcher() - { - AssociationCleanup(assoc_); - } - - virtual bool Step(); - }; - - OFCondition EchoScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID); - - CommandDispatcher* AcceptAssociation(const DicomServer& server, - T_ASC_Network *net); - } -}
--- a/PalanthirServer/Internals/FindScp.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "FindScp.h" - -#include "../FromDcmtkBridge.h" -#include "../ToDcmtkBridge.h" -#include "../../Core/PalanthirException.h" - -#include <dcmtk/dcmdata/dcfilefo.h> -#include <dcmtk/dcmdata/dcmetinf.h> -#include <dcmtk/dcmdata/dcostrmb.h> -#include <dcmtk/dcmdata/dcdeftag.h> -#include <dcmtk/dcmnet/diutil.h> - - -namespace Palanthir -{ - namespace Internals - { - extern OFLogger Logger; - } - - - namespace - { - struct FindScpData - { - IFindRequestHandler* handler_; - DicomMap input_; - DicomFindAnswers answers_; - DcmDataset* lastRequest_; - }; - - - void FindScpCallback( - /* in */ - void *callbackData, - OFBool cancelled, - T_DIMSE_C_FindRQ *request, - DcmDataset *requestIdentifiers, - int responseCount, - /* out */ - T_DIMSE_C_FindRSP *response, - DcmDataset **responseIdentifiers, - DcmDataset **statusDetail) - { - bzero(response, sizeof(T_DIMSE_C_FindRSP)); - *statusDetail = NULL; - - FindScpData& data = *(FindScpData*) callbackData; - if (data.lastRequest_ == NULL) - { - FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); - - try - { - data.handler_->Handle(data.input_, data.answers_); - } - catch (PalanthirException& e) - { - // Internal error! - OFLOG_ERROR(Internals::Logger, "IFindRequestHandler Failed: " << e.What()); - response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; - *responseIdentifiers = NULL; - return; - } - - data.lastRequest_ = requestIdentifiers; - } - else if (data.lastRequest_ != requestIdentifiers) - { - // Internal error! - response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; - *responseIdentifiers = NULL; - return; - } - - if (responseCount <= static_cast<int>(data.answers_.GetSize())) - { - response->DimseStatus = STATUS_Pending; - *responseIdentifiers = ToDcmtkBridge::Convert(data.answers_.GetAnswer(responseCount - 1)); - } - else - { - response->DimseStatus = STATUS_Success; - *responseIdentifiers = NULL; - } - } - } - - - OFCondition Internals::findScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IFindRequestHandler& handler) - { - FindScpData data; - data.lastRequest_ = NULL; - data.handler_ = &handler; - - OFCondition cond = DIMSE_findProvider(assoc, presID, &msg->msg.CFindRQ, - FindScpCallback, &data, - /*opt_blockMode*/ DIMSE_BLOCKING, - /*opt_dimse_timeout*/ 0); - - // if some error occured, dump corresponding information and remove the outfile if necessary - if (cond.bad()) - { - OFString temp_str; - OFLOG_ERROR(Internals::Logger, "Find SCP Failed: " << DimseCondition::dump(temp_str, cond)); - } - - return cond; - } -}
--- a/PalanthirServer/Internals/FindScp.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../DicomProtocol/IFindRequestHandler.h" - -#include <dcmtk/dcmnet/assoc.h> -#include <dcmtk/dcmnet/dimse.h> - -namespace Palanthir -{ - namespace Internals - { - OFCondition findScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IFindRequestHandler& handler); - } -}
--- a/PalanthirServer/Internals/MoveScp.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "MoveScp.h" - -#include <memory> - -#include "../FromDcmtkBridge.h" -#include "../ToDcmtkBridge.h" -#include "../../Core/PalanthirException.h" - -#include <dcmtk/dcmdata/dcfilefo.h> -#include <dcmtk/dcmdata/dcmetinf.h> -#include <dcmtk/dcmdata/dcostrmb.h> -#include <dcmtk/dcmdata/dcdeftag.h> -#include <dcmtk/dcmnet/diutil.h> - - -namespace Palanthir -{ - namespace Internals - { - extern OFLogger Logger; - } - - - namespace - { - struct MoveScpData - { - std::string target_; - IMoveRequestHandler* handler_; - DicomMap input_; - DcmDataset* lastRequest_; - unsigned int subOperationCount_; - unsigned int failureCount_; - unsigned int warningCount_; - std::auto_ptr<IMoveRequestIterator> iterator_; - }; - - - void MoveScpCallback( - /* in */ - void *callbackData, - OFBool cancelled, - T_DIMSE_C_MoveRQ *request, - DcmDataset *requestIdentifiers, - int responseCount, - /* out */ - T_DIMSE_C_MoveRSP *response, - DcmDataset **responseIdentifiers, - DcmDataset **statusDetail) - { - bzero(response, sizeof(T_DIMSE_C_MoveRSP)); - *statusDetail = NULL; - *responseIdentifiers = NULL; - - MoveScpData& data = *(MoveScpData*) callbackData; - if (data.lastRequest_ == NULL) - { - FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); - - try - { - data.iterator_.reset(data.handler_->Handle(data.target_, data.input_)); - data.subOperationCount_ = data.iterator_->GetSubOperationCount(); - data.failureCount_ = 0; - data.warningCount_ = 0; - } - catch (PalanthirException& e) - { - // Internal error! - OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); - response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; - return; - } - - data.lastRequest_ = requestIdentifiers; - } - else if (data.lastRequest_ != requestIdentifiers) - { - // Internal error! - response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; - return; - } - - if (data.subOperationCount_ == 0) - { - response->DimseStatus = STATUS_Success; - } - else - { - IMoveRequestIterator::Status status; - - try - { - status = data.iterator_->DoNext(); - } - catch (PalanthirException& e) - { - // Internal error! - OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); - response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; - return; - } - - if (status == IMoveRequestIterator::Status_Failure) - { - data.failureCount_++; - } - else if (status == IMoveRequestIterator::Status_Warning) - { - data.warningCount_++; - } - - if (responseCount < static_cast<int>(data.subOperationCount_)) - { - response->DimseStatus = STATUS_Pending; - } - else - { - response->DimseStatus = STATUS_Success; - } - } - - response->NumberOfRemainingSubOperations = data.subOperationCount_ - responseCount; - response->NumberOfCompletedSubOperations = responseCount; - response->NumberOfFailedSubOperations = data.failureCount_; - response->NumberOfWarningSubOperations = data.warningCount_; - } - } - - - OFCondition Internals::moveScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IMoveRequestHandler& handler) - { - MoveScpData data; - data.target_ = std::string(msg->msg.CMoveRQ.MoveDestination); - data.lastRequest_ = NULL; - data.handler_ = &handler; - - OFCondition cond = DIMSE_moveProvider(assoc, presID, &msg->msg.CMoveRQ, - MoveScpCallback, &data, - /*opt_blockMode*/ DIMSE_BLOCKING, - /*opt_dimse_timeout*/ 0); - - // if some error occured, dump corresponding information and remove the outfile if necessary - if (cond.bad()) - { - OFString temp_str; - OFLOG_ERROR(Internals::Logger, "Move SCP Failed: " << DimseCondition::dump(temp_str, cond)); - } - - return cond; - } -}
--- a/PalanthirServer/Internals/MoveScp.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../DicomProtocol/IMoveRequestHandler.h" - -#include <dcmtk/dcmnet/assoc.h> -#include <dcmtk/dcmnet/dimse.h> - -namespace Palanthir -{ - namespace Internals - { - OFCondition moveScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IMoveRequestHandler& handler); - } -}
--- a/PalanthirServer/Internals/StoreScp.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "StoreScp.h" - -#include "../FromDcmtkBridge.h" -#include "../ToDcmtkBridge.h" -#include "../../Core/PalanthirException.h" - -#include <dcmtk/dcmdata/dcfilefo.h> -#include <dcmtk/dcmdata/dcmetinf.h> -#include <dcmtk/dcmdata/dcostrmb.h> -#include <dcmtk/dcmdata/dcdeftag.h> -#include <dcmtk/dcmnet/diutil.h> - - -namespace Palanthir -{ - namespace Internals - { - extern OFLogger Logger; - } - - - namespace - { - struct StoreCallbackData - { - IStoreRequestHandler* handler; - const char* distantAET; - const char* modality; - const char* affectedSOPInstanceUID; - uint32_t messageID; - }; - - - static int SaveToMemoryBuffer(DcmDataset* dataSet, - std::vector<uint8_t>& buffer) - { - // Determine the transfer syntax which shall be used to write the - // information to the file. We always switch to the Little Endian - // syntax, with explicit length. - - // http://support.dcmtk.org/docs/dcxfer_8h-source.html - E_TransferSyntax xfer = EXS_LittleEndianExplicit; - E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; - - uint32_t s = dataSet->getLength(xfer, encodingType); - - buffer.resize(s); - DcmOutputBufferStream ob(&buffer[0], s); - - dataSet->transferInit(); - OFCondition c = dataSet->write(ob, xfer, encodingType, NULL, - /*opt_groupLength*/ EGL_recalcGL, - /*opt_paddingType*/ EPD_withoutPadding); - dataSet->transferEnd(); - if (c.good()) - { - return 0; - } - else - { - buffer.clear(); - return -1; - } - -#if 0 - OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, - encodingType, - /*opt_groupLength*/ EGL_recalcGL, - /*opt_paddingType*/ EPD_withoutPadding, - OFstatic_cast(Uint32, /*opt_filepad*/ 0), - OFstatic_cast(Uint32, /*opt_itempad*/ 0), - (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); -#endif - } - - - static void - storeScpCallback( - void *callbackData, - T_DIMSE_StoreProgress *progress, - T_DIMSE_C_StoreRQ *req, - char * /*imageFileName*/, DcmDataset **imageDataSet, - T_DIMSE_C_StoreRSP *rsp, - DcmDataset **statusDetail) - /* - * This function.is used to indicate progress when storescp receives instance data over the - * network. On the final call to this function (identified by progress->state == DIMSE_StoreEnd) - * this function will store the data set which was received over the network to a file. - * Earlier calls to this function will simply cause some information to be dumped to stdout. - * - * Parameters: - * callbackData - [in] data for this callback function - * progress - [in] The state of progress. (identifies if this is the initial or final call - * to this function, or a call in between these two calls. - * req - [in] The original store request message. - * imageFileName - [in] The path to and name of the file the information shall be written to. - * imageDataSet - [in] The data set which shall be stored in the image file - * rsp - [inout] the C-STORE-RSP message (will be sent after the call to this function) - * statusDetail - [inout] This variable can be used to capture detailed information with regard to - * the status information which is captured in the status element (0000,0900). Note - * that this function does specify any such information, the pointer will be set to NULL. - */ - { - StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData); - - DIC_UI sopClass; - DIC_UI sopInstance; - - // if this is the final call of this function, save the data which was received to a file - // (note that we could also save the image somewhere else, put it in database, etc.) - if (progress->state == DIMSE_StoreEnd) - { - OFString tmpStr; - - // do not send status detail information - *statusDetail = NULL; - - // Concerning the following line: an appropriate status code is already set in the resp structure, - // it need not be success. For example, if the caller has already detected an out of resources problem - // then the status will reflect this. The callback function is still called to allow cleanup. - //rsp->DimseStatus = STATUS_Success; - - // we want to write the received information to a file only if this information - // is present and the options opt_bitPreserving and opt_ignore are not set. - if ((imageDataSet != NULL) && (*imageDataSet != NULL)) - { - DicomMap summary; - Json::Value dicomJson; - std::vector<uint8_t> buffer; - - try - { - FromDcmtkBridge::Convert(summary, **imageDataSet); - FromDcmtkBridge::ToJson(dicomJson, **imageDataSet); - - if (SaveToMemoryBuffer(*imageDataSet, buffer) < 0) - { - OFLOG_ERROR(Internals::Logger, "cannot write DICOM file to memory"); - rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; - } - } - catch (...) - { - rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; - } - - // check the image to make sure it is consistent, i.e. that its sopClass and sopInstance correspond - // to those mentioned in the request. If not, set the status in the response message variable. - if ((rsp->DimseStatus == STATUS_Success)) - { - // which SOP class and SOP instance ? - if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, /*opt_correctUIDPadding*/ OFFalse)) - { - //OFLOG_ERROR(Internals::Logger, "bad DICOM file: " << fileName); - rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; - } - else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) - { - rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; - } - else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0) - { - rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; - } - else - { - try - { - cbdata->handler->Handle(buffer, summary, dicomJson, cbdata->distantAET); - } - catch (PalanthirException& e) - { - rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; - OFLOG_ERROR(Internals::Logger, "Exception while storing DICOM: " << e.What()); - } - } - } - } - } - } - } - -/* - * This function processes a DIMSE C-STORE-RQ commmand that was - * received over the network connection. - * - * Parameters: - * assoc - [in] The association (network connection to another DICOM application). - * msg - [in] The DIMSE C-STORE-RQ message that was received. - * presID - [in] The ID of the presentation context which was specified in the PDV which contained - * the DIMSE command. - */ - OFCondition Internals::storeScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IStoreRequestHandler& handler) - { - OFCondition cond = EC_Normal; - T_DIMSE_C_StoreRQ *req; - - // assign the actual information of the C-STORE-RQ command to a local variable - req = &msg->msg.CStoreRQ; - - // intialize some variables - StoreCallbackData callbackData; - callbackData.handler = &handler; - callbackData.modality = dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"); - callbackData.affectedSOPInstanceUID = req->AffectedSOPInstanceUID; - callbackData.messageID = req->MessageID; - if (assoc && assoc->params) - { - callbackData.distantAET = assoc->params->DULparams.callingAPTitle; - } - else - { - callbackData.distantAET = ""; - } - - DcmFileFormat dcmff; - - // store SourceApplicationEntityTitle in metaheader - if (assoc && assoc->params) - { - const char *aet = assoc->params->DULparams.callingAPTitle; - if (aet) dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet); - } - - // define an address where the information which will be received over the network will be stored - DcmDataset *dset = dcmff.getDataset(); - - cond = DIMSE_storeProvider(assoc, presID, req, NULL, /*opt_useMetaheader*/OFFalse, &dset, - storeScpCallback, &callbackData, - /*opt_blockMode*/ DIMSE_BLOCKING, - /*opt_dimse_timeout*/ 0); - - // if some error occured, dump corresponding information and remove the outfile if necessary - if (cond.bad()) - { - OFString temp_str; - OFLOG_ERROR(Logger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond)); - } - - // return return value - return cond; - } -}
--- a/PalanthirServer/Internals/StoreScp.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../DicomProtocol/IStoreRequestHandler.h" - -#include <dcmtk/dcmnet/assoc.h> -#include <dcmtk/dcmnet/dimse.h> - -namespace Palanthir -{ - namespace Internals - { - OFCondition storeScp(T_ASC_Association * assoc, - T_DIMSE_Message * msg, - T_ASC_PresentationContextID presID, - IStoreRequestHandler& handler); - } -}
--- a/PalanthirServer/PalanthirInitialization.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "PalanthirInitialization.h" - -#include "../Core/PalanthirException.h" -#include "../Core/Toolbox.h" - -#include <boost/lexical_cast.hpp> -#include <boost/filesystem.hpp> -#include <curl/curl.h> -#include <boost/thread.hpp> - -namespace Palanthir -{ - static const char* CONFIGURATION_FILE = "Configuration.json"; - - static boost::mutex globalMutex_; - static std::auto_ptr<Json::Value> configuration_; - - - static void ReadGlobalConfiguration(const char* configurationFile) - { - configuration_.reset(new Json::Value); - - std::string content; - - if (configurationFile) - { - Toolbox::ReadFile(content, configurationFile); - } - else - { - try - { -#if PALANTHIR_STANDALONE == 0 - boost::filesystem::path p = PALANTHIR_PATH; - p /= "Resources"; - p /= CONFIGURATION_FILE; - Toolbox::ReadFile(content, p.string()); -#else - Toolbox::ReadFile(content, CONFIGURATION_FILE); -#endif - } - catch (PalanthirException&) - { - // No configuration file found, give up with empty configuration - return; - } - } - - Json::Reader reader; - if (!reader.parse(content, *configuration_)) - { - throw PalanthirException("Unable to read the configuration file"); - } - } - - - void PalanthirInitialize(const char* configurationFile) - { - boost::mutex::scoped_lock lock(globalMutex_); - ReadGlobalConfiguration(configurationFile); - curl_global_init(CURL_GLOBAL_ALL); - } - - - - void PalanthirFinalize() - { - boost::mutex::scoped_lock lock(globalMutex_); - curl_global_cleanup(); - configuration_.reset(NULL); - } - - - - std::string GetGlobalStringParameter(const std::string& parameter, - const std::string& defaultValue) - { - boost::mutex::scoped_lock lock(globalMutex_); - - if (configuration_->isMember(parameter)) - { - return (*configuration_) [parameter].asString(); - } - else - { - return defaultValue; - } - } - - - int GetGlobalIntegerParameter(const std::string& parameter, - int defaultValue) - { - boost::mutex::scoped_lock lock(globalMutex_); - - if (configuration_->isMember(parameter)) - { - return (*configuration_) [parameter].asInt(); - } - else - { - return defaultValue; - } - } - - bool GetGlobalBoolParameter(const std::string& parameter, - bool defaultValue) - { - boost::mutex::scoped_lock lock(globalMutex_); - - if (configuration_->isMember(parameter)) - { - return (*configuration_) [parameter].asBool(); - } - else - { - return defaultValue; - } - } - - - - - void GetDicomModality(const std::string& name, - std::string& aet, - std::string& address, - int& port) - { - boost::mutex::scoped_lock lock(globalMutex_); - - if (!configuration_->isMember("DicomModalities")) - { - throw PalanthirException(""); - } - - const Json::Value& modalities = (*configuration_) ["DicomModalities"]; - if (modalities.type() != Json::objectValue || - !modalities.isMember(name)) - { - throw PalanthirException(""); - } - - try - { - aet = modalities[name].get(0u, "").asString(); - address = modalities[name].get(1u, "").asString(); - port = modalities[name].get(2u, "").asInt(); - } - catch (...) - { - throw PalanthirException("Badly formatted DICOM modality"); - } - } - - - - void GetListOfDicomModalities(std::set<std::string>& target) - { - boost::mutex::scoped_lock lock(globalMutex_); - - target.clear(); - - if (!configuration_->isMember("DicomModalities")) - { - return; - } - - const Json::Value& modalities = (*configuration_) ["DicomModalities"]; - if (modalities.type() != Json::objectValue) - { - throw PalanthirException("Badly formatted list of DICOM modalities"); - } - - Json::Value::Members members = modalities.getMemberNames(); - for (size_t i = 0; i < members.size(); i++) - { - for (size_t j = 0; j < members[i].size(); j++) - { - if (!isalnum(members[i][j]) && members[i][j] != '-') - { - throw PalanthirException("Only alphanumeric and dash characters are allowed in the names of the modalities"); - } - } - - target.insert(members[i]); - } - } - - - - void SetupRegisteredUsers(MongooseServer& httpServer) - { - boost::mutex::scoped_lock lock(globalMutex_); - - httpServer.ClearUsers(); - - if (!configuration_->isMember("RegisteredUsers")) - { - return; - } - - const Json::Value& users = (*configuration_) ["RegisteredUsers"]; - if (users.type() != Json::objectValue) - { - throw PalanthirException("Badly formatted list of users"); - } - - Json::Value::Members usernames = users.getMemberNames(); - for (size_t i = 0; i < usernames.size(); i++) - { - const std::string& username = usernames[i]; - std::string password = users[username].asString(); - httpServer.RegisterUser(username.c_str(), password.c_str()); - } - } -}
--- a/PalanthirServer/PalanthirInitialization.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <string> -#include <set> -#include <json/json.h> -#include "../Core/HttpServer/MongooseServer.h" - -namespace Palanthir -{ - void PalanthirInitialize(const char* configurationFile = NULL); - - void PalanthirFinalize(); - - std::string GetGlobalStringParameter(const std::string& parameter, - const std::string& defaultValue); - - int GetGlobalIntegerParameter(const std::string& parameter, - int defaultValue); - - bool GetGlobalBoolParameter(const std::string& parameter, - bool defaultValue); - - void GetDicomModality(const std::string& name, - std::string& aet, - std::string& address, - int& port); - - void GetListOfDicomModalities(std::set<std::string>& target); - - void SetupRegisteredUsers(MongooseServer& httpServer); -}
--- a/PalanthirServer/PalanthirRestApi.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,802 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "PalanthirRestApi.h" - -#include "PalanthirInitialization.h" -#include "FromDcmtkBridge.h" -#include "../Core/Uuid.h" - -#include <dcmtk/dcmdata/dcistrmb.h> -#include <dcmtk/dcmdata/dcfilefo.h> -#include <boost/lexical_cast.hpp> - -namespace Palanthir -{ - static void SendJson(HttpOutput& output, - const Json::Value& value) - { - Json::StyledWriter writer; - std::string s = writer.write(value); - output.AnswerBufferWithContentType(s, "application/json"); - } - - - static void SimplifyTagsRecursion(Json::Value& target, - const Json::Value& source) - { - assert(source.isObject()); - - target = Json::objectValue; - Json::Value::Members members = source.getMemberNames(); - - for (size_t i = 0; i < members.size(); i++) - { - const Json::Value& v = source[members[i]]; - const std::string& name = v["Name"].asString(); - const std::string& type = v["Type"].asString(); - - if (type == "String") - { - target[name] = v["Value"].asString(); - } - else if (type == "TooLong" || - type == "Null") - { - target[name] = Json::nullValue; - } - else if (type == "Sequence") - { - const Json::Value& array = v["Value"]; - assert(array.isArray()); - - Json::Value children = Json::arrayValue; - for (size_t i = 0; i < array.size(); i++) - { - Json::Value c; - SimplifyTagsRecursion(c, array[i]); - children.append(c); - } - - target[name] = children; - } - else - { - assert(0); - } - } - } - - - static void SimplifyTags(Json::Value& target, - const FileStorage& storage, - const std::string& fileUuid) - { - std::string s; - storage.ReadFile(s, fileUuid); - - Json::Value source; - Json::Reader reader; - if (!reader.parse(s, source)) - { - throw PalanthirException("Corrupted JSON file"); - } - - SimplifyTagsRecursion(target, source); - } - - - bool PalanthirRestApi::Store(Json::Value& result, - const std::string& postData) - { - // Prepare an input stream for the memory buffer - DcmInputBufferStream is; - if (postData.size() > 0) - { - is.setBuffer(&postData[0], postData.size()); - } - is.setEos(); - - //printf("[%d]\n", postData.size()); - - DcmFileFormat dicomFile; - if (dicomFile.read(is).good()) - { - DicomMap dicomSummary; - FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); - - Json::Value dicomJson; - FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); - - std::string instanceUuid; - StoreStatus status = StoreStatus_Failure; - if (postData.size() > 0) - { - status = index_.Store - (instanceUuid, storage_, reinterpret_cast<const char*>(&postData[0]), - postData.size(), dicomSummary, dicomJson, ""); - } - - switch (status) - { - case StoreStatus_Success: - result["ID"] = instanceUuid; - result["Path"] = "/instances/" + instanceUuid; - result["Status"] = "Success"; - return true; - - case StoreStatus_AlreadyStored: - result["ID"] = instanceUuid; - result["Path"] = "/instances/" + instanceUuid; - result["Status"] = "AlreadyStored"; - return true; - - default: - return false; - } - } - - return false; - } - - void PalanthirRestApi::ConnectToModality(DicomUserConnection& c, - const std::string& name) - { - std::string aet, address; - int port; - GetDicomModality(name, aet, address, port); - c.SetLocalApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTHIR")); - c.SetDistantApplicationEntityTitle(aet); - c.SetDistantHost(address); - c.SetDistantPort(port); - c.Open(); - } - - bool PalanthirRestApi::MergeQueryAndTemplate(DicomMap& result, - const std::string& postData) - { - Json::Value query; - Json::Reader reader; - - if (!reader.parse(postData, query) || - query.type() != Json::objectValue) - { - return false; - } - - Json::Value::Members members = query.getMemberNames(); - for (size_t i = 0; i < members.size(); i++) - { - DicomTag t = FromDcmtkBridge::FindTag(members[i]); - result.SetValue(t, query[members[i]].asString()); - } - - return true; - } - - bool PalanthirRestApi::DicomFindPatient(Json::Value& result, - DicomUserConnection& c, - const std::string& postData) - { - DicomMap m; - DicomMap::SetupFindPatientTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - - DicomFindAnswers answers; - c.FindPatient(answers, m); - answers.ToJson(result); - return true; - } - - bool PalanthirRestApi::DicomFindStudy(Json::Value& result, - DicomUserConnection& c, - const std::string& postData) - { - DicomMap m; - DicomMap::SetupFindStudyTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - - if (m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && - m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) - { - return false; - } - - DicomFindAnswers answers; - c.FindStudy(answers, m); - answers.ToJson(result); - return true; - } - - bool PalanthirRestApi::DicomFindSeries(Json::Value& result, - DicomUserConnection& c, - const std::string& postData) - { - DicomMap m; - DicomMap::SetupFindSeriesTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - - if ((m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && - m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) || - m.GetValue(DicomTag::STUDY_UID).AsString().size() <= 2) - { - return false; - } - - DicomFindAnswers answers; - c.FindSeries(answers, m); - answers.ToJson(result); - return true; - } - - bool PalanthirRestApi::DicomFind(Json::Value& result, - DicomUserConnection& c, - const std::string& postData) - { - DicomMap m; - DicomMap::SetupFindPatientTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - - DicomFindAnswers patients; - c.FindPatient(patients, m); - - // Loop over the found patients - result = Json::arrayValue; - for (size_t i = 0; i < patients.GetSize(); i++) - { - Json::Value patient(Json::objectValue); - FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i)); - - DicomMap::SetupFindStudyTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - m.CopyTagIfExists(patients.GetAnswer(i), DicomTag::PATIENT_ID); - - DicomFindAnswers studies; - c.FindStudy(studies, m); - - patient["Studies"] = Json::arrayValue; - - // Loop over the found studies - for (size_t j = 0; j < studies.GetSize(); j++) - { - Json::Value study(Json::objectValue); - FromDcmtkBridge::ToJson(study, studies.GetAnswer(j)); - - DicomMap::SetupFindSeriesTemplate(m); - if (!MergeQueryAndTemplate(m, postData)) - { - return false; - } - m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::PATIENT_ID); - m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::STUDY_UID); - - DicomFindAnswers series; - c.FindSeries(series, m); - - // Loop over the found series - study["Series"] = Json::arrayValue; - for (size_t k = 0; k < series.GetSize(); k++) - { - Json::Value series2(Json::objectValue); - FromDcmtkBridge::ToJson(series2, series.GetAnswer(k)); - study["Series"].append(series2); - } - - patient["Studies"].append(study); - } - - result.append(patient); - } - - return true; - } - - - - bool PalanthirRestApi::DicomStore(Json::Value& result, - DicomUserConnection& c, - const std::string& postData) - { - Json::Value found(Json::objectValue); - - if (!Toolbox::IsUuid(postData)) - { - // This is not a UUID, assume this is a DICOM instance - c.Store(postData); - } - else if (index_.GetSeries(found, postData)) - { - // The UUID corresponds to a series - for (size_t i = 0; i < found["Instances"].size(); i++) - { - std::string uuid = found["Instances"][i].asString(); - Json::Value instance(Json::objectValue); - if (index_.GetInstance(instance, uuid)) - { - std::string content; - storage_.ReadFile(content, instance["FileUuid"].asString()); - c.Store(content); - } - else - { - return false; - } - } - } - else if (index_.GetInstance(found, postData)) - { - // The UUID corresponds to an instance - std::string content; - storage_.ReadFile(content, found["FileUuid"].asString()); - c.Store(content); - } - else - { - return false; - } - - return true; - } - - - PalanthirRestApi::PalanthirRestApi(ServerIndex& index, - const std::string& path) : - index_(index), - storage_(path) - { - GetListOfDicomModalities(modalities_); - } - - - void PalanthirRestApi::Handle( - HttpOutput& output, - const std::string& method, - const UriComponents& uri, - const Arguments& headers, - const Arguments& arguments, - const std::string& postData) - { - if (uri.size() == 0) - { - if (method == "GET") - { - output.Redirect("/app/explorer.html"); - } - else - { - output.SendMethodNotAllowedError("GET"); - } - - return; - } - - bool existingResource = false; - Json::Value result(Json::objectValue); - - - // List all the instances --------------------------------------------------- - - if (uri.size() == 1 && uri[0] == "instances") - { - if (method == "GET") - { - result = Json::Value(Json::arrayValue); - index_.GetAllUuids(result, "Instances"); - existingResource = true; - } - else if (method == "POST") - { - // Add a new instance to the storage - if (Store(result, postData)) - { - SendJson(output, result); - return; - } - else - { - output.SendHeader(Palanthir_HttpStatus_415_UnsupportedMediaType); - return; - } - } - else - { - output.SendMethodNotAllowedError("GET,POST"); - return; - } - } - - - // List all the patients, studies or series --------------------------------- - - if (uri.size() == 1 && - (uri[0] == "series" || - uri[0] == "studies" || - uri[0] == "patients")) - { - if (method == "GET") - { - result = Json::Value(Json::arrayValue); - - if (uri[0] == "instances") - index_.GetAllUuids(result, "Instances"); - else if (uri[0] == "series") - index_.GetAllUuids(result, "Series"); - else if (uri[0] == "studies") - index_.GetAllUuids(result, "Studies"); - else if (uri[0] == "patients") - index_.GetAllUuids(result, "Patients"); - - existingResource = true; - } - else - { - output.SendMethodNotAllowedError("GET"); - return; - } - } - - - // Information about a single object ---------------------------------------- - - else if (uri.size() == 2 && - (uri[0] == "instances" || - uri[0] == "series" || - uri[0] == "studies" || - uri[0] == "patients")) - { - if (method == "GET") - { - if (uri[0] == "patients") - { - existingResource = index_.GetPatient(result, uri[1]); - } - else if (uri[0] == "studies") - { - existingResource = index_.GetStudy(result, uri[1]); - } - else if (uri[0] == "series") - { - existingResource = index_.GetSeries(result, uri[1]); - } - else if (uri[0] == "instances") - { - existingResource = index_.GetInstance(result, uri[1]); - } - } - else if (method == "DELETE") - { - if (uri[0] == "patients") - { - existingResource = index_.DeletePatient(result, uri[1]); - } - else if (uri[0] == "studies") - { - existingResource = index_.DeleteStudy(result, uri[1]); - } - else if (uri[0] == "series") - { - existingResource = index_.DeleteSeries(result, uri[1]); - } - else if (uri[0] == "instances") - { - existingResource = index_.DeleteInstance(result, uri[1]); - } - - if (existingResource) - { - result["Status"] = "Success"; - } - } - else - { - output.SendMethodNotAllowedError("GET,DELETE"); - return; - } - } - - - // Get the DICOM or the JSON file of one instance --------------------------- - - else if (uri.size() == 3 && - uri[0] == "instances" && - (uri[2] == "file" || - uri[2] == "tags" || - uri[2] == "simplified-tags")) - { - std::string fileUuid, contentType; - if (uri[2] == "file") - { - existingResource = index_.GetDicomFile(fileUuid, uri[1]); - contentType = "application/dicom"; - } - else if (uri[2] == "tags" || - uri[2] == "simplified-tags") - { - existingResource = index_.GetJsonFile(fileUuid, uri[1]); - contentType = "application/json"; - } - - if (existingResource) - { - if (uri[2] == "simplified-tags") - { - Json::Value v; - SimplifyTags(v, storage_, fileUuid); - SendJson(output, v); - return; - } - else - { - output.AnswerFile(storage_, fileUuid, contentType); - return; - } - } - } - - - else if (uri.size() == 3 && - uri[0] == "instances" && - uri[2] == "frames") - { - Json::Value instance(Json::objectValue); - existingResource = index_.GetInstance(instance, uri[1]); - - if (existingResource) - { - result = Json::arrayValue; - - unsigned int numberOfFrames = 1; - try - { - Json::Value tmp = instance["MainDicomTags"]["NumberOfFrames"]; - numberOfFrames = boost::lexical_cast<unsigned int>(tmp.asString()); - } - catch (boost::bad_lexical_cast) - { - } - - for (unsigned int i = 0; i < numberOfFrames; i++) - { - result.append(i); - } - } - } - - - else if (uri[0] == "instances" && - ((uri.size() == 3 && - (uri[2] == "preview" || - uri[2] == "image-uint8" || - uri[2] == "image-uint16")) || - (uri.size() == 5 && - uri[2] == "frames" && - (uri[4] == "preview" || - uri[4] == "image-uint8" || - uri[4] == "image-uint16")))) - { - std::string uuid; - existingResource = index_.GetDicomFile(uuid, uri[1]); - - std::string action = uri[2]; - - unsigned int frame = 0; - if (existingResource && - uri.size() == 5) - { - // Access to multi-frame image - action = uri[4]; - try - { - frame = boost::lexical_cast<unsigned int>(uri[3]); - } - catch (boost::bad_lexical_cast) - { - existingResource = false; - } - } - - if (existingResource) - { - std::string dicomContent, png; - storage_.ReadFile(dicomContent, uuid); - try - { - if (action == "preview") - { - FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_Preview); - } - else if (action == "image-uint8") - { - FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt8); - } - else if (action == "image-uint16") - { - FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt16); - } - else - { - throw PalanthirException(ErrorCode_InternalError); - } - - output.AnswerBufferWithContentType(png, "image/png"); - return; - } - catch (PalanthirException&) - { - output.Redirect("/app/images/Unsupported.png"); - return; - } - } - } - - - - // Changes API -------------------------------------------------------------- - - if (uri.size() == 1 && uri[0] == "changes") - { - if (method == "GET") - { - const static unsigned int MAX_RESULTS = 100; - - std::string filter = GetArgument(arguments, "filter", ""); - int64_t since; - unsigned int limit; - try - { - since = boost::lexical_cast<int64_t>(GetArgument(arguments, "since", "0")); - limit = boost::lexical_cast<unsigned int>(GetArgument(arguments, "limit", "0")); - } - catch (boost::bad_lexical_cast) - { - output.SendHeader(Palanthir_HttpStatus_400_BadRequest); - return; - } - - if (limit == 0 || limit > MAX_RESULTS) - { - limit = MAX_RESULTS; - } - - if (!index_.GetChanges(result, since, filter, limit)) - { - output.SendHeader(Palanthir_HttpStatus_400_BadRequest); - return; - } - - existingResource = true; - } - else - { - output.SendMethodNotAllowedError("GET"); - return; - } - } - - - // DICOM bridge ------------------------------------------------------------- - - if (uri.size() == 1 && - uri[0] == "modalities") - { - if (method == "GET") - { - result = Json::Value(Json::arrayValue); - existingResource = true; - - for (Modalities::const_iterator it = modalities_.begin(); - it != modalities_.end(); it++) - { - result.append(*it); - } - } - else - { - output.SendMethodNotAllowedError("GET"); - return; - } - } - - if ((uri.size() == 2 || - uri.size() == 3) && - uri[0] == "modalities") - { - if (modalities_.find(uri[1]) == modalities_.end()) - { - // Unknown modality - } - else if (uri.size() == 2) - { - if (method != "GET") - { - output.SendMethodNotAllowedError("POST"); - return; - } - else - { - existingResource = true; - result = Json::arrayValue; - result.append("find-patient"); - result.append("find-study"); - result.append("find-series"); - result.append("find"); - result.append("store"); - } - } - else if (uri.size() == 3) - { - if (uri[2] != "find-patient" && - uri[2] != "find-study" && - uri[2] != "find-series" && - uri[2] != "find" && - uri[2] != "store") - { - // Unknown request - } - else if (method != "POST") - { - output.SendMethodNotAllowedError("POST"); - return; - } - else - { - DicomUserConnection connection; - ConnectToModality(connection, uri[1]); - existingResource = true; - - if ((uri[2] == "find-patient" && !DicomFindPatient(result, connection, postData)) || - (uri[2] == "find-study" && !DicomFindStudy(result, connection, postData)) || - (uri[2] == "find-series" && !DicomFindSeries(result, connection, postData)) || - (uri[2] == "find" && !DicomFind(result, connection, postData)) || - (uri[2] == "store" && !DicomStore(result, connection, postData))) - { - output.SendHeader(Palanthir_HttpStatus_400_BadRequest); - return; - } - } - } - } - - - if (existingResource) - { - SendJson(output, result); - } - else - { - output.SendHeader(Palanthir_HttpStatus_404_NotFound); - } - } -}
--- a/PalanthirServer/PalanthirRestApi.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Core/HttpServer/HttpHandler.h" -#include "ServerIndex.h" -#include "DicomProtocol/DicomUserConnection.h" - -#include <set> - - -namespace Palanthir -{ - class PalanthirRestApi : public HttpHandler - { - private: - typedef std::set<std::string> Modalities; - - ServerIndex& index_; - FileStorage storage_; - Modalities modalities_; - - bool Store(Json::Value& result, - const std::string& postData); - - void ConnectToModality(DicomUserConnection& c, - const std::string& name); - - bool MergeQueryAndTemplate(DicomMap& result, - const std::string& postData); - - bool DicomFindPatient(Json::Value& result, - DicomUserConnection& c, - const std::string& postData); - - bool DicomFindStudy(Json::Value& result, - DicomUserConnection& c, - const std::string& postData); - - bool DicomFindSeries(Json::Value& result, - DicomUserConnection& c, - const std::string& postData); - - bool DicomFind(Json::Value& result, - DicomUserConnection& c, - const std::string& postData); - - bool DicomStore(Json::Value& result, - DicomUserConnection& c, - const std::string& postData); - - public: - PalanthirRestApi(ServerIndex& index, - const std::string& path); - - virtual bool IsServedUri(const UriComponents& uri) - { - return true; - } - - virtual void Handle( - HttpOutput& output, - const std::string& method, - const UriComponents& uri, - const Arguments& headers, - const Arguments& arguments, - const std::string& postData); - }; -}
--- a/PalanthirServer/PrepareDatabase.sql Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -CREATE TABLE GlobalProperties( - name TEXT PRIMARY KEY, - value TEXT - ); - -CREATE TABLE Patients( - uuid TEXT PRIMARY KEY, - dicomPatientId TEXT - ); - -CREATE TABLE Studies( - uuid TEXT PRIMARY KEY, - parentPatient TEXT REFERENCES Patients(uuid) ON DELETE CASCADE, - dicomStudy TEXT - ); - -CREATE TABLE Series( - uuid TEXT PRIMARY KEY, - parentStudy TEXT REFERENCES Studies(uuid) ON DELETE CASCADE, - dicomSeries TEXT - ); - -CREATE TABLE Instances( - uuid TEXT PRIMARY KEY, - parentSeries TEXT REFERENCES Series(uuid) ON DELETE CASCADE, - dicomInstance TEXT, - fileUuid TEXT, - fileSize INTEGER, - jsonUuid TEXT, - distantAet TEXT - ); - -CREATE TABLE MainDicomTags( - uuid TEXT, - tagGroup INTEGER, - tagElement INTEGER, - value TEXT, - PRIMARY KEY(uuid, tagGroup, tagElement) - ); - -CREATE TABLE Changes( - seq INTEGER PRIMARY KEY AUTOINCREMENT, - basePath TEXT, - uuid TEXT - ); - - -CREATE INDEX PatientToStudies ON Studies(parentPatient); -CREATE INDEX StudyToSeries ON Series(parentStudy); -CREATE INDEX SeriesToInstances ON Instances(parentSeries); - -CREATE INDEX DicomPatientIndex ON Patients(dicomPatientId); -CREATE INDEX DicomStudyIndex ON Studies(dicomStudy); -CREATE INDEX DicomSeriesIndex ON Series(dicomSeries); -CREATE INDEX DicomInstanceIndex ON Instances(dicomInstance); - -CREATE INDEX MainDicomTagsIndex ON MainDicomTags(uuid); -CREATE INDEX ChangesIndex ON Changes(uuid); - -CREATE TRIGGER InstanceRemoved -AFTER DELETE ON Instances -FOR EACH ROW BEGIN - DELETE FROM MainDicomTags WHERE uuid = old.uuid; - DELETE FROM Changes WHERE uuid = old.uuid; - SELECT DeleteFromFileStorage(old.fileUuid); - SELECT DeleteFromFileStorage(old.jsonUuid); - SELECT SignalDeletedLevel(3, old.parentSeries); -END; - -CREATE TRIGGER SeriesRemoved -AFTER DELETE ON Series -FOR EACH ROW BEGIN - DELETE FROM MainDicomTags WHERE uuid = old.uuid; - DELETE FROM Changes WHERE uuid = old.uuid; - SELECT SignalDeletedLevel(2, old.parentStudy); -END; - -CREATE TRIGGER StudyRemoved -AFTER DELETE ON Studies -FOR EACH ROW BEGIN - DELETE FROM MainDicomTags WHERE uuid = old.uuid; - DELETE FROM Changes WHERE uuid = old.uuid; - SELECT SignalDeletedLevel(1, old.parentPatient); -END; - -CREATE TRIGGER PatientRemoved -AFTER DELETE ON Patients -FOR EACH ROW BEGIN - DELETE FROM MainDicomTags WHERE uuid = old.uuid; - DELETE FROM Changes WHERE uuid = old.uuid; - SELECT SignalDeletedLevel(0, ""); -END; - - - - -CREATE TRIGGER InstanceRemovedUpwardCleaning -AFTER DELETE ON Instances -FOR EACH ROW - WHEN (SELECT COUNT(*) FROM Instances WHERE parentSeries = old.parentSeries) = 0 - BEGIN - SELECT DeleteFromFileStorage("deleting parent series"); -- TODO REMOVE THIS - DELETE FROM Series WHERE uuid = old.parentSeries; - END; - -CREATE TRIGGER SeriesRemovedUpwardCleaning -AFTER DELETE ON Series -FOR EACH ROW - WHEN (SELECT COUNT(*) FROM Series WHERE parentStudy = old.parentStudy) = 0 - BEGIN - SELECT DeleteFromFileStorage("deleting parent study"); -- TODO REMOVE THIS - DELETE FROM Studies WHERE uuid = old.parentStudy; - END; - -CREATE TRIGGER StudyRemovedUpwardCleaning -AFTER DELETE ON Studies -FOR EACH ROW - WHEN (SELECT COUNT(*) FROM Studies WHERE parentPatient = old.parentPatient) = 0 - BEGIN - SELECT DeleteFromFileStorage("deleting parent patient"); -- TODO REMOVE THIS - DELETE FROM Patients WHERE uuid = old.parentPatient; - END;
--- a/PalanthirServer/ServerIndex.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,833 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "ServerIndex.h" - -using namespace Palanthir; - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#include "EmbeddedResources.h" -#include "../Core/Toolbox.h" -#include "../Core/Uuid.h" -#include "../Core/DicomFormat/DicomArray.h" -#include "../Core/SQLite/Transaction.h" -#include "FromDcmtkBridge.h" - -#include <boost/lexical_cast.hpp> -#include <stdio.h> - -namespace Palanthir -{ - namespace Internals - { - class DeleteFromFileStorageFunction : public SQLite::IScalarFunction - { - private: - FileStorage fileStorage_; - - public: - DeleteFromFileStorageFunction(const std::string& path) : - fileStorage_(path) - { - } - - virtual const char* GetName() const - { - return "DeleteFromFileStorage"; - } - - virtual unsigned int GetCardinality() const - { - return 1; - } - - virtual void Compute(SQLite::FunctionContext& context) - { - std::string fileUuid = context.GetStringValue(0); - printf("Removing file [%s]\n", fileUuid.c_str()); - if (Toolbox::IsUuid(fileUuid)) - { - fileStorage_.Remove(fileUuid); - } - } - }; - - - class SignalDeletedLevelFunction : public SQLite::IScalarFunction - { - private: - int remainingLevel_; - std::string remainingLevelUuid_; - - public: - void Clear() - { - remainingLevel_ = std::numeric_limits<int>::max(); - } - - bool HasRemainingLevel() const - { - return (remainingLevel_ != 0 && - remainingLevel_ != std::numeric_limits<int>::max()); - } - - const std::string& GetRemainingLevelUuid() const - { - assert(HasRemainingLevel()); - return remainingLevelUuid_; - } - - const char* GetRemainingLevelType() const - { - assert(HasRemainingLevel()); - switch (remainingLevel_) - { - case 1: - return "patient"; - case 2: - return "study"; - case 3: - return "series"; - default: - throw PalanthirException(ErrorCode_InternalError); - } - } - - virtual const char* GetName() const - { - return "SignalDeletedLevel"; - } - - virtual unsigned int GetCardinality() const - { - return 2; - } - - virtual void Compute(SQLite::FunctionContext& context) - { - int level = context.GetIntValue(0); - if (level < remainingLevel_) - { - remainingLevel_ = level; - remainingLevelUuid_ = context.GetStringValue(1); - } - - //printf("deleted level [%d] [%s]\n", level, context.GetStringValue(1).c_str()); - } - }; - } - - - void ServerIndex::StoreMainDicomTags(const std::string& uuid, - const DicomMap& map) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); - - DicomArray flattened(map); - for (size_t i = 0; i < flattened.GetSize(); i++) - { - s.Reset(); - s.BindString(0, uuid); - s.BindInt(1, flattened.GetElement(i).GetTag().GetGroup()); - s.BindInt(2, flattened.GetElement(i).GetTag().GetElement()); - s.BindString(3, flattened.GetElement(i).GetValue().AsString()); - s.Run(); - } - } - - bool ServerIndex::GetMainDicomStringTag(std::string& result, - const std::string& uuid, - const DicomTag& tag) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, - "SELECT * FROM MainDicomTags WHERE uuid=? AND tagGroup=? AND tagElement=?"); - s.BindString(0, uuid); - s.BindInt(1, tag.GetGroup()); - s.BindInt(2, tag.GetElement()); - if (!s.Step()) - { - return false; - } - - result = s.ColumnString(0); - return true; - } - - bool ServerIndex::GetMainDicomIntTag(int& result, - const std::string& uuid, - const DicomTag& tag) - { - std::string s; - if (!GetMainDicomStringTag(s, uuid, tag)) - { - return false; - } - - try - { - result = boost::lexical_cast<int>(s); - return true; - } - catch (boost::bad_lexical_cast) - { - return false; - } - } - - bool ServerIndex::HasInstance(std::string& instanceUuid, - const std::string& dicomInstance) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); - s.BindString(0, dicomInstance); - if (s.Step()) - { - instanceUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - - void ServerIndex::RecordChange(const std::string& resourceType, - const std::string& uuid) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?)"); - s.BindString(0, resourceType); - s.BindString(1, uuid); - s.Run(); - } - - - std::string ServerIndex::CreateInstance(const std::string& parentSeriesUuid, - const std::string& dicomInstance, - const DicomMap& dicomSummary, - const std::string& fileUuid, - uint64_t fileSize, - const std::string& jsonUuid, - const std::string& distantAet) - { - std::string instanceUuid = Toolbox::GenerateUuid(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?)"); - s.BindString(0, instanceUuid); - s.BindString(1, parentSeriesUuid); - s.BindString(2, dicomInstance); - s.BindString(3, fileUuid); - s.BindInt64(4, fileSize); - s.BindString(5, jsonUuid); - s.BindString(6, distantAet); - s.Run(); - - RecordChange("instances", instanceUuid); - - DicomMap dicom; - dicomSummary.ExtractInstanceInformation(dicom); - StoreMainDicomTags(instanceUuid, dicom); - - return instanceUuid; - } - - void ServerIndex::RemoveInstance(const std::string& uuid) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Instances WHERE uuid=?"); - s.BindString(0, uuid); - s.Run(); - } - - bool ServerIndex::HasSeries(std::string& seriesUuid, - const std::string& dicomSeries) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE dicomSeries=?"); - s.BindString(0, dicomSeries); - if (s.Step()) - { - seriesUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - std::string ServerIndex::CreateSeries(const std::string& parentStudyUuid, - const std::string& dicomSeries, - const DicomMap& dicomSummary) - { - std::string seriesUuid = Toolbox::GenerateUuid(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?)"); - s.BindString(0, seriesUuid); - s.BindString(1, parentStudyUuid); - s.BindString(2, dicomSeries); - s.Run(); - - RecordChange("series", seriesUuid); - - DicomMap dicom; - dicomSummary.ExtractSeriesInformation(dicom); - StoreMainDicomTags(seriesUuid, dicom); - - return seriesUuid; - } - - bool ServerIndex::HasStudy(std::string& studyUuid, - const std::string& dicomStudy) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE dicomStudy=?"); - s.BindString(0, dicomStudy); - if (s.Step()) - { - studyUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - std::string ServerIndex::CreateStudy(const std::string& parentPatientUuid, - const std::string& dicomStudy, - const DicomMap& dicomSummary) - { - std::string studyUuid = Toolbox::GenerateUuid(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Studies VALUES(?, ?, ?)"); - s.BindString(0, studyUuid); - s.BindString(1, parentPatientUuid); - s.BindString(2, dicomStudy); - s.Run(); - - RecordChange("studies", studyUuid); - - DicomMap dicom; - dicomSummary.ExtractStudyInformation(dicom); - StoreMainDicomTags(studyUuid, dicom); - - return studyUuid; - } - - - - bool ServerIndex::HasPatient(std::string& patientUuid, - const std::string& dicomPatientId) - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Patients WHERE dicomPatientId=?"); - s.BindString(0, dicomPatientId); - if (s.Step()) - { - patientUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - std::string ServerIndex::CreatePatient(const std::string& patientId, - const DicomMap& dicomSummary) - { - std::string patientUuid = Toolbox::GenerateUuid(); - std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); - s.BindString(0, patientUuid); - s.BindString(1, dicomPatientId); - s.Run(); - - RecordChange("patients", patientUuid); - - DicomMap dicom; - dicomSummary.ExtractPatientInformation(dicom); - StoreMainDicomTags(patientUuid, dicom); - - return patientUuid; - } - - - void ServerIndex::GetMainDicomTags(DicomMap& map, - const std::string& uuid) - { - map.Clear(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE uuid=?"); - s.BindString(0, uuid); - while (s.Step()) - { - map.SetValue(s.ColumnInt(1), - s.ColumnInt(2), - s.ColumnString(3)); - } - } - - void ServerIndex::MainDicomTagsToJson(Json::Value& target, - const std::string& uuid) - { - DicomMap map; - GetMainDicomTags(map, uuid); - target["MainDicomTags"] = Json::objectValue; - FromDcmtkBridge::ToJson(target["MainDicomTags"], map); - } - - - bool ServerIndex::DeleteInternal(Json::Value& target, - const std::string& uuid, - const std::string& tableName) - { - boost::mutex::scoped_lock scoped_lock(mutex_); - - deletedLevels_->Clear(); - - SQLite::Statement s(db_, "DELETE FROM " + tableName + " WHERE uuid=?"); - s.BindString(0, uuid); - - if (!s.Run()) - { - return false; - } - - if (db_.GetLastChangeCount() == 0) - { - // Nothing was deleted, inexistent UUID - return false; - } - - if (deletedLevels_->HasRemainingLevel()) - { - std::string type(deletedLevels_->GetRemainingLevelType()); - const std::string& uuid = deletedLevels_->GetRemainingLevelUuid(); - - target["RemainingAncestor"] = Json::Value(Json::objectValue); - target["RemainingAncestor"]["Path"] = "/" + type + "/" + uuid; - target["RemainingAncestor"]["Type"] = type; - target["RemainingAncestor"]["ID"] = uuid; - } - else - { - target["RemainingAncestor"] = Json::nullValue; - } - - return true; - } - - - ServerIndex::ServerIndex(const std::string& storagePath) - { - boost::filesystem::path p = storagePath; - - try - { - boost::filesystem::create_directories(storagePath); - } - catch (boost::filesystem::filesystem_error) - { - } - - p /= "index"; - db_.Open(p.string()); - db_.Register(new Internals::DeleteFromFileStorageFunction(storagePath)); - deletedLevels_ = (Internals::SignalDeletedLevelFunction*) - db_.Register(new Internals::SignalDeletedLevelFunction); - - if (!db_.DoesTableExist("GlobalProperties")) - { - printf("Creating the database\n"); - std::string query; - EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); - db_.Execute(query); - } - } - - - StoreStatus ServerIndex::Store(std::string& instanceUuid, - const DicomMap& dicomSummary, - const std::string& fileUuid, - uint64_t uncompressedFileSize, - const std::string& jsonUuid, - const std::string& distantAet) - { - boost::mutex::scoped_lock scoped_lock(mutex_); - - std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); - std::string dicomInstance = dicomSummary.GetValue(DicomTag::INSTANCE_UID).AsString(); - std::string dicomSeries = dicomSummary.GetValue(DicomTag::SERIES_UID).AsString(); - std::string dicomStudy = dicomSummary.GetValue(DicomTag::STUDY_UID).AsString(); - - try - { - SQLite::Transaction t(db_); - t.Begin(); - - if (HasInstance(instanceUuid, dicomInstance)) - { - return StoreStatus_AlreadyStored; - // TODO: Check consistency? - } - - std::string patientUuid; - if (HasPatient(patientUuid, dicomPatientId)) - { - // TODO: Check consistency? - } - else - { - patientUuid = CreatePatient(dicomPatientId, dicomSummary); - } - - std::string studyUuid; - if (HasStudy(studyUuid, dicomStudy)) - { - // TODO: Check consistency? - } - else - { - studyUuid = CreateStudy(patientUuid, dicomStudy, dicomSummary); - } - - std::string seriesUuid; - if (HasSeries(seriesUuid, dicomSeries)) - { - // TODO: Check consistency? - } - else - { - seriesUuid = CreateSeries(studyUuid, dicomSeries, dicomSummary); - } - - instanceUuid = CreateInstance(seriesUuid, dicomInstance, dicomSummary, fileUuid, - uncompressedFileSize, jsonUuid, distantAet); - - t.Commit(); - return StoreStatus_Success; - //t.Rollback(); - } - catch (PalanthirException& e) - { - std::cout << "EXCEPT2 [" << e.What() << "]" << " " << db_.GetErrorMessage() << std::endl; - } - - return StoreStatus_Failure; - } - - - StoreStatus ServerIndex::Store(std::string& instanceUuid, - FileStorage& storage, - const char* dicomFile, - size_t dicomSize, - const DicomMap& dicomSummary, - const Json::Value& dicomJson, - const std::string& distantAet) - { - std::string fileUuid = storage.Create(dicomFile, dicomSize); - std::string jsonUuid = storage.Create(dicomJson.toStyledString()); - StoreStatus status = Store(instanceUuid, dicomSummary, fileUuid, - dicomSize, jsonUuid, distantAet); - - if (status != StoreStatus_Success) - { - storage.Remove(fileUuid); - storage.Remove(jsonUuid); - } - - switch (status) - { - case StoreStatus_Success: - std::cout << "New instance stored: " << GetTotalSize() << std::endl; - break; - - case StoreStatus_AlreadyStored: - std::cout << "Already stored" << std::endl; - break; - - case StoreStatus_Failure: - std::cout << "Store failure" << std::endl; - break; - } - - return status; - } - - uint64_t ServerIndex::GetTotalSize() - { - boost::mutex::scoped_lock scoped_lock(mutex_); - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(fileSize) FROM Instances"); - s.Run(); - return s.ColumnInt64(0); - } - - - SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) - { - int numberOfSlices; - if (!GetMainDicomIntTag(numberOfSlices, seriesUuid, DicomTag::NUMBER_OF_SLICES) || - numberOfSlices < 0) - { - return SeriesStatus_Unknown; - } - - // Loop over the instances of the series - //std::set< - - // TODO - return SeriesStatus_Unknown; - } - - - - - - bool ServerIndex::GetInstance(Json::Value& result, - const std::string& instanceUuid) - { - assert(result.type() == Json::objectValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid FROM Instances WHERE uuid=?"); - s.BindString(0, instanceUuid); - if (!s.Step()) - { - return false; - } - else - { - result["ID"] = instanceUuid; - result["ParentSeries"] = s.ColumnString(0); - result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? - result["FileUuid"] = s.ColumnString(3); - MainDicomTagsToJson(result, instanceUuid); - return true; - } - } - - - bool ServerIndex::GetSeries(Json::Value& result, - const std::string& seriesUuid) - { - assert(result.type() == Json::objectValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries FROM Series WHERE uuid=?"); - s1.BindString(0, seriesUuid); - if (!s1.Step()) - { - return false; - } - - result["ID"] = seriesUuid; - result["ParentStudy"] = s1.ColumnString(0); - MainDicomTagsToJson(result, seriesUuid); - - Json::Value instances(Json::arrayValue); - SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE parentSeries=?"); - s2.BindString(0, seriesUuid); - while (s2.Step()) - { - instances.append(s2.ColumnString(0)); - } - - result["Instances"] = instances; - - return true; - } - - - bool ServerIndex::GetStudy(Json::Value& result, - const std::string& studyUuid) - { - assert(result.type() == Json::objectValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentPatient, dicomStudy FROM Studies WHERE uuid=?"); - s1.BindString(0, studyUuid); - if (!s1.Step()) - { - return false; - } - - result["ID"] = studyUuid; - result["ParentPatient"] = s1.ColumnString(0); - MainDicomTagsToJson(result, studyUuid); - - Json::Value series(Json::arrayValue); - SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE parentStudy=?"); - s2.BindString(0, studyUuid); - while (s2.Step()) - { - series.append(s2.ColumnString(0)); - } - - result["Series"] = series; - return true; - } - - - bool ServerIndex::GetPatient(Json::Value& result, - const std::string& patientUuid) - { - assert(result.type() == Json::objectValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT dicomPatientId FROM Patients WHERE uuid=?"); - s1.BindString(0, patientUuid); - if (!s1.Step()) - { - return false; - } - - result["ID"] = patientUuid; - MainDicomTagsToJson(result, patientUuid); - - Json::Value studies(Json::arrayValue); - SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE parentPatient=?"); - s2.BindString(0, patientUuid); - while (s2.Step()) - { - studies.append(s2.ColumnString(0)); - } - - result["Studies"] = studies; - return true; - } - - - bool ServerIndex::GetJsonFile(std::string& fileUuid, - const std::string& instanceUuid) - { - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT jsonUuid FROM Instances WHERE uuid=?"); - s.BindString(0, instanceUuid); - if (s.Step()) - { - fileUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - bool ServerIndex::GetDicomFile(std::string& fileUuid, - const std::string& instanceUuid) - { - boost::mutex::scoped_lock scoped_lock(mutex_); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Instances WHERE uuid=?"); - s.BindString(0, instanceUuid); - if (s.Step()) - { - fileUuid = s.ColumnString(0); - return true; - } - else - { - return false; - } - } - - - void ServerIndex::GetAllUuids(Json::Value& target, - const std::string& tableName) - { - assert(target.type() == Json::arrayValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - std::string query = "SELECT uuid FROM " + tableName; - SQLite::Statement s(db_, query); - while (s.Step()) - { - target.append(s.ColumnString(0)); - } - } - - - bool ServerIndex::GetChanges(Json::Value& target, - int64_t since, - const std::string& filter, - unsigned int maxResults) - { - assert(target.type() == Json::objectValue); - boost::mutex::scoped_lock scoped_lock(mutex_); - - if (filter.size() != 0 && - filter != "instances" && - filter != "series" && - filter != "studies" && - filter != "patients") - { - return false; - } - - std::auto_ptr<SQLite::Statement> s; - if (filter.size() == 0) - { - s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " - "ORDER BY seq LIMIT ?")); - s->BindInt64(0, since); - s->BindInt(1, maxResults); - } - else - { - s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " - "AND basePath=? ORDER BY seq LIMIT ?")); - s->BindInt64(0, since); - s->BindString(1, filter); - s->BindInt(2, maxResults); - } - - int64_t lastSeq = 0; - Json::Value results(Json::arrayValue); - while (s->Step()) - { - int64_t seq = s->ColumnInt64(0); - std::string basePath = s->ColumnString(1); - std::string uuid = s->ColumnString(2); - - if (filter.size() == 0 || - filter == basePath) - { - Json::Value change(Json::objectValue); - change["Seq"] = static_cast<int>(seq); // TODO JsonCpp in 64bit - change["BasePath"] = basePath; - change["ID"] = uuid; - results.append(change); - } - - if (seq > lastSeq) - { - lastSeq = seq; - } - } - - target["Results"] = results; - target["LastSeq"] = static_cast<int>(lastSeq); // TODO JsonCpp in 64bit - - return true; - } -}
--- a/PalanthirServer/ServerIndex.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <boost/thread.hpp> -#include "../Core/SQLite/Connection.h" -#include "../Core/DicomFormat/DicomMap.h" -#include "../Core/FileStorage.h" - - -namespace Palanthir -{ - enum SeriesStatus - { - SeriesStatus_Complete, - SeriesStatus_Missing, - SeriesStatus_Inconsistent, - SeriesStatus_Unknown - }; - - - enum StoreStatus - { - StoreStatus_Success, - StoreStatus_AlreadyStored, - StoreStatus_Failure - }; - - - namespace Internals - { - class SignalDeletedLevelFunction; - } - - - class ServerIndex - { - private: - SQLite::Connection db_; - boost::mutex mutex_; - - // DO NOT delete the following one, SQLite::Connection will do it automatically - Internals::SignalDeletedLevelFunction* deletedLevels_; - - void StoreMainDicomTags(const std::string& uuid, - const DicomMap& map); - - bool GetMainDicomStringTag(std::string& result, - const std::string& uuid, - const DicomTag& tag); - - bool GetMainDicomIntTag(int& result, - const std::string& uuid, - const DicomTag& tag); - - bool HasInstance(std::string& instanceUuid, - const std::string& dicomInstance); - - void RecordChange(const std::string& resourceType, - const std::string& uuid); - - std::string CreateInstance(const std::string& parentSeriesUuid, - const std::string& dicomInstance, - const DicomMap& dicomSummary, - const std::string& fileUuid, - uint64_t fileSize, - const std::string& jsonUuid, - const std::string& distantAet); - - void RemoveInstance(const std::string& uuid); - - bool HasSeries(std::string& seriesUuid, - const std::string& dicomSeries); - - std::string CreateSeries(const std::string& parentStudyUuid, - const std::string& dicomSeries, - const DicomMap& dicomSummary); - - bool HasStudy(std::string& studyUuid, - const std::string& dicomStudy); - - std::string CreateStudy(const std::string& parentPatientUuid, - const std::string& dicomStudy, - const DicomMap& dicomSummary); - - bool HasPatient(std::string& patientUuid, - const std::string& dicomPatientId); - - std::string CreatePatient(const std::string& patientId, - const DicomMap& dicomSummary); - - void GetMainDicomTags(DicomMap& map, - const std::string& uuid); - - void MainDicomTagsToJson(Json::Value& target, - const std::string& uuid); - - bool DeleteInternal(Json::Value& target, - const std::string& uuid, - const std::string& tableName); - - public: - ServerIndex(const std::string& storagePath); - - StoreStatus Store(std::string& instanceUuid, - const DicomMap& dicomSummary, - const std::string& fileUuid, - uint64_t uncompressedFileSize, - const std::string& jsonUuid, - const std::string& distantAet); - - StoreStatus Store(std::string& instanceUuid, - FileStorage& storage, - const char* dicomFile, - size_t dicomSize, - const DicomMap& dicomSummary, - const Json::Value& dicomJson, - const std::string& distantAet); - - uint64_t GetTotalSize(); - - SeriesStatus GetSeriesStatus(const std::string& seriesUuid); - - - bool GetInstance(Json::Value& result, - const std::string& instanceUuid); - - bool GetSeries(Json::Value& result, - const std::string& seriesUuid); - - bool GetStudy(Json::Value& result, - const std::string& studyUuid); - - bool GetPatient(Json::Value& result, - const std::string& patientUuid); - - bool GetJsonFile(std::string& fileUuid, - const std::string& instanceUuid); - - bool GetDicomFile(std::string& fileUuid, - const std::string& instanceUuid); - - void GetAllUuids(Json::Value& target, - const std::string& tableName); - - bool DeletePatient(Json::Value& target, - const std::string& patientUuid) - { - return DeleteInternal(target, patientUuid, "Patients"); - } - - bool DeleteStudy(Json::Value& target, - const std::string& studyUuid) - { - return DeleteInternal(target, studyUuid, "Studies"); - } - - bool DeleteSeries(Json::Value& target, - const std::string& seriesUuid) - { - return DeleteInternal(target, seriesUuid, "Series"); - } - - bool DeleteInstance(Json::Value& target, - const std::string& instanceUuid) - { - return DeleteInternal(target, instanceUuid, "Instances"); - } - - bool GetChanges(Json::Value& target, - int64_t since, - const std::string& filter, - unsigned int maxResults); - }; -}
--- a/PalanthirServer/ToDcmtkBridge.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "ToDcmtkBridge.h" - -#include <memory> -#include <dcmtk/dcmdata/dcelem.h> -#include <dcmtk/dcmnet/diutil.h> - - -namespace Palanthir -{ - DcmTagKey ToDcmtkBridge::Convert(const DicomTag& tag) - { - return DcmTagKey(tag.GetGroup(), tag.GetElement()); - } - - - DcmDataset* ToDcmtkBridge::Convert(const DicomMap& map) - { - std::auto_ptr<DcmDataset> result(new DcmDataset); - - for (DicomMap::Map::const_iterator - it = map.map_.begin(); it != map.map_.end(); it++) - { - std::string s = it->second->AsString(); - DU_putStringDOElement(result.get(), Convert(it->first), s.c_str()); - } - - return result.release(); - } -}
--- a/PalanthirServer/ToDcmtkBridge.h Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Core/DicomFormat/DicomMap.h" -#include <dcmtk/dcmdata/dcdatset.h> - - -namespace Palanthir -{ - class ToDcmtkBridge - { - public: - static DcmTagKey Convert(const DicomTag& tag); - - static DcmDataset* Convert(const DicomMap& map); - }; -}
--- a/PalanthirServer/main.cpp Sun Sep 16 09:21:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/** - * Palanthir - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "PalanthirRestApi.h" - -#include <stdio.h> - -#include "../Core/HttpServer/EmbeddedResourceHttpHandler.h" -#include "../Core/HttpServer/FilesystemHttpHandler.h" -#include "../Core/HttpServer/MongooseServer.h" -#include "DicomProtocol/DicomServer.h" -#include "PalanthirInitialization.h" - - -using namespace Palanthir; - - -class MyDicomStore : public IStoreRequestHandler -{ -private: - ServerIndex& index_; - FileStorage storage_; - -public: - MyDicomStore(ServerIndex& index, - const std::string& path) : - index_(index), - storage_(path) - { - } - - virtual void Handle(const std::vector<uint8_t>& dicomFile, - const DicomMap& dicomSummary, - const Json::Value& dicomJson, - const std::string& remoteAet) - { - std::string instanceUuid; - if (dicomFile.size() > 0) - { - index_.Store(instanceUuid, storage_, - reinterpret_cast<const char*>(&dicomFile[0]), dicomFile.size(), - dicomSummary, dicomJson, remoteAet); - } - } -}; - - -class MyDicomStoreFactory : public IStoreRequestHandlerFactory -{ -private: - ServerIndex& index_; - std::string path_; - -public: - MyDicomStoreFactory(ServerIndex& index, - const std::string& path) : - index_(index), - path_(path) - { - } - - virtual IStoreRequestHandler* ConstructStoreRequestHandler() - { - return new MyDicomStore(index_, path_); - } - - void Done() - { - //index_.db().Execute("DELETE FROM Studies"); - } -}; - - - - - - - -int main(int argc, char* argv[]) -{ - try - { - if (argc >= 2) - { - PalanthirInitialize(argv[1]); - } - else - { - PalanthirInitialize(); - } - - std::string storageDirectory = GetGlobalStringParameter("StorageDirectory", "PalanthirStorage"); - ServerIndex index(storageDirectory); - MyDicomStoreFactory storeScp(index, storageDirectory); - - { - // DICOM server - DicomServer dicomServer; - dicomServer.SetCalledApplicationEntityTitleCheck(GetGlobalBoolParameter("DicomCheckCalledAet", false)); - dicomServer.SetStoreRequestHandlerFactory(storeScp); - dicomServer.SetPortNumber(GetGlobalIntegerParameter("DicomPort", 4242)); - dicomServer.SetApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTHIR")); - - // HTTP server - MongooseServer httpServer; - httpServer.SetPort(GetGlobalIntegerParameter("HttpPort", 8000)); - httpServer.SetRemoteAccessAllowed(GetGlobalBoolParameter("RemoteAccessAllowed", false)); - - httpServer.SetAuthenticationEnabled(GetGlobalBoolParameter("AuthenticationEnabled", false)); - SetupRegisteredUsers(httpServer); - - if (GetGlobalBoolParameter("SslEnabled", false)) - { - std::string certificate = GetGlobalStringParameter("SslCertificate", "certificate.pem"); - httpServer.SetSslEnabled(true); - httpServer.SetSslCertificate(certificate.c_str()); - } - else - { - httpServer.SetSslEnabled(false); - } - -#if PALANTHIR_STANDALONE == 1 - httpServer.RegisterHandler(new EmbeddedResourceHttpHandler("/app", EmbeddedResources::PALANTHIR_EXPLORER)); -#else - httpServer.RegisterHandler(new FilesystemHttpHandler("/app", PALANTHIR_PATH "/PalanthirExplorer")); -#endif - - httpServer.RegisterHandler(new PalanthirRestApi(index, storageDirectory)); - - // GO !!! - httpServer.Start(); - dicomServer.Start(); - - printf("The server has started\n"); - Toolbox::ServerBarrier(); - - // Stop - printf("Finishing\n"); - } - - storeScp.Done(); - } - catch (PalanthirException& e) - { - std::cout << "EXCEPT [" << e.What() << "]" << std::endl; - } - - PalanthirFinalize(); - - return 0; -}
--- a/README Sun Sep 16 09:21:12 2012 +0200 +++ b/README Sun Sep 16 09:22:48 2012 +0200 @@ -1,18 +1,18 @@ -Palanthir - A Lightweight, RESTful DICOM Server -=============================================== +Orthanc - A Lightweight, RESTful DICOM Server +============================================= + General Information ------------------- General information about this software can be found on our Google Code hosting page: -http://code.google.com/p/palanthir/ +http://code.google.com/p/orthanc/ -The instructions for building Palanthir can be found in the "INSTALL" +The instructions for building Orthanc can be found in the "INSTALL" file. - Supported Platforms ------------------- @@ -23,11 +23,10 @@ * Windows 32bit. - Supported Toolchains -------------------- -Palanthir can currently be built using the following compiling +Orthanc can currently be built using the following compiling toolchains: * Native Linux compilation, with gcc. @@ -35,18 +34,16 @@ * Cross-compilation for Windows under Linux, with MinGW. - Licensing --------- -Palanthir is licensed under the GPLv3 license. Because Palanthir uses -the Software-as-a-Service paradigm, commercial products are allowed to -access the Palanthir REST services and to bundle Palanthir in an -commercial aggregate. +Orthanc is licensed under the GPLv3 license. Because Orthanc uses the +Software-as-a-Service paradigm, commercial products are allowed to +access the Orthanc REST services and to bundle Orthanc in an +commercial aggregate. We also kindly require scientific works and clinical studies that make -use of Palanthir to cite Palanthir in their associated publications. - +use of Orthanc to cite Orthanc in their associated publications. Licensing of special directories @@ -54,7 +51,7 @@ The following directories have separate licensing terms: -* The files of the "PalanthirCppClient/" directory are licensed under +* The files of the "OrthancCppClient/" directory are licensed under the MIT license, which allows commercial products to statically link against the C++ client library. @@ -62,16 +59,15 @@ 3-clause BSD license, as they are derived from the Chromium project. - Content ------- This archive contains the following directories: * Core/ - The core C++ classes (independent of DCMTK) -* PalanthirCppClient/ - Code of the C++ client (under MIT license) -* PalanthirExplorer/ - Code of the Web application (HTML5/Javascript) -* PalanthirServer/ - Code of the Palanthir server (depends on DCMTK) +* OrthancCppClient/ - Code of the C++ client (under MIT license) +* OrthancExplorer/ - Code of the Web application (HTML5/Javascript) +* OrthancServer/ - Code of the Orthanc server (depends on DCMTK) * Resources/ - Scripts, resources for building third-party code * UnitTests/ - Unit tests @@ -80,11 +76,11 @@ * AUTHORS - The list of the authors * CMakeLists.txt - The main build script * COPYING - The GPLv3 license -* INSTALL - How to build Palanthir +* INSTALL - How to build Orthanc * README - This file * THANKS - The list of the contributors * NEWS - The history of main changes between versions We have decided not to maintain a separate "ChangeLog" file. Each -commit to the official Palanthir Mercurial repository should be +commit to the official Orthanc Mercurial repository should be associated with a description of the changes.
--- a/THANKS Sun Sep 16 09:21:12 2012 +0200 +++ b/THANKS Sun Sep 16 09:22:48 2012 +0200 @@ -1,11 +1,11 @@ -Palanthir - A Lightweight, RESTful DICOM Server -=============================================== +Orthanc - A Lightweight, RESTful DICOM Server +============================================= -Palanthir has originally been written by Sebastien Jodogne +Orthanc has originally been written by Sebastien Jodogne (cf. "AUTHORS" file). This file contains the list of the people that -have further contributed to Palanthir by reporting problems, -suggesting various improvements, or submitting actual actual. Please -help keep it complete and exempt or errors. +have further contributed to Orthanc by reporting problems, suggesting +various improvements, or submitting actual actual. Please help keep it +complete and exempt or errors. Contributors