[FEATURE] Backend documentation module 22/22622/5
authorXavier Perseguers <xavier@typo3.org>
Sat, 27 Jul 2013 13:15:35 +0000 (15:15 +0200)
committerXavier Perseguers <xavier@typo3.org>
Sun, 28 Jul 2013 19:20:36 +0000 (21:20 +0200)
The documentation module brings back access to extension manuals and
lets official TYPO3 documents (such as guidelines, tutorials and
references) as well as custom documents to be listed in a central place.

Resolves: #50486
Releases: 6.2
Change-Id: Ib35a48f72682844f1bfe569763a561a89e7d810b
Reviewed-on: https://review.typo3.org/22622
Reviewed-by: Francois Suter
Tested-by: Francois Suter
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Stefan Neufeind
Reviewed-by: Xavier Perseguers
Tested-by: Xavier Perseguers
43 files changed:
typo3/sysext/documentation/Classes/Controller/DocumentController.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Domain/Model/Document.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Domain/Model/DocumentFormat.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Domain/Model/DocumentTranslation.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Domain/Repository/DocumentRepository.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Exception/Document.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Exception/XmlParser.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Service/DocumentationService.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Utility/GeneralUtility.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Utility/LanguageUtility.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/ViewHelpers/Be/Security/IfAdminViewHelper.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/ViewHelpers/FormatsViewHelper.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/ViewHelpers/Link/ActionViewHelper.php [new file with mode: 0644]
typo3/sysext/documentation/Configuration/TypoScript/constants.txt [new file with mode: 0644]
typo3/sysext/documentation/Configuration/TypoScript/setup.txt [new file with mode: 0644]
typo3/sysext/documentation/README.rst [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/.htaccess [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Language/locallang.xlf [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Language/locallang_mod.xlf [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Layouts/Default.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/.gitignore [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/helpers/_mixins.scss [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/main.css [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/main.scss [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/page/_base.scss [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/page/_get.scss [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Scss/page/_manage.scss [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Templates/Document/List.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Templates/Document/Manage.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/Css/README.txt [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/Css/jquery.clearable.css [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/Css/main.css [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/JavaScript/configuration.js [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/JavaScript/jquery.clearable.js [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/JavaScript/jquery.dataTables-1.9.4.min.js [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/JavaScript/jquery.tools.min.js [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/JavaScript/main.js [new file with mode: 0644]
typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentFormatTest.php [new file with mode: 0644]
typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTest.php [new file with mode: 0644]
typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTranslationTest.php [new file with mode: 0644]
typo3/sysext/documentation/ext_emconf.php [new file with mode: 0644]
typo3/sysext/documentation/ext_icon.gif [new file with mode: 0644]
typo3/sysext/documentation/ext_tables.php [new file with mode: 0644]

diff --git a/typo3/sysext/documentation/Classes/Controller/DocumentController.php b/typo3/sysext/documentation/Classes/Controller/DocumentController.php
new file mode 100644 (file)
index 0000000..aa2a8f4
--- /dev/null
@@ -0,0 +1,203 @@
+<?php
+namespace TYPO3\CMS\Documentation\Controller;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Andrea Schmuttermair <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Main controller of the Documentation module.
+ *
+ * @author Andrea Schmuttermair <spam@schmutt.de>
+ */
+class DocumentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
+
+       /**
+        * documentRepository
+        *
+        * @var \TYPO3\CMS\Documentation\Domain\Repository\DocumentRepository
+        * @inject
+        */
+       protected $documentRepository;
+
+       /**
+        * @var \TYPO3\CMS\Documentation\Service\DocumentationService
+        * @inject
+        */
+       protected $documentationService;
+
+       /**
+        * languageUtility
+        *
+        * @var \TYPO3\CMS\Documentation\Utility\LanguageUtility
+        * @inject
+        */
+       protected $languageUtility;
+
+       /**
+        * Signal Slot dispatcher
+        *
+        * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
+        * @inject
+        */
+       protected $signalSlotDispatcher;
+
+       /**
+        * Lists the available documents.
+        *
+        * @return void
+        */
+       public function listAction() {
+               $language = $this->languageUtility->getDocumentationLanguage();
+               $documents = $this->documentRepository->findByLanguage($language);
+
+               $this->signalSlotDispatcher->dispatch(
+                       __CLASS__,
+                       'afterInitializeDocuments',
+                       array(
+                               'language'  => $language,
+                               'documents' => &$documents,
+                       )
+               );
+
+               // Filter documents to be shown for current user
+               $hideDocuments = $this->getBackendUser()->getTSConfigVal('mod.help_DocumentationDocumentation.documents.hide');
+               $hideDocuments = GeneralUtility::trimExplode(',', $hideDocuments, TRUE);
+               if (count($hideDocuments) > 0) {
+                       $documents = array_diff_key($documents, array_flip($hideDocuments));
+               }
+               $showDocuments = $this->getBackendUser()->getTSConfigVal('mod.help_DocumentationDocumentation.documents.show');
+               $showDocuments = GeneralUtility::trimExplode(',', $showDocuments, TRUE);
+               if (count($showDocuments) > 0) {
+                       $documents = array_intersect_key($documents, array_flip($showDocuments));
+               }
+
+               $this->view->assign('documents', $documents);
+       }
+
+       /**
+        * Manages the documents.
+        *
+        * @return void
+        */
+       public function manageAction() {
+               // This action is reserved for admin users. Redirect to default view if not.
+               if (!$this->getBackendUser()->isAdmin()) {
+                       $this->redirect('list');
+               }
+
+               // Retrieve the list of official documents
+               $documents = $this->documentationService->getOfficialDocuments();
+
+               // Merge with the list of local extensions
+               $extensions = $this->documentationService->getLocalExtensions();
+               $allDocuments = array_merge($documents, $extensions);
+
+               $this->view->assign('documents', $allDocuments);
+       }
+
+       /**
+        * Downloads a document.
+        *
+        * @param string $url
+        * @param string $key
+        * @param string $version
+        * @return void
+        */
+       public function downloadAction($url, $key, $version = NULL) {
+               // This action is reserved for admin users. Redirect to default view if not.
+               if (!$this->getBackendUser()->isAdmin()) {
+                       $this->redirect('list');
+               }
+
+               try {
+                       $result = $this->documentationService->fetchNearestDocument($url, $key, $version ?: 'latest');
+
+                       if ($result) {
+                               $this->controllerContext->getFlashMessageQueue()->enqueue(
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                                               \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
+                                                       'downloadSucceeded',
+                                                       'documentation'
+                                               ),
+                                               '',
+                                               \TYPO3\CMS\Core\Messaging\AbstractMessage::OK,
+                                               TRUE
+                                       )
+                               );
+                       } else {
+                               $this->controllerContext->getFlashMessageQueue()->enqueue(
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                                               \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
+                                                       'downloadFailedNoArchive',
+                                                       'documentation'
+                                               ),
+                                               \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
+                                                       'downloadFailed',
+                                                       'documentation'
+                                               ),
+                                               \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR,
+                                               TRUE
+                                       )
+                               );
+                       }
+               } catch (\Exception $e) {
+                       $this->controllerContext->getFlashMessageQueue()->enqueue(
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                       'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                                       \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
+                                               'downloadFailedDetails',
+                                               'documentation',
+                                               array(
+                                                       $key,
+                                                       $e->getMessage(),
+                                                       $e->getCode()
+                                               )
+                                       ),
+                                       \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
+                                               'downloadFailed',
+                                               'documentation'
+                                       ),
+                                       \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR,
+                                       TRUE
+                               )
+                       );
+               }
+               $this->redirect('manage');
+       }
+
+       /**
+        * Get backend user
+        *
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        */
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Domain/Model/Document.php b/typo3/sysext/documentation/Classes/Domain/Model/Document.php
new file mode 100644 (file)
index 0000000..da2bdab
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+namespace TYPO3\CMS\Documentation\Domain\Model;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Andrea Schmuttermair <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An extension helper model to be used in ext:documentation context
+ *
+ * @entity
+ * @author Andrea Schmuttermair <spam@schmutt.de>
+ */
+class Document extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * packageKey
+        *
+        * @var string
+        * @validate NotEmpty
+        */
+       protected $packageKey;
+
+       /**
+        * icon
+        *
+        * @var string
+        */
+       protected $icon;
+
+       /**
+        * translations
+        *
+        * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation>
+        */
+       protected $translations;
+
+       /**
+        * Default constructor.
+        */
+       public function __construct() {
+               // Do not remove the next line: It would break the functionality
+               $this->initStorageObjects();
+       }
+
+       /**
+        * Initializes all ObjectStorage properties.
+        *
+        * @return void
+        */
+       protected function initStorageObjects() {
+               /**
+                * Do not modify this method!
+                * It will be rewritten on each save in the extension builder
+                * You may modify the constructor of this class instead
+                */
+               $this->translations = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+       }
+
+       /**
+        * Returns the package key.
+        *
+        * @return string $packageKey
+        */
+       public function getPackageKey() {
+               return $this->packageKey;
+       }
+
+       /**
+        * Sets the package key.
+        *
+        * @param string $packageKey
+        * @return Document
+        */
+       public function setPackageKey($packageKey) {
+               $this->packageKey = $packageKey;
+               return $this;
+       }
+
+       /**
+        * Returns the icon.
+        *
+        * @return string $icon
+        */
+       public function getIcon() {
+               return $this->icon;
+       }
+
+       /**
+        * Sets the icon.
+        *
+        * @param string $icon
+        * @return Document
+        */
+       public function setIcon($icon) {
+               $this->icon = $icon;
+               return $this;
+       }
+
+       /**
+        * Adds a document translation.
+        *
+        * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $translation
+        * @return Document
+        */
+       public function addTranslation(\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $translation) {
+               $this->translations->attach($translation);
+               return $this;
+       }
+
+       /**
+        * Removes a document translation.
+        *
+        * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $translationToRemove The DocumentTranslation to be removed
+        * @return Document
+        */
+       public function removeTranslation(\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $translationToRemove) {
+               $this->translations->detach($translationToRemove);
+               return $this;
+       }
+
+       /**
+        * Returns the translations.
+        *
+        * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation> $translations
+        */
+       public function getTranslations() {
+               return $this->translations;
+       }
+
+       /**
+        * Sets the translations.
+        *
+        * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation> $translations
+        * @return Document
+        */
+       public function setTranslations(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $translations) {
+               $this->translations = $translations;
+               return $this;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Domain/Model/DocumentFormat.php b/typo3/sysext/documentation/Classes/Domain/Model/DocumentFormat.php
new file mode 100644 (file)
index 0000000..7340615
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+namespace TYPO3\CMS\Documentation\Domain\Model;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Andrea Schmuttermair <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An extension helper model to be used in ext:documentation context
+ *
+ * @entity
+ * @author Andrea Schmuttermair <spam@schmutt.de>
+ */
+class DocumentFormat extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * format
+        *
+        * @var string
+        * @validate NotEmpty
+        */
+       protected $format;
+
+       /**
+        * path
+        *
+        * @var string
+        * @validate NotEmpty
+        */
+       protected $path;
+
+       /**
+        * Returns the format.
+        *
+        * @return string $format
+        */
+       public function getFormat() {
+               return $this->format;
+       }
+
+       /**
+        * Sets the format.
+        *
+        * @param string $format
+        * @return DocumentFormat
+        */
+       public function setFormat($format) {
+               $this->format = $format;
+               return $this;
+       }
+
+       /**
+        * Returns the path.
+        *
+        * @return string $path
+        */
+       public function getPath() {
+               return $this->path;
+       }
+
+       /**
+        * Sets the path.
+        *
+        * @param string $path
+        * @return DocumentFormat
+        */
+       public function setPath($path) {
+               $this->path = $path;
+               return $this;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Domain/Model/DocumentTranslation.php b/typo3/sysext/documentation/Classes/Domain/Model/DocumentTranslation.php
new file mode 100644 (file)
index 0000000..a5c082d
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+namespace TYPO3\CMS\Documentation\Domain\Model;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  (c) 2013 Andrea Schmuttermair <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An extension helper model to be used in ext:documentation context
+ *
+ * @entity
+ * @author Xavier Perseguers <xavier@typo3.org>
+ * @author Andrea Schmuttermair <spam@schmutt.de>
+ */
+class DocumentTranslation extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * language
+        * 2 char language identifier (or "" for default)
+        *
+        * @var string
+        * @validate NotEmpty
+        */
+       protected $language;
+
+       /**
+        * title
+        *
+        * @var string
+        */
+       protected $title;
+
+       /**
+        * description
+        *
+        * @var string
+        */
+       protected $description;
+
+       /**
+        * formats
+        *
+        * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentFormat>
+        */
+       protected $formats;
+
+       /**
+        * Default constructor.
+        */
+       public function __construct() {
+               // Do not remove the next line: It would break the functionality
+               $this->initStorageObjects();
+       }
+
+       /**
+        * Initializes all ObjectStorage properties.
+        *
+        * @return void
+        */
+       protected function initStorageObjects() {
+               /**
+                * Do not modify this method!
+                * It will be rewritten on each save in the extension builder
+                * You may modify the constructor of this class instead
+                */
+               $this->formats = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+       }
+
+       /**
+        * Returns the language.
+        *
+        * @return string $language
+        */
+       public function getLanguage() {
+               return $this->language;
+       }
+
+       /**
+        * Sets the language.
+        *
+        * @param string $language
+        * @return DocumentTranslation
+        */
+       public function setLanguage($language) {
+               $this->language = $language;
+               return $this;
+       }
+
+       /**
+        * Returns the title.
+        *
+        * @return string $title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * Sets the title.
+        *
+        * @param string $title
+        * @return DocumentTranslation
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+               return $this;
+       }
+
+       /**
+        * Returns the description.
+        *
+        * @return string $description
+        */
+       public function getDescription() {
+               return $this->description;
+       }
+
+       /**
+        * Sets the description.
+        *
+        * @param string $description
+        * @return DocumentTranslation
+        */
+       public function setDescription($description) {
+               $this->description = $description;
+               return $this;
+       }
+
+       /**
+        * Adds a documentation format.
+        *
+        * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $format
+        * @return DocumentTranslation
+        */
+       public function addFormat(\TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $format) {
+               $this->formats->attach($format);
+               return $this;
+       }
+
+       /**
+        * Removes a documentation format.
+        *
+        * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $formatToRemove The DocumentFormat to be removed
+        * @return DocumentTranslation
+        */
+       public function removeFormat(\TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $formatToRemove) {
+               $this->formats->detach($formatToRemove);
+               return $this;
+       }
+
+       /**
+        * Returns the formats.
+        *
+        * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentFormat> $formats
+        */
+       public function getFormats() {
+               return $this->formats;
+       }
+
+       /**
+        * Sets the formats.
+        *
+        * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Documentation\Domain\Model\DocumentFormat> $formats
+        * @return DocumentTranslation
+        */
+       public function setFormats(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $formats) {
+               $this->formats = $formats;
+               return $this;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Domain/Repository/DocumentRepository.php b/typo3/sysext/documentation/Classes/Domain/Repository/DocumentRepository.php
new file mode 100644 (file)
index 0000000..ae1321e
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+namespace TYPO3\CMS\Documentation\Domain\Repository;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An extension helper repository to be used in ext:documentation context
+ *
+ * @author Xavier Perseguers <xavier@typo3.org>
+ */
+class DocumentRepository {
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
+        * @inject
+        */
+       protected $objectManager;
+
+       /**
+        * Finds all documents.
+        *
+        * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
+        */
+       public function findAll() {
+               $documents = $this->findSphinxDocuments();
+               $openOfficeDocuments = $this->findOpenOfficeDocuments();
+
+               // Add OpenOffice documents if there is not already an existing, non OpenOffice version
+               foreach ($openOfficeDocuments as $documentKey => $document) {
+                       if (!isset($documents[$documentKey])) {
+                               $documents[$documentKey] = $document;
+                       }
+               }
+
+               return $documents;
+       }
+
+       /**
+        * Finds documents by language, always falls back to 'default' (English).
+        *
+        * @param string $language
+        * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
+        */
+       public function findByLanguage($language) {
+               $allDocuments = $this->findAll();
+
+               // Initialize the dependency of languages
+               $languageDependencies = array();
+               /** @var $locales \TYPO3\CMS\Core\Localization\Locales */
+               $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
+               // Language is found. Configure it:
+               if (in_array($language, $locales->getLocales())) {
+                       $languageDependencies[] = $language;
+                       foreach ($locales->getLocaleDependencies($language) as $languageDependency) {
+                               $languageDependencies[] = $languageDependency;
+                       }
+               }
+               if ($language !== 'default') {
+                       $languageDependencies[] = 'default';
+               }
+
+               foreach ($allDocuments as $document) {
+                       // Remove every unwanted translation
+                       $selectedTranslation = NULL;
+                       $highestPriorityLanguageIndex = count($languageDependencies);
+
+                       $translations = $document->getTranslations();
+                       foreach ($translations as $translation) {
+                               $languageIndex = array_search($translation->getLanguage(), $languageDependencies);
+                               if ($languageIndex !== FALSE && $languageIndex < $highestPriorityLanguageIndex) {
+                                       $selectedTranslation = $translation;
+                                       $highestPriorityLanguageIndex = $languageIndex;
+                               }
+                       }
+
+                       $newTranslations = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+                       $document->setTranslations($newTranslations);
+                       if ($selectedTranslation !== NULL) {
+                               $document->addTranslation($selectedTranslation);
+                       }
+
+               }
+
+               return $allDocuments;
+       }
+
+       /**
+        * Retrieves Sphinx documents.
+        *
+        * @return array
+        */
+       protected function findSphinxDocuments() {
+               $basePath = 'typo3conf/Documentation/';
+               $documents = array();
+
+               $documentKeys = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs(PATH_site . $basePath);
+               foreach ($documentKeys as $documentKey) {
+                       $icon = \TYPO3\CMS\Documentation\Utility\GeneralUtility::getIcon($documentKey);
+
+                       /** @var \TYPO3\CMS\Documentation\Domain\Model\Document $document */
+                       $document = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\Document')
+                               ->setPackageKey($documentKey)
+                               ->setIcon($icon);
+
+                       $languagePath = $basePath . $documentKey . '/';
+                       $languages = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs(PATH_site . $languagePath);
+                       foreach ($languages as $language) {
+                               $metadata = $this->getMetadata($documentKey, $language);
+
+                               /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation */
+                               $documentTranslation = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\DocumentTranslation')
+                                       ->setLanguage($language)
+                                       ->setTitle($metadata['title'])
+                                       ->setDescription($metadata['description']);
+
+                               $formatPath = $languagePath . $language . '/';
+                               $formats = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs(PATH_site . $formatPath);
+                               foreach ($formats as $format) {
+                                       $documentFile = '';
+                                       switch ($format) {
+                                               case 'html':
+                                                       $documentFile = 'Index.html';
+                                                       break;
+                                               case 'pdf':
+                                                       // Retrieve first PDF
+                                                       $files = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(PATH_site . $formatPath . $format, 'pdf');
+                                                       if (count($files) > 0) {
+                                                               $documentFile = current($files);
+                                                       }
+                                                       break;
+                                       }
+                                       if (!empty($documentFile) && is_file(PATH_site . $formatPath . $format . '/' . $documentFile)) {
+                                               /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $documentFormat */
+                                               $documentFormat = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\DocumentFormat')
+                                                       ->setFormat($format)
+                                                       ->setPath($formatPath . $format . '/' . $documentFile);
+
+                                               $documentTranslation->addFormat($documentFormat);
+                                       }
+                               }
+
+                               if (count($documentTranslation->getFormats()) > 0) {
+                                       $document->addTranslation($documentTranslation);
+                                       $documents[$documentKey] = $document;
+                               }
+                       }
+               }
+
+               return $documents;
+       }
+
+       /**
+        * Retrieves OpenOffice documents (manual.sxw).
+        *
+        * @return array
+        */
+       protected function findOpenOfficeDocuments() {
+               $documents = array();
+               $language = 'default';
+
+               foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $extensionKey => $extensionData) {
+                       $path = $extensionData['siteRelPath'] . 'doc/';
+                       if (is_file(PATH_site . $path . 'manual.sxw')) {
+                               $documentKey = 'typo3cms.extensions.' . $extensionKey;
+                               $icon = \TYPO3\CMS\Documentation\Utility\GeneralUtility::getIcon($documentKey);
+
+                               /** @var \TYPO3\CMS\Documentation\Domain\Model\Document $document */
+                               $document = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\Document')
+                                       ->setPackageKey($documentKey)
+                                       ->setIcon($icon);
+
+                               $metadata = $this->getMetadata($documentKey, $language);
+                               /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation */
+                               $documentTranslation = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\DocumentTranslation')
+                                       ->setLanguage($language)
+                                       ->setTitle($metadata['title'])
+                                       ->setDescription($metadata['description']);
+
+                               /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $documentFormat */
+                               $documentFormat = $this->objectManager->get('TYPO3\\CMS\\Documentation\\Domain\\Model\\DocumentFormat')
+                                       ->setFormat('sxw')
+                                       ->setPath($path . 'manual.sxw');
+
+                               $documentTranslation->addFormat($documentFormat);
+                               $document->addTranslation($documentTranslation);
+                               $documents[$documentKey] = $document;
+                       }
+               }
+
+               return $documents;
+       }
+
+       /**
+        * Returns metadata associated to a given document key.
+        *
+        * @param string $documentKey
+        * @param string $language
+        * @return array
+        */
+       protected function getMetadata($documentKey, $language) {
+               $documentPath = PATH_site . 'typo3conf/Documentation/' . $documentKey . '/' . $language . '/';
+               $metadata = array(
+                       'title' => $documentKey,
+                       'description' => '',
+               );
+               if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($documentKey, 'typo3cms.extensions.')) {
+                       $extensionKey = substr($documentKey, 20);
+                       if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey)) {
+                               $metadata = \TYPO3\CMS\Documentation\Utility\GeneralUtility::getExtensionMetaData($extensionKey);
+                       }
+               } elseif (is_file($documentPath . 'composer.json')) {
+                       $info = json_decode(file_get_contents($documentPath . 'composer.json'), TRUE);
+                       if (is_array($info)) {
+                               $metadata['title'] = $info['name'];
+                               $metadata['description'] = $info['description'];
+                       }
+               }
+               return $metadata;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Exception/Document.php b/typo3/sysext/documentation/Classes/Exception/Document.php
new file mode 100644 (file)
index 0000000..f2fb47a
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace TYPO3\CMS\Documentation\Exception;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An exception when something is wrong within the document
+ *
+ * @author Xavier Perseguers <xavier@typo3.org>
+ */
+class Document extends \TYPO3\CMS\Core\Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Exception/XmlParser.php b/typo3/sysext/documentation/Classes/Exception/XmlParser.php
new file mode 100644 (file)
index 0000000..cf54305
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace TYPO3\CMS\Documentation\Exception;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An exception when something is wrong within an XML file
+ *
+ * @author Xavier Perseguers <xavier@typo3.org>
+ */
+class XmlParser extends \TYPO3\CMS\Core\Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Service/DocumentationService.php b/typo3/sysext/documentation/Classes/Service/DocumentationService.php
new file mode 100644 (file)
index 0000000..b9efd81
--- /dev/null
@@ -0,0 +1,305 @@
+<?php
+namespace TYPO3\CMS\Documentation\Service;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use \TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Service class to connect to docs.typo3.org.
+ *
+ * @author Xavier Perseguers <xavier@typo3.org>
+ */
+class DocumentationService {
+
+       /**
+        * Returns the list of official documents on docs.typo3.org.
+        *
+        * @return array
+        */
+       public function getOfficialDocuments() {
+               $documents = array();
+
+               $json = GeneralUtility::getUrl('http://docs.typo3.org/typo3cms/documents.json');
+               if ($json) {
+                       $documents = json_decode($json, TRUE);
+                       foreach ($documents as &$document) {
+                               $document['icon'] = \TYPO3\CMS\Documentation\Utility\GeneralUtility::getIcon($document['key']);
+                       }
+
+                       // Cache file locally to be able to create a composer.json file when fetching a document
+                       $absoluteCacheFilename = GeneralUtility::getFileAbsFileName('typo3temp' . DIRECTORY_SEPARATOR . 'documents.json');
+                       GeneralUtility::writeFile($absoluteCacheFilename, $json);
+               }
+               return $documents;
+       }
+
+       /**
+        * Returns the list of local extensions.
+        *
+        * @return array
+        */
+       public function getLocalExtensions() {
+               $documents = array();
+
+               foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $extensionKey => $extensionData) {
+                       $absoluteExtensionPath = GeneralUtility::getFileAbsFileName($extensionData['siteRelPath']);
+                       if (is_file($absoluteExtensionPath . 'README.rst') || is_file($absoluteExtensionPath . 'Documentation' . DIRECTORY_SEPARATOR . 'Index.rst')) {
+                               $metadata = \TYPO3\CMS\Documentation\Utility\GeneralUtility::getExtensionMetaData($extensionKey);
+                               if ($extensionData['type'] === 'S') {
+                                       $version = TYPO3_branch;
+                               } else {
+                                       $version = substr($metadata['release'], -4) === '-dev' ? 'latest' : $metadata['release'];
+                               }
+
+                               $documentKey = 'typo3cms.extensions.' . $extensionKey;
+                               $documents[] = array(
+                                       'title'   => $metadata['title'],
+                                       'icon'    => \TYPO3\CMS\Documentation\Utility\GeneralUtility::getIcon($documentKey),
+                                       'type'    => 'Extension',
+                                       'key'     => $documentKey,
+                                       'url'     => 'http://docs.typo3.org/typo3cms/extensions/' . $extensionKey . '/',
+                                       'version' => $version,
+                               );
+                       }
+               }
+
+               return $documents;
+       }
+
+       /**
+        * Fetches the nearest version of a document from docs.typo3.org.
+        *
+        * Algorithm is as follows:
+        *
+        * 1) If exact version/language pair exists, fetch it
+        * 2) If document with version trimmed down to 2 digits and given language exists, fetch it
+        * 3) If document with version 'latest' and given language exists, fetch it
+        * 4) Restart at step 1) with language 'default'
+        *
+        * @param string $url
+        * @param string $key
+        * @param string $version
+        * @param string $language
+        * @return boolean TRUE if fetch succeeded, otherwise FALSE
+        */
+       public function fetchNearestDocument($url, $key, $version = 'latest', $language = 'default') {
+               $packages = $this->getAvailablePackages($url);
+               if (count($packages) == 0) {
+                       return FALSE;
+               }
+
+               $languages = array($language);
+               if ($language !== 'default') {
+                       $languages[] = 'default';
+               }
+               foreach ($languages as $language) {
+                       // Step 1)
+                       if (isset($packages[$version][$language])) {
+                               return $this->fetchDocument($url, $key, $version, $language);
+                       }
+                       // Step 2)
+                       if (preg_match('/^(\d+\.\d+)\.\d+$/', $version, $matches)) {
+                               // Instead of a 3-digit version, try to get it on 2 digits
+                               $shortVersion = $matches[1];
+                               if (isset($packages[$shortVersion][$language])) {
+                                       return $this->fetchDocument($url, $key, $shortVersion, $language);
+                               }
+                       }
+                       // Step 3)
+                       if ($version !== 'latest' && isset($packages['latest'][$language])) {
+                               return $this->fetchDocument($url, $key, 'latest', $language);
+                       }
+               }
+
+               // Could not find a working combination
+               return FALSE;
+       }
+
+       /**
+        * Fetches a document from docs.typo3.org.
+        *
+        * @param string $url
+        * @param string $key
+        * @param string $version
+        * @param string $language
+        * @return boolean TRUE if fetch succeeded, otherwise FALSE
+        */
+       public function fetchDocument($url, $key, $version = 'latest', $language = 'default') {
+               $result = FALSE;
+               $url = rtrim($url, '/') . '/';
+
+               $packagePrefix = substr($key, strrpos($key, '.') + 1);
+               $packageName = sprintf('%s-%s-%s.zip', $packagePrefix, $version, $language);
+               $packageUrl = $url . 'packages/' . $packageName;
+               $absolutePathToZipFile = GeneralUtility::getFileAbsFileName('typo3temp' . DIRECTORY_SEPARATOR . $packageName);
+
+               $packages = $this->getAvailablePackages($url);
+               if (count($packages) == 0 || !isset($packages[$version][$language])) {
+                       return FALSE;
+               }
+
+               // Check if a local version of the package is already present
+               $hasArchive = FALSE;
+               if (is_file($absolutePathToZipFile)) {
+                       $localMd5 = md5_file($absolutePathToZipFile);
+                       $remoteMd5 = $packages[$version][$language];
+                       $hasArchive = $localMd5 === $remoteMd5;
+               }
+
+               if (!$hasArchive) {
+                       /** @var $http \TYPO3\CMS\Core\Http\HttpRequest */
+                       $http = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Http\HttpRequest', $packageUrl);
+                       $response = $http->send();
+                       if ($response->getStatus() == 200) {
+                               GeneralUtility::writeFile($absolutePathToZipFile, $response->getBody());
+                       }
+               }
+
+               if (is_file($absolutePathToZipFile)) {
+                       $absoluteDocumentPath = GeneralUtility::getFileAbsFileName('typo3conf' . DIRECTORY_SEPARATOR . 'Documentation' . DIRECTORY_SEPARATOR);
+
+                       $result = $this->unzipDocumentPackage($absolutePathToZipFile, $absoluteDocumentPath);
+
+                       // Create a composer.json file
+                       $absoluteCacheFilename = GeneralUtility::getFileAbsFileName('typo3temp' . DIRECTORY_SEPARATOR . 'documents.json');
+                       $documents = json_decode(file_get_contents($absoluteCacheFilename), TRUE);
+                       foreach ($documents as $document) {
+                               if ($document['key'] === $key) {
+                                       $composerData = array(
+                                               'name' => $document['title'],
+                                               'type' => 'documentation',
+                                               'description' => 'TYPO3 ' . $document['type'],
+                                       );
+                                       $relativeComposerFilename = $key . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . 'composer.json';
+                                       $absoluteComposerFilename = GeneralUtility::getFileAbsFileName('typo3conf' . DIRECTORY_SEPARATOR . 'Documentation' . DIRECTORY_SEPARATOR . $relativeComposerFilename);
+                                       GeneralUtility::writeFile($absoluteComposerFilename, json_encode($composerData));
+                                       break;
+                               }
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * Returns the available packages (version + language) for a given
+        * document on docs.typo3.org.
+        *
+        * @param string $url
+        * @return array
+        */
+       protected function getAvailablePackages($url) {
+               $packages = array();
+               $url = rtrim($url, '/') . '/';
+               $indexUrl = $url . 'packages/packages.xml';
+
+               $remote = GeneralUtility::getUrl($indexUrl);
+               if ($remote) {
+                       $packages = $this->parsePackagesXML($remote);
+               }
+
+               return $packages;
+       }
+
+       /**
+        * Parses content of packages.xml into a suitable array.
+        *
+        * @param string $string: XML data to parse
+        * @throws \TYPO3\CMS\Documentation\Exception\XmlParser
+        * @return array Array representation of XML data
+        */
+       protected function parsePackagesXML($string) {
+               $data = json_decode(json_encode((array)simplexml_load_string($string)), TRUE);
+               if (count($data) != 2) {
+                       throw new \TYPO3\CMS\Documentation\Exception\XmlParser('Error in XML parser while decoding packages XML file.', 1374222437);
+               }
+
+               // SimpleXML does not properly handle arrays with only 1 item
+               if ($data['languagePackIndex']['languagepack'][0] === NULL) {
+                       $data['languagePackIndex']['languagepack'] = array($data['languagePackIndex']['languagepack']);
+               }
+
+               $packages = array();
+               foreach ($data['languagePackIndex']['languagepack'] as $languagePack) {
+                       $language = $languagePack['@attributes']['language'];
+                       $version = $languagePack['@attributes']['version'];
+                       $packages[$version][$language] = $languagePack['md5'];
+               }
+
+               return $packages;
+       }
+
+       /**
+        * Unzips a document package.
+        *
+        * @param string $file path to zip file
+        * @param string $path path to extract to
+        * @throws \TYPO3\CMS\Documentation\Exception\Document
+        * @return boolean
+        */
+       protected function unzipDocumentPackage($file, $path) {
+               $zip = zip_open($file);
+               if (is_resource($zip)) {
+                       $result = TRUE;
+
+                       if (!is_dir($path)) {
+                               GeneralUtility::mkdir_deep($path);
+                       }
+
+                       while (($zipEntry = zip_read($zip)) !== FALSE) {
+                               $zipEntryName = zip_entry_name($zipEntry);
+                               if (strpos($zipEntryName, '/') !== FALSE) {
+                                       $zipEntryPathSegments =  explode('/', $zipEntryName);
+                                       $fileName = array_pop($zipEntryPathSegments);
+                                       // It is a folder, because the last segment is empty, let's create it
+                                       if (empty($fileName)) {
+                                               GeneralUtility::mkdir_deep($path, implode('/', $zipEntryPathSegments));
+                                       } else {
+                                               $absoluteTargetPath = GeneralUtility::getFileAbsFileName($path . implode('/', $zipEntryPathSegments) . '/' . $fileName);
+                                               if (strlen(trim($absoluteTargetPath)) > 0) {
+                                                       $return = GeneralUtility::writeFile(
+                                                               $absoluteTargetPath, zip_entry_read($zipEntry, zip_entry_filesize($zipEntry))
+                                                       );
+                                                       if ($return === FALSE) {
+                                                               throw new \TYPO3\CMS\Documentation\Exception\Document('Could not write file ' . $zipEntryName, 1374161546);
+                                                       }
+                                               } else {
+                                                       throw new \TYPO3\CMS\Documentation\Exception\Document('Could not write file ' . $zipEntryName, 1374161532);
+                                               }
+                                       }
+                               } else {
+                                       throw new \TYPO3\CMS\Documentation\Exception\Document('Extension directory missing in zip file!', 1374161519);
+                               }
+                       }
+               } else {
+                       throw new \TYPO3\CMS\Documentation\Exception\Document('Unable to open zip file ' . $file, 1374161508);
+               }
+
+               return $result;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Utility/GeneralUtility.php b/typo3/sysext/documentation/Classes/Utility/GeneralUtility.php
new file mode 100644 (file)
index 0000000..de22000
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+namespace TYPO3\CMS\Documentation\Utility;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * General utility.
+ *
+ * @author Xavier Perseguers <xavier@typo3.org>
+ */
+class GeneralUtility {
+
+       /**
+        * Returns meta-data for a given extension.
+        *
+        * @param string $extensionKey
+        * @return array
+        */
+       static public function getExtensionMetaData($extensionKey) {
+               $_EXTKEY = $extensionKey;
+               $EM_CONF = array();
+               $extPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($extensionKey);
+               include($extPath . 'ext_emconf.php');
+
+               $release = $EM_CONF[$_EXTKEY]['version'];
+               list($major, $minor, $_) = explode('.', $release, 3);
+               if (($pos = strpos($minor, '-')) !== FALSE) {
+                       // $minor ~ '2-dev'
+                       $minor = substr($minor, 0, $pos);
+               }
+               $EM_CONF[$_EXTKEY]['version'] = $major . '.' . $minor;
+               $EM_CONF[$_EXTKEY]['release'] = $release;
+               $EM_CONF[$_EXTKEY]['extensionKey'] = $extensionKey;
+
+               return $EM_CONF[$_EXTKEY];
+       }
+
+       /**
+        * Returns the icon associated to a given document key.
+        *
+        * @param string $documentKey
+        * @return string
+        */
+       static public function getIcon($documentKey) {
+               $basePath = 'typo3conf/Documentation/';
+               $documentPath = $basePath . $documentKey . '/';
+
+               // Fallback icon
+               $icon = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('documentation') . 'ext_icon.gif';
+
+               if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($documentKey, 'typo3cms.extensions.')) {
+                       // Standard extension icon
+                       $extensionKey = substr($documentKey, 20);
+                       if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey)) {
+                               $icon = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath($extensionKey) . 'ext_icon.gif';
+                       }
+               } elseif (is_file(PATH_site . $documentPath . 'icon.png')) {
+                       $icon = $documentPath . 'icon.png';
+               } elseif (is_file(PATH_site . $documentPath . 'icon.gif')) {
+                       $icon = $documentPath . 'icon.gif';
+               }
+
+               return $icon;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/Utility/LanguageUtility.php b/typo3/sysext/documentation/Classes/Utility/LanguageUtility.php
new file mode 100644 (file)
index 0000000..fc9bc66
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+namespace TYPO3\CMS\Documentation\Utility;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Andrea Schmuttermair <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Utility for language selection.
+ *
+ * @author Andrea Schmuttermair <spam@schmutt.de>
+ */
+class LanguageUtility implements \TYPO3\CMS\Core\SingletonInterface {
+
+       /**
+        * Returns the language from BE User settings.
+        *
+        * @return string language identifier 2 chars or default (English)
+        */
+       public function getDocumentationLanguage() {
+               $backendLanguage = $GLOBALS['BE_USER']->uc['lang'] ?: 'default';
+               return $backendLanguage;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/ViewHelpers/Be/Security/IfAdminViewHelper.php b/typo3/sysext/documentation/Classes/ViewHelpers/Be/Security/IfAdminViewHelper.php
new file mode 100644 (file)
index 0000000..8dedeac
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+namespace TYPO3\CMS\Documentation\ViewHelpers\Be\Security;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Francois Suter, <francois.suter@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * This view helper checks whether a given BE user is admin or not.
+ *
+ * = Examples =
+ *
+ * <code title="Basic usage">
+ * <doc:be.security.ifAdmin>
+ * You see this is you're an admin.
+ * </doc:be.security.ifAdmin>
+ * </code>
+ * <output>
+ * You see this is you're an admin. (if an admin user, of course)
+ * </output>
+ *
+ * <code title="Usage with then / else">
+ * <doc:be.security.ifAdmin>
+ * <f:then>
+ * You see this is you're an admin.
+ * </f:then>
+ * <f:else>
+ * You see this is you're not an admin.
+ * </f:else>
+ * </doc:be.security.ifAdmin>
+ * </code>
+ * <output>
+ * Content of the "then" tag if an admin, content of the "else" tag otherwise.
+ * </output>
+ *
+ * @api
+ */
+class IfAdminViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper {
+
+       /**
+        * Renders <f:then> child if the current logged in BE user is an admin,
+        * otherwise renders <f:else> child.
+        *
+        * @return string the rendered string
+        * @api
+        */
+       public function render() {
+               if ($GLOBALS['BE_USER']->isAdmin()) {
+                       return $this->renderThenChild();
+               } else {
+                       return $this->renderElseChild();
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/ViewHelpers/FormatsViewHelper.php b/typo3/sysext/documentation/Classes/ViewHelpers/FormatsViewHelper.php
new file mode 100644 (file)
index 0000000..992f96a
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+namespace TYPO3\CMS\Documentation\ViewHelpers;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers, <xavier@typo3.org>
+ *  (c) 2013 Andrea Schmuttermair, <spam@schmutt.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * ViewHelper to display all download links for a document
+ *
+ * Example: <doc:formats document="{document}" />
+ */
+class FormatsViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
+
+       /**
+        * Renders all format download links.
+        *
+        * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation
+        * @return string
+        */
+       public function render(\TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation) {
+               $output = '';
+               foreach ($documentTranslation->getFormats() as $format) {
+                       /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $format */
+
+                       // TODO: Encode uri with official TYPO3 API?
+                       $uri = $this->controllerContext->getRequest()->getBaseURI() . '../' . $format->getPath();
+                       $extension = substr($uri, strrpos($uri, '.') + 1);
+                       if (strlen($extension) < 5) {
+                               // This is direct link to a file
+                               $output .= '<a href="' . $uri . '">' . htmlspecialchars($format->getFormat()) . '</a> ';
+                       } else {
+                               $output .= '<a href="#" onclick="top.TYPO3.Backend.ContentContainer.setUrl(\'' . $uri . '\')">' . htmlspecialchars($format->getFormat()) . '</a> ';
+                       }
+               }
+               return $output;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Classes/ViewHelpers/Link/ActionViewHelper.php b/typo3/sysext/documentation/Classes/ViewHelpers/Link/ActionViewHelper.php
new file mode 100644 (file)
index 0000000..289d2b8
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+namespace TYPO3\CMS\Documentation\ViewHelpers\Link;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers, <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * A view helper for creating links to extbase actions using the loading mask.
+ *
+ * = Examples =
+ *
+ * <code title="link to the show-action of the current controller">
+ * <d:link.action action="show">action link</d:link.action>
+ * </code>
+ * <output>
+ * <a href="#" onclick="top.TYPO3.Backend.ContentContainer.setUrl('index.php?id=123&tx_myextension_plugin[action]=show&tx_myextension_plugin[controller]=Standard&cHash=xyz')">action link</a>
+ * (depending on the current page and your TS configuration)
+ * </output>
+ */
+class ActionViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Link\ActionViewHelper {
+
+       /**
+        * Renders the extbase action link.
+        *
+        * @param string $action Target action
+        * @param array $arguments Arguments
+        * @param string $controller Target controller. If NULL current controllerName is used
+        * @param string $extensionName Target Extension Name (without "tx_" prefix and no underscores). If NULL the current extension name is used
+        * @param string $pluginName Target plugin. If empty, the current plugin name is used
+        * @param integer $pageUid target page. See TypoLink destination
+        * @param integer $pageType type of the target page. See typolink.parameter
+        * @param boolean $noCache set this to disable caching for the target page. You should not need this.
+        * @param boolean $noCacheHash set this to supress the cHash query parameter created by TypoLink. You should not need this.
+        * @param string $section the anchor to be added to the URI
+        * @param string $format The requested format, e.g. ".html
+        * @param boolean $linkAccessRestrictedPages If set, links pointing to access restricted pages will still link to the page even though the page cannot be accessed.
+        * @param array $additionalParams additional query parameters that won't be prefixed like $arguments (overrule $arguments)
+        * @param boolean $absolute If set, the URI of the rendered link is absolute
+        * @param boolean $addQueryString If set, the current query parameters will be kept in the URI
+        * @param array $argumentsToBeExcludedFromQueryString arguments to be removed from the URI. Only active if $addQueryString = TRUE
+        * @return string Rendered link
+        */
+       public function render($action = NULL, array $arguments = array(), $controller = NULL, $extensionName = NULL, $pluginName = NULL, $pageUid = NULL, $pageType = 0, $noCache = FALSE, $noCacheHash = FALSE, $section = '', $format = '', $linkAccessRestrictedPages = FALSE, array $additionalParams = array(), $absolute = FALSE, $addQueryString = FALSE, array $argumentsToBeExcludedFromQueryString = array()) {
+               $uriBuilder = $this->controllerContext->getUriBuilder();
+               $uri = $uriBuilder
+                       ->reset()
+                       ->setTargetPageUid($pageUid)
+                       ->setTargetPageType($pageType)
+                       ->setNoCache($noCache)
+                       ->setUseCacheHash(!$noCacheHash)
+                       ->setSection($section)
+                       ->setFormat($format)
+                       ->setLinkAccessRestrictedPages($linkAccessRestrictedPages)
+                       ->setArguments($additionalParams)
+                       ->setCreateAbsoluteUri($absolute)
+                       ->setAddQueryString($addQueryString)
+                       ->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)
+                       ->uriFor($action, $arguments, $controller, $extensionName, $pluginName);
+
+               $this->tag->addAttribute('href', '#');
+               $this->tag->addAttribute('onclick', 'top.TYPO3.Backend.ContentContainer.setUrl(\'' . $uri . '\')');
+               $this->tag->setContent($this->renderChildren());
+               $this->tag->forceClosingTag(TRUE);
+               return $this->tag->render();
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Configuration/TypoScript/constants.txt b/typo3/sysext/documentation/Configuration/TypoScript/constants.txt
new file mode 100644 (file)
index 0000000..3d8eaf3
--- /dev/null
@@ -0,0 +1,14 @@
+module.tx_documentation {
+       view {
+               # cat=module.tx_documentation/file; type=string; label=Path to template root (BE)
+               templateRootPath = EXT:documentation/Resources/Private/Backend/Templates/
+               # cat=module.tx_documentation/file; type=string; label=Path to template partials (BE)
+               partialRootPath = EXT:documentation/Resources/Private/Backend/Partials/
+               # cat=module.tx_documentation/file; type=string; label=Path to template layouts (BE)
+               layoutRootPath = EXT:documentation/Resources/Private/Backend/Layouts/
+       }
+       persistence {
+               # cat=module.tx_documentation//a; type=string; label=Default storage PID
+               storagePid =
+       }
+}
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Configuration/TypoScript/setup.txt b/typo3/sysext/documentation/Configuration/TypoScript/setup.txt
new file mode 100644 (file)
index 0000000..cf5e2dd
--- /dev/null
@@ -0,0 +1,11 @@
+# Module configuration
+module.tx_documentation {
+       persistence {
+               storagePid = {$module.tx_documentation.persistence.storagePid}
+       }
+       view {
+               templateRootPath = {$module.tx_documentation.view.templateRootPath}
+               partialRootPath = {$module.tx_documentation.view.partialRootPath}
+               layoutRootPath = {$module.tx_documentation.view.layoutRootPath}
+       }
+}
\ No newline at end of file
diff --git a/typo3/sysext/documentation/README.rst b/typo3/sysext/documentation/README.rst
new file mode 100644 (file)
index 0000000..7282b8b
--- /dev/null
@@ -0,0 +1,85 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+
+.. _start:
+
+=============
+Documentation
+=============
+
+This extension provides a Backend module for TYPO3 to show both the documentation of local extensions and custom
+documents.
+
+The Backend module features two actions:
+
+#. Show Documentation
+#. Manage Documentation
+
+
+Show Documentation
+==================
+
+This view shows a list of available documents:
+
+- Extensions with a manual rendered as ``html`` or ``pdf``;
+- Extensions with an OpenOffice manual (``sxw``);
+- Official TYPO3 documentation (tutorials, references, ...) available locally;
+- Custom documents, rendered either as ``html`` or ``pdf``.
+
+To be listed, documents should be stored within ``typo3conf/Documentation/<documentation-key>/<language>/<format>/``:
+
+``documentation-key``
+       Extensions use the documentation key ``typo3cms.extensions.<extension-key>``.
+
+``language``
+       Either "default" (for English) or some (generally) two-letter ISO code identifying a translation of your document.
+
+``format``
+       Either ``html`` or ``pdf``. Additional formats may be supported by 3rd party extensions (such as EXT:sphinx).
+
+
+Registering Custom Documents
+----------------------------
+
+#. Choose a documentation key such as ``<company>.<document-name>``
+
+#. Put your documentation as HTML (main file *must be* ``Index.html``) within
+   ``typo3conf/Documentation/<documentation-key>/default/html/`` or as PDF (any name will fit) within
+   ``typo3conf/Documentation/<documentation-key>/default/pdf/``
+
+#. Create a text description file ``composer.json`` containing the title and description of your documentation and place
+   it within ``typo3conf/Documentation/<documentation-key>/default/``:
+
+   .. code-block:: json
+
+       {
+           "name": "Put some title here",
+           "type": "documentation",
+           "description": "Put some description here."
+       }
+
+#. [optionally] Put a custom icon (either ``icon.png`` or ``icon.gif``) within directory
+   ``typo3conf/Documentation/<documentation-key>/``
+
+
+Manage Documentation
+====================
+
+This view is only accessible to TYPO3 administrators. It shows a form to retrieve rendered documentation for loaded
+extensions and to fetch a copy of official TYPO3 manuals, guides and references from http://docs.typo3.org.
+
+
+Configuration
+=============
+
+There are two User TSconfig options available:
+
+mod.help_DocumentationDocumentation.documents.hide
+  Comma-separated list of keys of documentation that should be hidden from the user.
+
+mod.help_DocumentationDocumentation.documents.show
+  Comma-separated list of keys of documentation that should be shown to the user (others are implicitly hidden).
+
diff --git a/typo3/sysext/documentation/Resources/Private/.htaccess b/typo3/sysext/documentation/Resources/Private/.htaccess
new file mode 100644 (file)
index 0000000..dfc0272
--- /dev/null
@@ -0,0 +1 @@
+deny  from all
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf b/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf
new file mode 100644 (file)
index 0000000..ba0a284
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2013-07-04T16:35:47Z" product-name="documentation">
+               <header/>
+               <body>
+
+                       <trans-unit id="documentation_manager">
+                               <source>Documentation Manager</source>
+                       </trans-unit>
+
+                       <trans-unit id="documentation.title">
+                               <source>Title</source>
+                       </trans-unit>
+                       <trans-unit id="documentation.type">
+                               <source>Type</source>
+                       </trans-unit>
+                       <trans-unit id="documentation.actions">
+                               <source>Actions</source>
+                       </trans-unit>
+                       <trans-unit id="documentation.actions.download">
+                               <source>Download document</source>
+                       </trans-unit>
+
+                       <trans-unit id="tx_documentation_domain_model_document">
+                               <source>Document</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_document.package_key">
+                               <source>Package Key</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_document.title">
+                               <source>Title</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_document.version">
+                               <source>Version</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_document.translations">
+                               <source>Translations</source>
+                       </trans-unit>
+
+                       <trans-unit id="tx_documentation_domain_model_documenttranslation">
+                               <source>Document Translation</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documenttranslation.language">
+                               <source>Language</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documenttranslation.title">
+                               <source>Title</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documenttranslation.description">
+                               <source>Description</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documenttranslation.formats">
+                               <source>Formats</source>
+                       </trans-unit>
+
+                       <trans-unit id="tx_documentation_domain_model_documentformat">
+                               <source>Document Format</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documentformat.format">
+                               <source>Format</source>
+                       </trans-unit>
+                       <trans-unit id="tx_documentation_domain_model_documentformat.path">
+                               <source>Path</source>
+                       </trans-unit>
+
+                       <trans-unit id="showDocumentation" xml:space="preserve">
+                               <source>Show Documentation</source>
+                       </trans-unit>
+                       <trans-unit id="manageDocumentation" xml:space="preserve">
+                               <source>Manage Documentation</source>
+                       </trans-unit>
+                       <trans-unit id="searchTemplate.submitButton" xml:space="preserve">
+                               <source>Go</source>
+                       </trans-unit>
+                       <trans-unit id="downloadSucceeded" xml:space="preserve">
+                               <source>The rendered documentation was downloaded successfully.</source>
+                       </trans-unit>
+                       <trans-unit id="downloadFailed" xml:space="preserve">
+                               <source>Download failed</source>
+                       </trans-unit>
+                       <trans-unit id="downloadFailedNoArchive" xml:space="preserve">
+                               <source>No rendered documentation archive could be found on docs.typo3.org.</source>
+                       </trans-unit>
+                       <trans-unit id="downloadFailedDetails" xml:space="preserve">
+                               <source>The documentation for "%s" could not be downloaded, because of the following error: %s (%d).</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Language/locallang_mod.xlf b/typo3/sysext/documentation/Resources/Private/Language/locallang_mod.xlf
new file mode 100644 (file)
index 0000000..7cf4f38
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2013-07-04T16:35:47Z" product-name="documentation">
+               <header/>
+               <body>
+                       <trans-unit id="mlang_tabs_tab">
+                               <source>Documentation</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_labels_tabdescr">
+                               <source>Backend module for TYPO3 to list and show documentation of loaded extensions as well as custom documents.</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_labels_tablabel">
+                               <source>Documentation</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Layouts/Default.html b/typo3/sysext/documentation/Resources/Private/Layouts/Default.html
new file mode 100644 (file)
index 0000000..b83bf5d
--- /dev/null
@@ -0,0 +1,38 @@
+{namespace doc=TYPO3\CMS\Documentation\ViewHelpers}
+
+<f:be.container pageTitle="{f:translate(key: 'documentation_manager')}" enableJumpToUrl="true" enableClickMenu="false" loadPrototype="false" loadScriptaculous="false" loadExtJs="false" loadExtJsTheme="true"
+
+       includeCssFiles="{
+               0:'{f:uri.resource(path:\'Css/main.css\')}',
+               2:'{f:uri.resource(path:\'Css/jquery.clearable.css\')}'
+       }"
+       includeJsFiles="{
+               0:'contrib/jquery/jquery-1.8.2.min.js',
+               1:'{f:uri.resource(path:\'JavaScript/jquery.dataTables-1.9.4.min.js\')}',
+               2:'{f:uri.resource(path:\'JavaScript/jquery.tools.min.js\')}',
+               2a:'{f:uri.resource(path:\'JavaScript/jquery.clearable.js\')}',
+               3:'{f:uri.resource(path:\'JavaScript/main.js\')}',
+               4:'{f:uri.resource(path:\'JavaScript/configuration.js\')}'
+       }">
+
+       <div id="typo3-docheader">
+               <div class="typo3-docheader-functions">
+                       <f:be.menus.actionMenu>
+                               <f:be.menus.actionMenuItem label="{f:translate(key: 'showDocumentation')}" controller="Document" action="list" />
+                               <doc:be.security.ifAdmin>
+                                       <f:be.menus.actionMenuItem label="{f:translate(key: 'manageDocumentation')}" controller="Document" action="manage" />
+                               </doc:be.security.ifAdmin>
+                       </f:be.menus.actionMenu>
+               </div>
+               <div class="typo3-docheader-buttons">
+                       <f:render section="docheader-buttons" />
+               </div>
+       </div>
+       <div id="typo3-docbody">
+               <div id="typo3-inner-docbody" class="typo3-documentation">
+                       <f:render section="module-headline" />
+                       <f:flashMessages renderMode="div" />
+                       <f:render section="Content" />
+               </div>
+       </div>
+</f:be.container>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/.gitignore b/typo3/sysext/documentation/Resources/Private/Scss/.gitignore
new file mode 100644 (file)
index 0000000..5df1b9b
--- /dev/null
@@ -0,0 +1 @@
+.sass-cache
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/helpers/_mixins.scss b/typo3/sysext/documentation/Resources/Private/Scss/helpers/_mixins.scss
new file mode 100644 (file)
index 0000000..14da817
--- /dev/null
@@ -0,0 +1,73 @@
+// SASS MIXINS
+$useIEFilters: 0;
+
+@mixin border-radius ($values) {
+       -webkit-border-radius: $values;
+          -moz-border-radius: $values;
+               border-radius: $values;
+}
+
+@mixin box-shadow ($values) {
+       -webkit-box-shadow: $values;
+               box-shadow: $values;
+}
+
+
+@mixin linear-gradient($preset, $from, $to, $ie: $useIEFilters) {
+       background-color: $preset;
+       background-image: -webkit-gradient(linear, left top, left bottom, from($from), to($to));
+       background-image: -webkit-linear-gradient(top, $from, $to);
+       background-image:    -moz-linear-gradient(top, $from, $to);
+       background-image:     -ms-linear-gradient(top, $from, $to);
+       background-image:      -o-linear-gradient(top, $from, $to);
+       background-image:         linear-gradient(to bottom, $from, $to);
+
+       @if $ie == 1 {
+               filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{$from}', endColorstr='#{$to}');
+       }
+}
+
+@mixin rotate ($deg) {
+       -webkit-transform: rotate(#{$deg}deg);
+          -moz-transform: rotate(#{$deg}deg);
+            -o-transform: rotate(#{$deg}deg);
+           -ms-transform: rotate(#{$deg}deg);
+               transform: rotate(#{$deg}deg);
+}
+
+@mixin scale ($size) {
+       -webkit-transform: scale(#{$size});
+          -moz-transform: scale(#{$size});
+            -o-transform: scale(#{$size});
+           -ms-transform: scale(#{$size});
+               transform: scale(#{$size});
+}
+
+@mixin transform ($values) {
+       -webkit-transform: #{$values};
+          -moz-transform: #{$values};
+            -o-transform: #{$values};
+           -ms-transform: #{$values};
+               transform: #{$values};
+}
+
+@mixin transition ($value) {
+       -webkit-transition: $value;
+          -moz-transition: $value;
+            -o-transition: $value;
+           -ms-transition: $value;
+               transition: $value;
+}
+
+
+// box-sizing
+@mixin box-sizing ($type: border-box) {
+       -webkit-box-sizing: $type;
+          -moz-box-sizing: $type;
+               box-sizing: $type;
+}
+
+// Hardware Xalleration
+@mixin xallerate ($values: '') {
+       @include transform(translate3d(0,0,0) #{$values});
+}
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/main.css b/typo3/sysext/documentation/Resources/Private/Scss/main.css
new file mode 100644 (file)
index 0000000..ed8eabe
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  Created: 2013-07-26
+ *
+ *  CSS in SASS's SCSS dialect for
+ *  TYPO3 Documentation Module v6.2.0
+ *  Questions can be submitted to xavier@typo3.org
+ *
+ */
+.ui-widget-header {
+  background: none;
+  border: none;
+  font-weight: normal; }
+
+.dataTable {
+  border-right: 1px solid #a2aab8;
+  border-bottom: 1px solid #a2aab8;
+  border-left: 1px solid #a2aab8; }
+
+.dataTables_info {
+  font-size: 10px;
+  color: #444;
+  float: left; }
+
+.paging_two_button .ui-button {
+  float: left;
+  cursor: pointer; }
+
+.paging_full_numbers .ui-button {
+  padding: 2px 6px;
+  margin: 0;
+  cursor: pointer;
+  color: #333 !important; }
+
+.dataTables_paginate .ui-button {
+  margin-right: -0.1em !important; }
+
+.paging_full_numbers {
+  float: right; }
+
+.dataTables_paginate {
+  width: auto; }
+
+.typo3-documentation-list {
+  width: 100%; }
+
+.typo3-documentation-list td {
+  padding: 10px; }
+
+.typo3-documentation-list td.title {
+  width: 280px; }
+
+.typo3-documentation-list td.icons {
+  width: 40px; }
+
+.typo3-documentation-list .icons a {
+  display: none; }
+
+.typo3-documentation-list tr:hover .icons a {
+  display: inline; }
+
+.typo3-documentation-list td.formats {
+  width: 140px; }
+  .typo3-documentation-list td.formats a {
+    padding: 2px; }
+    .typo3-documentation-list td.formats a:hover {
+      border: 1px solid #333; }
+
+.headerTooltip,
+.tooltip {
+  -webkit-box-shadow: 2px 2px 11px #666666;
+  box-shadow: 2px 2px 11px #666666;
+  display: none;
+  width: 400px;
+  background-color: #ffa;
+  border: 1px solid #cc9;
+  padding: 3px;
+  font-size: 13px;
+  z-index: 1000; }
+
+.headerTooltip {
+  width: 150px; }
+
+p {
+  padding-bottom: 20px; }
+
+.headerRow {
+  overflow: auto;
+  width: 100%; }
+
+.typo3-documentation-headerRowLeft {
+  float: left; }
+
+.typo3-documentation-headerRowRight {
+  float: right; }
+
+.ui-toolbar {
+  margin-bottom: 5px; }
+  .ui-toolbar .dataTables_filter {
+    display: block; }
+
+.typo3-documentation-list {
+  border-spacing: 0; }
+  .typo3-documentation-list thead {
+    background-color: #666; }
+    .typo3-documentation-list thead tr {
+      background: none !important; }
+      .typo3-documentation-list thead tr:hover {
+        background: none; }
+  .typo3-documentation-list th {
+    background: none;
+    border: 0;
+    padding: 8px 10px;
+    min-width: 53px;
+    vertical-align: middle;
+    font-weight: bold;
+    color: #fff;
+    cursor: pointer;
+    white-space: nowrap; }
+    .typo3-documentation-list th:hover {
+      background: rgba(200, 200, 200, 0.3); }
+    .typo3-documentation-list th .DataTables_sort_icon {
+      display: inline-block;
+      vertical-align: middle;
+      margin-left: 5px; }
+      .typo3-documentation-list th .DataTables_sort_icon.ui-icon-carat-2-n-s {
+        background: none; }
+  .typo3-documentation-list tr.odd td, .typo3-documentation-list tr.even td {
+    background: none; }
+  .typo3-documentation-list tr.odd:hover td, .typo3-documentation-list tr.even:hover td {
+    background: none; }
+  .typo3-documentation-list tr td {
+    background: none;
+    padding: 8px 10px;
+    vertical-align: middle; }
+    .typo3-documentation-list tr td img {
+      vertical-align: middle;
+      margin-right: 5px; }
+  .typo3-documentation-list tr:nth-child(2n) {
+    background: #fff; }
+  .typo3-documentation-list tr:nth-child(2n + 1) {
+    background: #f7f7f7; }
+  .typo3-documentation-list tr:hover {
+    background: #ececec; }
+
+.dataTables_info {
+  display: none; }
+
+.dataTables_paginate {
+  float: left;
+  margin: 10px 0 0; }
+
+.typo3-documentation-list .t3-icon,
+.typo3-documentation-list .t3-icon:hover {
+  border: none;
+  background-color: transparent; }
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/main.scss b/typo3/sysext/documentation/Resources/Private/Scss/main.scss
new file mode 100644 (file)
index 0000000..129f768
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  Created: 2013-07-26
+ *
+ *  CSS in SASS's SCSS dialect for
+ *  TYPO3 Documentation Module v6.2.0
+ *  Questions can be submitted to xavier@typo3.org
+ *
+ */
+
+// Some helpers
+@import "helpers/mixins";
+
+// Appearance of the page
+@import "page/base",
+               "page/manage",
+               "page/get";
+
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/page/_base.scss b/typo3/sysext/documentation/Resources/Private/Scss/page/_base.scss
new file mode 100644 (file)
index 0000000..9b2428c
--- /dev/null
@@ -0,0 +1,98 @@
+
+
+.ui-widget-header {
+       background: none;
+       border: none;
+       font-weight: normal;
+}
+
+.dataTable {
+       border-right: 1px solid #a2aab8;
+       border-bottom: 1px solid #a2aab8;
+       border-left: 1px solid #a2aab8;
+}
+
+.dataTables_info {
+       font-size: 10px;
+       color: #444;
+       float: left;
+}
+
+.paging_two_button .ui-button {
+       float: left;
+       cursor: pointer;
+}
+
+.paging_full_numbers .ui-button {
+       padding: 2px 6px;
+       margin: 0;
+       cursor: pointer;
+       color: #333 !important;
+}
+
+.dataTables_paginate .ui-button {
+       margin-right: -0.1em !important;
+}
+
+.paging_full_numbers {
+       float: right;
+}
+
+.dataTables_paginate {
+       width: auto;
+}
+
+.typo3-documentation-list {
+       width: 100%;
+}
+
+.typo3-documentation-list td {
+       padding: 10px;
+}
+
+.typo3-documentation-list td.title {
+       width: 280px;
+}
+
+.typo3-documentation-list td.icons {
+       width: 40px;
+}
+
+.typo3-documentation-list .icons a {
+       display: none;
+}
+
+.typo3-documentation-list tr:hover .icons a {
+       display: inline;
+}
+
+.typo3-documentation-list td.formats {
+       width: 140px;
+
+       a {
+               padding: 2px;
+
+               &:hover {
+                       border: 1px solid #333;
+               }
+       }
+}
+
+.headerTooltip,
+.tooltip {
+       @include box-shadow(2px 2px 11px #666);
+
+       display: none;
+       width: 400px;
+       background-color: #ffa;
+       border: 1px solid #cc9;
+       padding: 3px;
+       font-size: 13px;
+       z-index: 1000;
+}
+
+.headerTooltip {
+       width: 150px;
+}
+
+p { padding-bottom: 20px; }
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/page/_get.scss b/typo3/sysext/documentation/Resources/Private/Scss/page/_get.scss
new file mode 100644 (file)
index 0000000..545e24d
--- /dev/null
@@ -0,0 +1,11 @@
+
+.typo3-documentation-list {
+
+       .t3-icon,
+       .t3-icon:hover {
+               border: none;
+               background-color: transparent;
+       }
+
+}
+
diff --git a/typo3/sysext/documentation/Resources/Private/Scss/page/_manage.scss b/typo3/sysext/documentation/Resources/Private/Scss/page/_manage.scss
new file mode 100644 (file)
index 0000000..ce90245
--- /dev/null
@@ -0,0 +1,127 @@
+// Upload extension
+.headerRow { overflow: auto; width: 100% }
+
+.typo3-documentation-headerRowLeft {
+       float: left;
+}
+
+.typo3-documentation-headerRowRight {
+       float: right;
+}
+
+.ui-toolbar {
+       margin-bottom: 5px;
+
+       .dataTables_filter {
+               display: block;
+       }
+}
+
+
+
+// Table
+.typo3-documentation-list {
+
+       border-spacing: 0;
+
+       // Header
+       thead {
+               background-color: #666;
+
+               tr {
+                       background: none !important;
+
+                       &:hover {
+                               background: none;
+                       }
+               }
+       }
+
+       th {
+               background: none;
+               border: 0;
+               padding: 8px 10px;
+
+               min-width: 53px;
+
+               vertical-align: middle;
+
+               font-weight: bold;
+               color: #fff;
+
+               cursor: pointer;
+               white-space: nowrap;
+
+
+               &:hover {
+                       background: rgba(200,200,200,.3);
+               }
+
+               .DataTables_sort_icon {
+                       display: inline-block;
+                       vertical-align: middle;
+                       margin-left: 5px;
+
+                       &.ui-icon-carat-2-n-s {
+                               background: none;
+                       }
+               }
+       }
+
+       // All lines
+       tr {
+
+               // Reset some values that get applied by jQuery UI styling
+               &.odd,
+               &.even {
+                       td {
+                               background: none;
+                       }
+
+                       &:hover {
+                               td {
+                                       background: none;
+                               }
+                       }
+               }
+
+               // Add some stuff to match corporate design
+               td {
+                       background: none;
+                       padding: 8px 10px;
+                       vertical-align: middle;
+
+                       img {
+                               vertical-align: middle;
+                               margin-right: 5px;
+                       }
+               }
+
+               // Zebra-look
+               &:nth-child(2n) {
+                       background: #fff;
+               }
+
+               &:nth-child(2n + 1) {
+                       background: #f7f7f7;
+               }
+
+               // Hovering lines
+               &:hover {
+                       background: #ececec;
+               }
+
+       }
+}
+
+
+
+// Paginator
+.dataTables_info {
+       display: none;
+}
+
+.dataTables_paginate {
+       float: left;
+       margin: 10px 0 0;
+}
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html b/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html
new file mode 100644 (file)
index 0000000..23e2a7d
--- /dev/null
@@ -0,0 +1,47 @@
+{namespace doc=TYPO3\CMS\Documentation\ViewHelpers}
+
+<f:layout name="Default" />
+
+<f:section name="docheader-buttons">
+
+</f:section>
+
+<f:section name="module-headline">
+       <h1><f:translate key="showDocumentation">Show Documentation</f:translate></h1>
+</f:section>
+
+<f:section name="Content">
+
+       <div class="headerRow ui-helper-clearfix">
+               <div class="typo3-documentation-headerRowLeft">
+               </div>
+               <div class="typo3-documentation-headerRowRight">
+               </div>
+       </div>
+
+       <table id="typo3-documentation-list" class="typo3-documentation-list">
+               <thead>
+                       <tr>
+                               <th><f:translate key="tx_documentation_domain_model_document.title" /></th>
+                               <th><f:translate key="tx_documentation_domain_model_documenttranslation.description" /></th>
+                               <th><f:translate key="tx_documentation_domain_model_documenttranslation.formats" /></th>
+                       </tr>
+               </thead>
+               <tbody>
+                       <f:for each="{documents}" as="document">
+                               <f:for each="{document.translations}" as="translation">
+                                       <tr id="{document.packageKey}" >
+                                               <td class="title">
+                                                       <img src="../{document.icon}" title="{translation.title}" alt="{translation.title}" />
+                                                       {translation.title}
+                                               </td>
+                                               <td>{translation.description}</td>
+                                               <td class="formats">
+                                                       <doc:formats documentTranslation="{translation}" />
+                                               </td>
+                                       </tr>
+                               </f:for>
+                       </f:for>
+               </tbody>
+       </table>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Document/Manage.html b/typo3/sysext/documentation/Resources/Private/Templates/Document/Manage.html
new file mode 100644 (file)
index 0000000..3364d8f
--- /dev/null
@@ -0,0 +1,47 @@
+{namespace doc=TYPO3\CMS\Documentation\ViewHelpers}
+
+<f:layout name="Default"/>
+
+<f:section name="docheader-buttons">
+
+</f:section>
+
+<f:section name="module-headline">
+       <h1><f:translate key="manageDocumentation">Manage Documentation</f:translate></h1>
+</f:section>
+
+<f:section name="Content">
+
+       <div class="headerRow ui-helper-clearfix">
+               <div class="typo3-documentation-headerRowLeft">
+               </div>
+               <div class="typo3-documentation-headerRowRight">
+               </div>
+       </div>
+       <table id="typo3-documentation-manage" class="typo3-documentation-list">
+               <thead>
+               <tr>
+                       <th><f:translate key="documentation.actions" /></th>
+                       <th><f:translate key="documentation.title" /></th>
+                       <th><f:translate key="documentation.type" /></th>
+               </tr>
+               </thead>
+               <tbody>
+               <f:for each="{documents}" as="document">
+                       <tr id="{document.key}" >
+                               <td class="icons">
+                                       <doc:link.action action="download" arguments="{url:document.url, key:document.key, version:document.version}" title="{f:translate(key:'documentation.actions.download')}">
+                                               <span class="t3-icon t3-icon-actions t3-icon-system-extension-download">&nbsp;</span>
+                                       </doc:link.action>
+                               </td>
+                               <td class="title">
+                                       <img src="../{document.icon}" title="{document.title}" alt="{document.title}" />
+                                       {document.title}
+                               </td>
+                               <td>{document.type}</td>
+                       </tr>
+               </f:for>
+               </tbody>
+       </table>
+
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Public/Css/README.txt b/typo3/sysext/documentation/Resources/Public/Css/README.txt
new file mode 100644 (file)
index 0000000..6b3228b
--- /dev/null
@@ -0,0 +1,7 @@
+The main.css is generated from the SASS (in its dialect SCSS) files.
+Please do not edit the CSS-files in any case but search the correct .scss file
+and edit the according SCSS. If you are not familiar with SCSS
+you can write pure CSS which is actually valid SCSS.
+
+See http://wiki.typo3.org/Sass for details.
+
diff --git a/typo3/sysext/documentation/Resources/Public/Css/jquery.clearable.css b/typo3/sysext/documentation/Resources/Public/Css/jquery.clearable.css
new file mode 100644 (file)
index 0000000..5f26201
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Styles for the "clearable" jquery plugin.
+ */
+
+.t3-clearable-wrapper {
+       position: relative;
+    display: inline-block;
+}
+
+.t3-clearable {
+       height: 17px;
+       padding-right: 15px;
+}
+
+.t3-clearable-wrapper .t3-tceforms-input-clearer {
+       position: absolute;
+       right: 3px;
+       top: 5px;
+}
diff --git a/typo3/sysext/documentation/Resources/Public/Css/main.css b/typo3/sysext/documentation/Resources/Public/Css/main.css
new file mode 100644 (file)
index 0000000..ed8eabe
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  Created: 2013-07-26
+ *
+ *  CSS in SASS's SCSS dialect for
+ *  TYPO3 Documentation Module v6.2.0
+ *  Questions can be submitted to xavier@typo3.org
+ *
+ */
+.ui-widget-header {
+  background: none;
+  border: none;
+  font-weight: normal; }
+
+.dataTable {
+  border-right: 1px solid #a2aab8;
+  border-bottom: 1px solid #a2aab8;
+  border-left: 1px solid #a2aab8; }
+
+.dataTables_info {
+  font-size: 10px;
+  color: #444;
+  float: left; }
+
+.paging_two_button .ui-button {
+  float: left;
+  cursor: pointer; }
+
+.paging_full_numbers .ui-button {
+  padding: 2px 6px;
+  margin: 0;
+  cursor: pointer;
+  color: #333 !important; }
+
+.dataTables_paginate .ui-button {
+  margin-right: -0.1em !important; }
+
+.paging_full_numbers {
+  float: right; }
+
+.dataTables_paginate {
+  width: auto; }
+
+.typo3-documentation-list {
+  width: 100%; }
+
+.typo3-documentation-list td {
+  padding: 10px; }
+
+.typo3-documentation-list td.title {
+  width: 280px; }
+
+.typo3-documentation-list td.icons {
+  width: 40px; }
+
+.typo3-documentation-list .icons a {
+  display: none; }
+
+.typo3-documentation-list tr:hover .icons a {
+  display: inline; }
+
+.typo3-documentation-list td.formats {
+  width: 140px; }
+  .typo3-documentation-list td.formats a {
+    padding: 2px; }
+    .typo3-documentation-list td.formats a:hover {
+      border: 1px solid #333; }
+
+.headerTooltip,
+.tooltip {
+  -webkit-box-shadow: 2px 2px 11px #666666;
+  box-shadow: 2px 2px 11px #666666;
+  display: none;
+  width: 400px;
+  background-color: #ffa;
+  border: 1px solid #cc9;
+  padding: 3px;
+  font-size: 13px;
+  z-index: 1000; }
+
+.headerTooltip {
+  width: 150px; }
+
+p {
+  padding-bottom: 20px; }
+
+.headerRow {
+  overflow: auto;
+  width: 100%; }
+
+.typo3-documentation-headerRowLeft {
+  float: left; }
+
+.typo3-documentation-headerRowRight {
+  float: right; }
+
+.ui-toolbar {
+  margin-bottom: 5px; }
+  .ui-toolbar .dataTables_filter {
+    display: block; }
+
+.typo3-documentation-list {
+  border-spacing: 0; }
+  .typo3-documentation-list thead {
+    background-color: #666; }
+    .typo3-documentation-list thead tr {
+      background: none !important; }
+      .typo3-documentation-list thead tr:hover {
+        background: none; }
+  .typo3-documentation-list th {
+    background: none;
+    border: 0;
+    padding: 8px 10px;
+    min-width: 53px;
+    vertical-align: middle;
+    font-weight: bold;
+    color: #fff;
+    cursor: pointer;
+    white-space: nowrap; }
+    .typo3-documentation-list th:hover {
+      background: rgba(200, 200, 200, 0.3); }
+    .typo3-documentation-list th .DataTables_sort_icon {
+      display: inline-block;
+      vertical-align: middle;
+      margin-left: 5px; }
+      .typo3-documentation-list th .DataTables_sort_icon.ui-icon-carat-2-n-s {
+        background: none; }
+  .typo3-documentation-list tr.odd td, .typo3-documentation-list tr.even td {
+    background: none; }
+  .typo3-documentation-list tr.odd:hover td, .typo3-documentation-list tr.even:hover td {
+    background: none; }
+  .typo3-documentation-list tr td {
+    background: none;
+    padding: 8px 10px;
+    vertical-align: middle; }
+    .typo3-documentation-list tr td img {
+      vertical-align: middle;
+      margin-right: 5px; }
+  .typo3-documentation-list tr:nth-child(2n) {
+    background: #fff; }
+  .typo3-documentation-list tr:nth-child(2n + 1) {
+    background: #f7f7f7; }
+  .typo3-documentation-list tr:hover {
+    background: #ececec; }
+
+.dataTables_info {
+  display: none; }
+
+.dataTables_paginate {
+  float: left;
+  margin: 10px 0 0; }
+
+.typo3-documentation-list .t3-icon,
+.typo3-documentation-list .t3-icon:hover {
+  border: none;
+  background-color: transparent; }
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/configuration.js b/typo3/sysext/documentation/Resources/Public/JavaScript/configuration.js
new file mode 100644 (file)
index 0000000..a4ea4da
--- /dev/null
@@ -0,0 +1,46 @@
+// IIFE for faster access to $ and save $ use
+(function ($) {
+
+       $(document).ready(function() {
+               configurationFieldSupport();
+               $('.validate').validator();
+       });
+
+       function configurationFieldSupport() {
+               $('.offset').each(function() {
+                       $(this).hide();
+                       val = $(this).attr('value');
+                       valArr = val.split(',');
+
+                       $(this).wrap('<div class="offsetSelector"></div>');
+                       $(this).parent().append('x: <input value="' + $.trim(valArr[0]) + '" class="tempOffset1 tempOffset">');
+                       $(this).parent().append('<span>, </span>');
+                       $(this).parent().append('y: <input value="' + $.trim(valArr[1]) + '" class="tempOffset2 tempOffset">');
+
+                       $(this).siblings('.tempOffset').keyup(function() {
+                               $(this).siblings('.offset').attr(
+                                       'value',
+                                       $(this).parent().children('.tempOffset1').attr('value') + ',' + $(this).parent().children('.tempOffset2').attr('value')
+                               );
+                       });
+               });
+
+               $('.wrap').each(function() {
+                       $(this).hide();
+                       val = $(this).attr('value');
+                       valArr = val.split('|');
+
+                       $(this).wrap('<div class="wrapSelector"></div>');
+                       $(this).parent().append('<input value="' + $.trim(valArr[0]) + '" class="tempWrap1 tempWrap">');
+                       $(this).parent().append('<span>|</span>');
+                       $(this).parent().append('<input value="' + $.trim(valArr[1]) + '" class="tempWrap2 tempWrap">');
+
+                       $(this).siblings('.tempWrap').keyup(function() {
+                               $(this).siblings('.wrap').attr(
+                                       'value',
+                                       $(this).parent().children('.tempWrap1').attr('value') + '|' + $(this).parent().children('.tempWrap2').attr('value')
+                               );
+                       });
+               });
+       }
+}(jQuery));
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.clearable.js b/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.clearable.js
new file mode 100644 (file)
index 0000000..2c0c72f
--- /dev/null
@@ -0,0 +1,102 @@
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Jost Baron <j.baron@netzkoenig.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * This file provides a jQuery plugin for generating 'clearable' input fields.
+ * These fields show a "clear"-button when someone hovers over them and
+ * they are not empty.
+ * Options:
+ *   * 'onClear':      Function that is called after clearing. Takes no arguments,
+ *                                     'this' is set to the clearable input element. Defaults to an
+ *                                     empty function.
+ */
+(function($) {
+       $.fn.clearable = function(options) {
+
+               var defaults = {
+                       'onClear'       : function() {}
+               };
+
+               // Merge defaults and given options. Given options have higher priority
+               // because they are the last argument.
+               var settings = $.extend({}, defaults, options);
+
+               // Iterate over the list of inputs and make each clearable. Return
+               // the list to allow chaining.
+               return this.each(function() {
+
+                       // The input element to make clearable.
+                       var $input = $(this);
+
+                       // Wrap it with a div and add a span that is the trigger for
+                       // clearing.
+                       $input.wrap('<div class="t3-clearable-wrapper"/>');
+                       $input.after('<span class="t3-icon t3-icon-actions t3-icon-actions-input t3-icon-input-clear t3-tceforms-input-clearer"/>');
+                       $input.addClass('t3-clearable');
+
+                       var $wrapper = $input.parent();
+                       var $clearer = $input.next();
+
+                       // Add some data to the wrapper indicating if it is currently being
+                       // hovered or not.
+                       $input.data('isHovering', false);
+                       $wrapper.hover(
+                               function() {
+                                       $input.data('isHovering', true);
+                               },
+                               function() {
+                                       $input.data('isHovering', false);
+                       });
+
+                       // Register a listener the various events triggering the clearer to
+                       // be shown or hidden.
+                       var handler = function() {
+                               if ($input.data('isHovering') && ($input.val() != '')) {
+                                       $clearer.show();
+                               }
+                               else {
+                                       $clearer.hide();
+                               }
+                       };
+
+                       $wrapper.on('mouseover mouseout', handler);
+                       $input.on('keypress', handler);
+
+
+                       // The actual clearing action. Focus the input element afterwards,
+                       // the user probably wants to type into it after clearing.
+                       $clearer.click(function() {
+                               $input.val('');
+                               $input.focus();
+                               handler();
+
+                               if ('function' === typeof(settings.onClear)) {
+                                       settings.onClear.call($input.get());
+                               }
+                       });
+
+                       // Initialize the clearer icon
+                       handler();
+               });
+       };
+})(jQuery);
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.dataTables-1.9.4.min.js b/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.dataTables-1.9.4.min.js
new file mode 100644 (file)
index 0000000..02694a4
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * File:        jquery.dataTables.min.js
+ * Version:     1.9.4
+ * Author:      Allan Jardine (www.sprymedia.co.uk)
+ * Info:        www.datatables.net
+ * 
+ * Copyright 2008-2012 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, available at:
+ *   http://datatables.net/license_gpl2
+ *   http://datatables.net/license_bsd
+ * 
+ * This source file 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 license files for details.
+ */
+(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
+c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=
+L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==
+h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function G(a,b){var c=r(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function R(a,b){var c=r(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function t(a){return r(a,"bVisible").length}
+function r(a,b){var c=[];h.map(a.aoColumns,function(a,i){a[b]&&c.push(i)});return c}function B(a){for(var b=j.ext.aTypes,c=b.length,d=0;d<c;d++){var i=b[d](a);if(null!==i)return i}return"string"}function u(a,b){for(var c=b.split(","),d=[],i=0,f=a.aoColumns.length;i<f;i++)for(var g=0;g<f;g++)if(a.aoColumns[i].sName==c[g]){d.push(g);break}return d}function M(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";return b.length==d?"":b.slice(0,-1)}function ta(a,b,c,d){var i,f,
+g,e,w;if(b)for(i=b.length-1;0<=i;i--){var j=b[i].aTargets;h.isArray(j)||D(a,1,"aTargets must be an array of targets, not a "+typeof j);f=0;for(g=j.length;f<g;f++)if("number"===typeof j[f]&&0<=j[f]){for(;a.aoColumns.length<=j[f];)o(a);d(j[f],b[i])}else if("number"===typeof j[f]&&0>j[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;e<w;e++)("_all"==j[f]||h(a.aoColumns[e].nTh).hasClass(j[f]))&&d(e,b[i])}}if(c){i=0;for(a=c.length;i<a;i++)d(i,c[i])}}function H(a,
+b){var c;c=h.isArray(b)?b.slice():h.extend(!0,{},b);var d=a.aoData.length,i=h.extend(!0,{},j.models.oRow);i._aData=c;a.aoData.push(i);for(var f,i=0,g=a.aoColumns.length;i<g;i++)c=a.aoColumns[i],"function"===typeof c.fnRender&&c.bUseRendered&&null!==c.mData?F(a,d,i,S(a,d,i)):F(a,d,i,v(a,d,i)),c._bAutoType&&"string"!=c.sType&&(f=v(a,d,i,"type"),null!==f&&""!==f&&(f=B(f),null===c.sType?c.sType=f:c.sType!=f&&"html"!=c.sType&&(c.sType="string")));a.aiDisplayMaster.push(d);a.oFeatures.bDeferRender||ea(a,
+d);return d}function ua(a){var b,c,d,i,f,g,e;if(a.bDeferLoading||null===a.sAjaxSource)for(b=a.nTBody.firstChild;b;){if("TR"==b.nodeName.toUpperCase()){c=a.aoData.length;b._DT_RowIndex=c;a.aoData.push(h.extend(!0,{},j.models.oRow,{nTr:b}));a.aiDisplayMaster.push(c);f=b.firstChild;for(d=0;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)F(a,c,d,h.trim(f.innerHTML)),d++;f=f.nextSibling}}b=b.nextSibling}i=T(a);d=[];b=0;for(c=i.length;b<c;b++)for(f=i[b].firstChild;f;)g=f.nodeName.toUpperCase(),("TD"==
+g||"TH"==g)&&d.push(f),f=f.nextSibling;c=0;for(i=a.aoColumns.length;c<i;c++){e=a.aoColumns[c];null===e.sTitle&&(e.sTitle=e.nTh.innerHTML);var w=e._bAutoType,o="function"===typeof e.fnRender,k=null!==e.sClass,n=e.bVisible,m,p;if(w||o||k||!n){g=0;for(b=a.aoData.length;g<b;g++)f=a.aoData[g],m=d[g*i+c],w&&"string"!=e.sType&&(p=v(a,g,c,"type"),""!==p&&(p=B(p),null===e.sType?e.sType=p:e.sType!=p&&"html"!=e.sType&&(e.sType="string"))),e.mRender?m.innerHTML=v(a,g,c,"display"):e.mData!==c&&(m.innerHTML=v(a,
+g,c,"display")),o&&(p=S(a,g,c),m.innerHTML=p,e.bUseRendered&&F(a,g,c,p)),k&&(m.className+=" "+e.sClass),n?f._anHidden[c]=null:(f._anHidden[c]=m,m.parentNode.removeChild(m)),e.fnCreatedCell&&e.fnCreatedCell.call(a.oInstance,m,v(a,g,c,"display"),f._aData,g,c)}}if(0!==a.aoRowCreatedCallback.length){b=0;for(c=a.aoData.length;b<c;b++)f=a.aoData[b],A(a,"aoRowCreatedCallback",null,[f.nTr,f._aData,b])}}function I(a,b){return b._DT_RowIndex!==n?b._DT_RowIndex:null}function fa(a,b,c){for(var b=J(a,b),d=0,a=
+a.aoColumns.length;d<a;d++)if(b[d]===c)return d;return-1}function Y(a,b,c,d){for(var i=[],f=0,g=d.length;f<g;f++)i.push(v(a,b,d[f],c));return i}function v(a,b,c,d){var i=a.aoColumns[c];if((c=i.fnGetData(a.aoData[b]._aData,d))===n)return a.iDrawError!=a.iDraw&&null===i.sDefaultContent&&(D(a,0,"Requested unknown parameter "+("function"==typeof i.mData?"{mData function}":"'"+i.mData+"'")+" from the data source for row "+b),a.iDrawError=a.iDraw),i.sDefaultContent;if(null===c&&null!==i.sDefaultContent)c=
+i.sDefaultContent;else if("function"===typeof c)return c();return"display"==d&&null===c?"":c}function F(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d)}function Q(a){if(null===a)return function(){return null};if("function"===typeof a)return function(b,d,i){return a(b,d,i)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var f=i.split("."),g;if(""!==i){var e=0;for(g=f.length;e<g;e++){if(i=f[e].match(U)){f[e]=f[e].replace(U,"");""!==f[e]&&(a=a[f[e]]);
+g=[];f.splice(0,e+1);for(var f=f.join("."),e=0,h=a.length;e<h;e++)g.push(b(a[e],d,f));a=i[0].substring(1,i[0].length-1);a=""===a?g:g.join(a);break}if(null===a||a[f[e]]===n)return n;a=a[f[e]]}}return a};return function(c,d){return b(c,d,a)}}return function(b){return b[a]}}function L(a){if(null===a)return function(){};if("function"===typeof a)return function(b,d){a(b,"set",d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var i=i.split("."),f,g,e=0;for(g=
+i.length-1;e<g;e++){if(f=i[e].match(U)){i[e]=i[e].replace(U,"");a[i[e]]=[];f=i.slice();f.splice(0,e+1);g=f.join(".");for(var h=0,j=d.length;h<j;h++)f={},b(f,d[h],g),a[i[e]].push(f);return}if(null===a[i[e]]||a[i[e]]===n)a[i[e]]={};a=a[i[e]]}a[i[i.length-1].replace(U,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Z(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function ga(a){a.aoData.splice(0,a.aoData.length);a.aiDisplayMaster.splice(0,
+a.aiDisplayMaster.length);a.aiDisplay.splice(0,a.aiDisplay.length);y(a)}function ha(a,b){for(var c=-1,d=0,i=a.length;d<i;d++)a[d]==b?c=d:a[d]>b&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&
+(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i<f;i++){var g=a.aoColumns[i];d=l.createElement(g.sCellType);d.innerHTML="function"===typeof g.fnRender&&(!g.bUseRendered||null===g.mData)?S(a,b,i):v(a,b,i,"display");null!==g.sClass&&(d.className=g.sClass);g.bVisible?(c.nTr.appendChild(d),c._anHidden[i]=null):c._anHidden[i]=d;g.fnCreatedCell&&g.fnCreatedCell.call(a.oInstance,d,v(a,b,i,"display"),c._aData,b,i)}A(a,"aoRowCreatedCallback",null,[c.nTr,c._aData,b])}}function va(a){var b,
+c,d;if(0!==h("th, td",a.nTHead).length){b=0;for(d=a.aoColumns.length;b<d;b++)if(c=a.aoColumns[b].nTh,c.setAttribute("role","columnheader"),a.aoColumns[b].bSortable&&(c.setAttribute("tabindex",a.iTabIndex),c.setAttribute("aria-controls",a.sTableId)),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{var i=l.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++)c=a.aoColumns[b].nTh,c.innerHTML=a.aoColumns[b].sTitle,
+c.setAttribute("tabindex","0"),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),i.appendChild(c);h(a.nTHead).html("")[0].appendChild(i);V(a.aoHeader,a.nTHead)}h(a.nTHead).children("tr").attr("role","row");if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;i=l.createElement("div");i.className=a.oClasses.sSortJUIWrapper;h(c).contents().appendTo(i);var f=l.createElement("span");f.className=a.oClasses.sSortIcon;i.appendChild(f);c.appendChild(i)}}if(a.oFeatures.bSort)for(b=
+0;b<a.aoColumns.length;b++)!1!==a.aoColumns[b].bSortable?ia(a,a.aoColumns[b].nTh,b):h(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone);""!==a.oClasses.sFooterTH&&h(a.nTFoot).children("tr").children("th").addClass(a.oClasses.sFooterTH);if(null!==a.nTFoot){c=N(a,null,a.aoFooter);b=0;for(d=a.aoColumns.length;b<d;b++)c[b]&&(a.aoColumns[b].nTf=c[b],a.aoColumns[b].sClass&&h(c[b]).addClass(a.aoColumns[b].sClass))}}function W(a,b,c){var d,i,f,g=[],e=[],h=a.aoColumns.length,j;c===n&&(c=!1);d=0;for(i=
+b.length;d<i;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=h-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);e.push([])}d=0;for(i=g.length;d<i;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(j=h=1,e[d][f]===n){a.appendChild(g[d][f].cell);for(e[d][f]=1;g[d+h]!==n&&g[d][f].cell==g[d+h][f].cell;)e[d+h][f]=1,h++;for(;g[d][f+j]!==n&&g[d][f].cell==g[d][f+j].cell;){for(c=0;c<h;c++)e[d+c][f+j]=1;j++}g[d][f].cell.rowSpan=h;g[d][f].cell.colSpan=j}}}function x(a){var b=
+A(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))E(a,!1);else{var c,d,b=[],i=0,f=a.asStripeClasses.length;c=a.aoOpenRows.length;a.bDrawing=!0;a.iInitDisplayStart!==n&&-1!=a.iInitDisplayStart&&(a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g=
+a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g<d;g++){var e=a.aoData[a.aiDisplay[g]];null===e.nTr&&ea(a,a.aiDisplay[g]);var j=e.nTr;if(0!==f){var o=a.asStripeClasses[i%f];e._sRowStripe!=o&&(h(j).removeClass(e._sRowStripe).addClass(o),e._sRowStripe=o)}A(a,"aoRowCallback",null,[j,a.aoData[a.aiDisplay[g]]._aData,i,g]);b.push(j);i++;if(0!==c)for(e=0;e<c;e++)if(j==a.aoOpenRows[e].nParent){b.push(a.aoOpenRows[e].nTr);break}}}else b[0]=l.createElement("tr"),a.asStripeClasses[0]&&
+(b[0].className=a.asStripeClasses[0]),c=a.oLanguage,f=c.sZeroRecords,1==a.iDraw&&null!==a.sAjaxSource&&!a.oFeatures.bServerSide?f=c.sLoadingRecords:c.sEmptyTable&&0===a.fnRecordsTotal()&&(f=c.sEmptyTable),c=l.createElement("td"),c.setAttribute("valign","top"),c.colSpan=t(a),c.className=a.oClasses.sRowEmpty,c.innerHTML=ja(a,f),b[i].appendChild(c);A(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);A(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],
+Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);i=l.createDocumentFragment();c=l.createDocumentFragment();if(a.nTBody){f=a.nTBody.parentNode;c.appendChild(a.nTBody);if(!a.oScroll.bInfinite||!a._bInitComplete||a.bSorted||a.bFiltered)for(;c=a.nTBody.firstChild;)a.nTBody.removeChild(c);c=0;for(d=b.length;c<d;c++)i.appendChild(b[c]);a.nTBody.appendChild(i);null!==f&&f.appendChild(a.nTBody)}A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1;a.oFeatures.bServerSide&&(E(a,!1),
+a._bInitComplete||$(a))}}function aa(a){a.oFeatures.bSort?O(a,a.oPreviousSearch):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(y(a),x(a))}function xa(a){var b=h("<div></div>")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('<div id="'+a.sTableId+'_wrapper" class="'+a.oClasses.sWrapper+'" role="grid"></div>')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m<d.length;m++){f=0;g=d[m];if("<"==g){e=h("<div></div>")[0];w=d[m+
+1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f=
+1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k<w;k++)if(g==e[k].cFeature){(i=e[k].fnInit(a))&&(f=1);break}}1==f&&null!==i&&("object"!==typeof a.aanFeatures[g]&&(a.aanFeatures[g]=[]),a.aanFeatures[g].push(i),c.appendChild(i))}b.parentNode.replaceChild(a.nTableWrapper,b)}function V(a,b){var c=h(b).children("tr"),d,i,f,g,e,j,o,k,m,p;a.splice(0,a.length);
+f=0;for(j=c.length;f<j;f++)a.push([]);f=0;for(j=c.length;f<j;f++){d=c[f];for(i=d.firstChild;i;){if("TD"==i.nodeName.toUpperCase()||"TH"==i.nodeName.toUpperCase()){k=1*i.getAttribute("colspan");m=1*i.getAttribute("rowspan");k=!k||0===k||1===k?1:k;m=!m||0===m||1===m?1:m;g=0;for(e=a[f];e[g];)g++;o=g;p=1===k?!0:!1;for(e=0;e<k;e++)for(g=0;g<m;g++)a[f+g][o+e]={cell:i,unique:p},a[f+g].nTr=d}i=i.nextSibling}}}function N(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],V(c,b)));for(var b=0,i=c.length;b<i;b++)for(var f=
+0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function wa(a){if(a.bAjaxDataGet){a.iDraw++;E(a,!0);var b=Ea(a);ka(a,b);a.fnServerData.call(a.oInstance,a.sAjaxSource,b,function(b){Fa(a,b)},a);return!1}return!0}function Ea(a){var b=a.aoColumns.length,c=[],d,i,f,g;c.push({name:"sEcho",value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:M(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength",
+value:!1!==a.oFeatures.bPaginate?a._iDisplayLength:-1});for(f=0;f<b;f++)d=a.aoColumns[f].mData,c.push({name:"mDataProp_"+f,value:"function"===typeof d?"function":d});if(!1!==a.oFeatures.bFilter){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(f=0;f<b;f++)c.push({name:"sSearch_"+f,value:a.aoPreSearchCols[f].sSearch}),c.push({name:"bRegex_"+f,value:a.aoPreSearchCols[f].bRegex}),c.push({name:"bSearchable_"+f,value:a.aoColumns[f].bSearchable})}if(!1!==
+a.oFeatures.bSort){var e=0;d=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(f=0;f<d.length;f++){i=a.aoColumns[d[f][0]].aDataSort;for(g=0;g<i.length;g++)c.push({name:"iSortCol_"+e,value:i[g]}),c.push({name:"sSortDir_"+e,value:d[f][1]}),e++}c.push({name:"iSortingCols",value:e});for(f=0;f<b;f++)c.push({name:"bSortable_"+f,value:a.aoColumns[f].bSortable})}return c}function ka(a,b){A(a,"aoServerParams","serverParams",[b])}function Fa(a,b){if(b.sEcho!==n){if(1*b.sEcho<
+a.iDraw)return;a.iDraw=1*b.sEcho}(!a.oScroll.bInfinite||a.oScroll.bInfinite&&(a.bSorted||a.bFiltered))&&ga(a);a._iRecordsTotal=parseInt(b.iTotalRecords,10);a._iRecordsDisplay=parseInt(b.iTotalDisplayRecords,10);var c=M(a),c=b.sColumns!==n&&""!==c&&b.sColumns!=c,d;c&&(d=u(a,b.sColumns));for(var i=Q(a.sAjaxDataProp)(b),f=0,g=i.length;f<g;f++)if(c){for(var e=[],h=0,j=a.aoColumns.length;h<j;h++)e.push(i[f][d[h]]);H(a,e)}else H(a,i[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;x(a);a.bAjaxDataGet=
+!0;E(a,!1)}function za(a){var b=a.oPreviousSearch,c=a.oLanguage.sSearch,c=-1!==c.indexOf("_INPUT_")?c.replace("_INPUT_",'<input type="text" />'):""===c?'<input type="text" />':c+' <input type="text" />',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="<label>"+c+"</label>";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"&quot;"));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,
+g=0,e=c.length;g<e;g++)c[g]!=h(this).parents("div.dataTables_filter")[0]&&h(c[g]._DT_Input).val(d);d!=b.sSearch&&K(a,{sSearch:d,bRegex:b.bRegex,bSmart:b.bSmart,bCaseInsensitive:b.bCaseInsensitive})});c.attr("aria-controls",a.sTableId).bind("keypress.DT",function(a){if(a.keyCode==13)return false});return d}function K(a,b,c){var d=a.oPreviousSearch,i=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};if(a.oFeatures.bServerSide)f(b);
+else{Ga(a,b.sSearch,c,b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<a.aoPreSearchCols.length;b++)Ha(a,i[b].sSearch,b,i[b].bRegex,i[b].bSmart,i[b].bCaseInsensitive);Ia(a)}a.bFiltered=!0;h(a.oInstance).trigger("filter",a);a._iDisplayStart=0;y(a);x(a);la(a,0)}function Ia(a){for(var b=j.ext.afnFiltering,c=r(a,"bSearchable"),d=0,i=b.length;d<i;d++)for(var f=0,g=0,e=a.aiDisplay.length;g<e;g++){var h=a.aiDisplay[g-f];b[d](a,Y(a,h,"filter",c),h)||(a.aiDisplay.splice(g-f,1),f++)}}function Ha(a,b,c,
+d,i,f){if(""!==b)for(var g=0,b=ma(b,d,i,f),d=a.aiDisplay.length-1;0<=d;d--)i=Ja(v(a,a.aiDisplay[d],c,"filter"),a.aoColumns[c].sType),b.test(i)||(a.aiDisplay.splice(d,1),g++)}function Ga(a,b,c,d,i,f){d=ma(b,d,i,f);i=a.oPreviousSearch;c||(c=0);0!==j.ext.afnFiltering.length&&(c=1);if(0>=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0,
+a.aiDisplay.length);la(a,1);for(b=0;b<a.aiDisplayMaster.length;b++)d.test(a.asDataSearch[b])&&a.aiDisplay.push(a.aiDisplayMaster[b])}else for(b=c=0;b<a.asDataSearch.length;b++)d.test(a.asDataSearch[b])||(a.aiDisplay.splice(b-c,1),c++)}function la(a,b){if(!a.oFeatures.bServerSide){a.asDataSearch=[];for(var c=r(a,"bSearchable"),d=1===b?a.aiDisplayMaster:a.aiDisplay,i=0,f=d.length;i<f;i++)a.asDataSearch[i]=na(a,Y(a,d[i],"filter",c))}}function na(a,b){var c=b.join("  ");-1!==c.indexOf("&")&&(c=h("<div>").html(c).text());
+return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),
+"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g);
+null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b<c;b++)h(a[b]).html(g)}}function ja(a,b){var c=a.fnFormatNumber(a._iDisplayStart+1),d=a.fnDisplayEnd(),d=a.fnFormatNumber(d),i=a.fnRecordsDisplay(),i=a.fnFormatNumber(i),f=a.fnRecordsTotal(),f=a.fnFormatNumber(f);a.oScroll.bInfinite&&(c=a.fnFormatNumber(1));return b.replace(/_START_/g,c).replace(/_END_/g,d).replace(/_TOTAL_/g,i).replace(/_MAX_/g,f)}function ba(a){var b,c,d=a.iInitDisplayStart;
+if(!1===a.bInitialised)setTimeout(function(){ba(a)},200);else{xa(a);va(a);W(a,a.aoHeader);a.nTFoot&&W(a,a.aoFooter);E(a,!0);a.oFeatures.bAutoWidth&&da(a);b=0;for(c=a.aoColumns.length;b<c;b++)null!==a.aoColumns[b].sWidth&&(a.aoColumns[b].nTh.style.width=q(a.aoColumns[b].sWidth));a.oFeatures.bSort?O(a):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(a.aiDisplay=a.aiDisplayMaster.slice(),y(a),x(a));null!==a.sAjaxSource&&!a.oFeatures.bServerSide?(c=[],ka(a,c),a.fnServerData.call(a.oInstance,a.sAjaxSource,
+c,function(c){var f=a.sAjaxDataProp!==""?Q(a.sAjaxDataProp)(c):c;for(b=0;b<f.length;b++)H(a,f[b]);a.iInitDisplayStart=d;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();y(a);x(a)}E(a,false);$(a,c)},a)):a.oFeatures.bServerSide||(E(a,!1),$(a))}}function $(a,b){a._bInitComplete=!0;A(a,"aoInitComplete","init",[a,b])}function pa(a){var b=j.defaults.oLanguage;!a.sEmptyTable&&(a.sZeroRecords&&"No data available in table"===b.sEmptyTable)&&p(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&
+(a.sZeroRecords&&"Loading..."===b.sLoadingRecords)&&p(a,a,"sZeroRecords","sLoadingRecords")}function ya(a){if(a.oScroll.bInfinite)return null;var b='<select size="1" '+('name="'+a.sTableId+'_length"')+">",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c<d;c++)b+='<option value="'+i[0][c]+'">'+i[1][c]+"</option>"}else{c=0;for(d=i.length;c<d;c++)b+='<option value="'+i[c]+'">'+i[c]+"</option>"}b+="</select>";i=l.createElement("div");a.aanFeatures.l||
+(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="<label>"+a.oLanguage.sLengthMenu.replace("_MENU_",b)+"</label>";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&h("select",i[c]).val(b);a._iDisplayLength=parseInt(b,10);y(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart<
+0)a._iDisplayStart=0}if(a._iDisplayLength==-1)a._iDisplayStart=0;x(a)});h("select",i).attr("aria-controls",a.sTableId);return i}function y(a){a._iDisplayEnd=!1===a.oFeatures.bPaginate?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a,
+b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=
+0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay()&&(a._iDisplayStart+=a._iDisplayLength):a._iDisplayStart=0;else if("last"==b)if(0<=a._iDisplayLength){var d=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(d-1)*a._iDisplayLength}else a._iDisplayStart=0;else D(a,0,"Unknown paging action: "+b);h(a.oInstance).trigger("page",a);return c!=a._iDisplayStart}function Aa(a){var b=l.createElement("div");a.aanFeatures.r||(b.id=a.sTableId+
+"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function E(a,b){if(a.oFeatures.bProcessing)for(var c=a.aanFeatures.r,d=0,i=c.length;d<i;d++)c[d].style.visibility=b?"visible":"hidden";h(a.oInstance).trigger("processing",[a,b])}function Ba(a){if(""===a.oScroll.sX&&""===a.oScroll.sY)return a.nTable;var b=l.createElement("div"),c=l.createElement("div"),d=l.createElement("div"),i=l.createElement("div"),f=l.createElement("div"),
+g=l.createElement("div"),e=a.nTable.cloneNode(!1),j=a.nTable.cloneNode(!1),o=a.nTable.getElementsByTagName("thead")[0],k=0===a.nTable.getElementsByTagName("tfoot").length?null:a.nTable.getElementsByTagName("tfoot")[0],m=a.oClasses;c.appendChild(d);f.appendChild(g);i.appendChild(a.nTable);b.appendChild(c);b.appendChild(i);d.appendChild(e);e.appendChild(o);null!==k&&(b.appendChild(f),g.appendChild(j),j.appendChild(k));b.className=m.sScrollWrapper;c.className=m.sScrollHead;d.className=m.sScrollHeadInner;
+i.className=m.sScrollBody;f.className=m.sScrollFoot;g.className=m.sScrollFootInner;a.oScroll.bAutoCss&&(c.style.overflow="hidden",c.style.position="relative",f.style.overflow="hidden",i.style.overflow="auto");c.style.border="0";c.style.width="100%";f.style.border="0";d.style.width=""!==a.oScroll.sXInner?a.oScroll.sXInner:"100%";e.removeAttribute("id");e.style.marginLeft="0";a.nTable.style.marginLeft="0";null!==k&&(j.removeAttribute("id"),j.style.marginLeft="0");d=h(a.nTable).children("caption");0<
+d.length&&(d=d[0],"top"===d._captionSide?e.appendChild(d):"bottom"===d._captionSide&&k&&j.appendChild(d));""!==a.oScroll.sX&&(c.style.width=q(a.oScroll.sX),i.style.width=q(a.oScroll.sX),null!==k&&(f.style.width=q(a.oScroll.sX)),h(i).scroll(function(){c.scrollLeft=this.scrollLeft;if(k!==null)f.scrollLeft=this.scrollLeft}));""!==a.oScroll.sY&&(i.style.height=q(a.oScroll.sY));a.aoDrawCallback.push({fn:La,sName:"scrolling"});a.oScroll.bInfinite&&h(i).scroll(function(){if(!a.bDrawing&&h(this).scrollTop()!==
+0&&h(this).scrollTop()+h(this).height()>h(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()<a.fnRecordsDisplay()){qa(a,"next");y(a);x(a)}});a.nScrollHead=c;a.nScrollFoot=f;return b}function La(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],d=a.nTable.parentNode,i,f,g,e,j,o,k,m,p=[],n=[],l=null!==a.nTFoot?a.nScrollFoot.getElementsByTagName("div")[0]:null,R=null!==a.nTFoot?l.getElementsByTagName("table")[0]:null,r=a.oBrowser.bScrollOversize,s=function(a){k=
+a.style;k.paddingTop="0";k.paddingBottom="0";k.borderTopWidth="0";k.borderBottomWidth="0";k.height=0};h(a.nTable).children("thead, tfoot").remove();i=h(a.nTHead).clone()[0];a.nTable.insertBefore(i,a.nTable.childNodes[0]);g=a.nTHead.getElementsByTagName("tr");e=i.getElementsByTagName("tr");null!==a.nTFoot&&(j=h(a.nTFoot).clone()[0],a.nTable.insertBefore(j,a.nTable.childNodes[1]),o=a.nTFoot.getElementsByTagName("tr"),j=j.getElementsByTagName("tr"));""===a.oScroll.sX&&(d.style.width="100%",b.parentNode.style.width=
+"100%");var t=N(a,i);i=0;for(f=t.length;i<f;i++)m=G(a,i),t[i].style.width=a.aoColumns[m].sWidth;null!==a.nTFoot&&C(function(a){a.style.width=""},j);a.oScroll.bCollapse&&""!==a.oScroll.sY&&(d.style.height=d.offsetHeight+a.nTHead.offsetHeight+"px");i=h(a.nTable).outerWidth();if(""===a.oScroll.sX){if(a.nTable.style.width="100%",r&&(h("tbody",d).height()>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=
+q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()<h(a.nTable).height()?(a.nTable.style.width=q(i-a.oScroll.iBarWidth),h(a.nTable).outerWidth()>i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML=
+"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()<i){g=d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):
+""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth>
+d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeight<d.offsetHeight&&(d.style.height=q(a.nTable.offsetHeight+r)));r=h(a.nTable).outerWidth();c.style.width=q(r);b.style.width=q(r);c=h(a.nTable).height()>d.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d=
+0,i=0,f=b.length,g,e;i<f;){g=b[i].firstChild;for(e=c?c[i].firstChild:null;g;)1===g.nodeType&&(c?a(g,e,d):a(g,d),d++),g=g.nextSibling,e=c?e.nextSibling:null;i++}}function Ma(a,b){if(!a||null===a||""===a)return 0;b||(b=l.body);var c,d=l.createElement("div");d.style.width=q(a);b.appendChild(d);c=d.offsetWidth;b.removeChild(d);return c}function da(a){var b=0,c,d=0,i=a.aoColumns.length,f,e,j=h("th",a.nTHead),o=a.nTable.getAttribute("width");e=a.nTable.parentNode;for(f=0;f<i;f++)a.aoColumns[f].bVisible&&
+(d++,null!==a.aoColumns[f].sWidth&&(c=Ma(a.aoColumns[f].sWidthOrig,e),null!==c&&(a.aoColumns[f].sWidth=q(c)),b++));if(i==j.length&&0===b&&d==i&&""===a.oScroll.sX&&""===a.oScroll.sY)for(f=0;f<a.aoColumns.length;f++)c=h(j[f]).width(),null!==c&&(a.aoColumns[f].sWidth=q(c));else{b=a.nTable.cloneNode(!1);f=a.nTHead.cloneNode(!0);d=l.createElement("tbody");c=l.createElement("tr");b.removeAttribute("id");b.appendChild(f);null!==a.nTFoot&&(b.appendChild(a.nTFoot.cloneNode(!0)),C(function(a){a.style.width=
+""},b.getElementsByTagName("tr")));b.appendChild(d);d.appendChild(c);d=h("thead th",b);0===d.length&&(d=h("tbody tr:eq(0)>td",b));j=N(a,f);for(f=d=0;f<i;f++){var k=a.aoColumns[f];k.bVisible&&null!==k.sWidthOrig&&""!==k.sWidthOrig?j[f-d].style.width=q(k.sWidthOrig):k.bVisible?j[f-d].style.width="":d++}for(f=0;f<i;f++)a.aoColumns[f].bVisible&&(d=Na(a,f),null!==d&&(d=d.cloneNode(!0),""!==a.aoColumns[f].sContentPadding&&(d.innerHTML+=a.aoColumns[f].sContentPadding),c.appendChild(d)));e.appendChild(b);
+""!==a.oScroll.sX&&""!==a.oScroll.sXInner?b.style.width=q(a.oScroll.sXInner):""!==a.oScroll.sX?(b.style.width="",h(b).width()<e.offsetWidth&&(b.style.width=q(e.offsetWidth))):""!==a.oScroll.sY?b.style.width=q(e.offsetWidth):o&&(b.style.width=q(o));b.style.visibility="hidden";Oa(a,b);i=h("tbody tr:eq(0)",b).children();0===i.length&&(i=N(a,h("thead",b)[0]));if(""!==a.oScroll.sX){for(f=d=e=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=null===a.aoColumns[f].sWidthOrig?e+h(i[d]).outerWidth():
+e+(parseInt(a.aoColumns[f].sWidth.replace("px",""),10)+(h(i[d]).outerWidth()-h(i[d]).width())),d++);b.style.width=q(e);a.nTable.style.width=q(e)}for(f=d=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=h(i[d]).width(),null!==e&&0<e&&(a.aoColumns[f].sWidth=q(e)),d++);i=h(b).css("width");a.nTable.style.width=-1!==i.indexOf("%")?i:q(h(b).outerWidth());b.parentNode.removeChild(b)}o&&(a.nTable.style.width=q(o))}function Oa(a,b){""===a.oScroll.sX&&""!==a.oScroll.sY?(h(b).width(),b.style.width=q(h(b).outerWidth()-
+a.oScroll.iBarWidth)):""!==a.oScroll.sX&&(b.style.width=q(h(b).outerWidth()))}function Na(a,b){var c=Pa(a,b);if(0>c)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i<a.aoData.length;i++){var e=v(a,i,b,"display")+"",e=e.replace(/<.*?>/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);
+return 48>b||57<b?a:a+"px"}function Qa(){var a=l.createElement("p"),b=a.style;b.width="100%";b.height="200px";b.padding="0px";var c=l.createElement("div"),b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.padding="0px";b.overflow="hidden";c.appendChild(a);l.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;b==a&&(a=c.clientWidth);l.body.removeChild(c);return b-a}function O(a,b){var c,d,i,e,g,k,o=[],m=[],p=
+j.ext.oSort,l=a.aoData,q=a.aoColumns,G=a.oLanguage.oAria;if(!a.oFeatures.bServerSide&&(0!==a.aaSorting.length||null!==a.aaSortingFixed)){o=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(c=0;c<o.length;c++)if(d=o[c][0],i=R(a,d),e=a.aoColumns[d].sSortDataType,j.ext.afnSortData[e])if(g=j.ext.afnSortData[e].call(a.oInstance,a,d,i),g.length===l.length){i=0;for(e=l.length;i<e;i++)F(a,i,d,g[i])}else D(a,0,"Returned data sort array (col "+d+") is the wrong length");c=
+0;for(d=a.aiDisplayMaster.length;c<d;c++)m[a.aiDisplayMaster[c]]=c;var r=o.length,s;c=0;for(d=l.length;c<d;c++)for(i=0;i<r;i++){s=q[o[i][0]].aDataSort;g=0;for(k=s.length;g<k;g++)e=q[s[g]].sType,e=p[(e?e:"string")+"-pre"],l[c]._aSortData[s[g]]=e?e(v(a,c,s[g],"sort")):v(a,c,s[g],"sort")}a.aiDisplayMaster.sort(function(a,b){var c,d,e,i,f;for(c=0;c<r;c++){f=q[o[c][0]].aDataSort;d=0;for(e=f.length;d<e;d++)if(i=q[f[d]].sType,i=p[(i?i:"string")+"-"+o[c][1]](l[a]._aSortData[f[d]],l[b]._aSortData[f[d]]),0!==
+i)return i}return p["numeric-asc"](m[a],m[b])})}(b===n||b)&&!a.oFeatures.bDeferRender&&P(a);c=0;for(d=a.aoColumns.length;c<d;c++)e=q[c].sTitle.replace(/<.*?>/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0<o.length&&o[0][0]==c?(i.setAttribute("aria-sort","asc"==o[0][1]?"ascending":"descending"),i.setAttribute("aria-label",e+("asc"==(q[c].asSorting[o[0][2]+1]?q[c].asSorting[o[0][2]+1]:q[c].asSorting[0])?G.sSortAscending:G.sSortDescending))):i.setAttribute("aria-label",
+e+("asc"==q[c].asSorting[0]?G.sSortAscending:G.sSortDescending)):i.setAttribute("aria-label",e);a.bSorted=!0;h(a.oInstance).trigger("sort",a);a.oFeatures.bFilter?K(a,a.oPreviousSearch,1):(a.aiDisplay=a.aiDisplayMaster.slice(),a._iDisplayStart=0,y(a),x(a))}function ia(a,b,c,d){Ra(b,{},function(b){if(!1!==a.aoColumns[c].bSortable){var e=function(){var d,e;if(b.shiftKey){for(var f=!1,h=0;h<a.aaSorting.length;h++)if(a.aaSorting[h][0]==c){f=!0;d=a.aaSorting[h][0];e=a.aaSorting[h][2]+1;a.aoColumns[d].asSorting[e]?
+(a.aaSorting[h][1]=a.aoColumns[d].asSorting[e],a.aaSorting[h][2]=e):a.aaSorting.splice(h,1);break}!1===f&&a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}else 1==a.aaSorting.length&&a.aaSorting[0][0]==c?(d=a.aaSorting[0][0],e=a.aaSorting[0][2]+1,a.aoColumns[d].asSorting[e]||(e=0),a.aaSorting[0][1]=a.aoColumns[d].asSorting[e],a.aaSorting[0][2]=e):(a.aaSorting.splice(0,a.aaSorting.length),a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0]));O(a)};a.oFeatures.bProcessing?(E(a,!0),setTimeout(function(){e();
+a.oFeatures.bServerSide||E(a,!1)},0)):e();"function"==typeof d&&d(a)}})}function P(a){var b,c,d,e,f,g=a.aoColumns.length,j=a.oClasses;for(b=0;b<g;b++)a.aoColumns[b].bSortable&&h(a.aoColumns[b].nTh).removeClass(j.sSortAsc+" "+j.sSortDesc+" "+a.aoColumns[b].sSortingClass);c=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){f=a.aoColumns[b].sSortingClass;e=-1;for(d=0;d<c.length;d++)if(c[d][0]==b){f="asc"==c[d][1]?
+j.sSortAsc:j.sSortDesc;e=d;break}h(a.aoColumns[b].nTh).addClass(f);a.bJUI&&(f=h("span."+j.sSortIcon,a.aoColumns[b].nTh),f.removeClass(j.sSortJUIAsc+" "+j.sSortJUIDesc+" "+j.sSortJUI+" "+j.sSortJUIAscAllowed+" "+j.sSortJUIDescAllowed),f.addClass(-1==e?a.aoColumns[b].sSortingClassJUI:"asc"==c[e][1]?j.sSortJUIAsc:j.sSortJUIDesc))}else h(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);f=j.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){a=J(a);e=[];for(b=0;b<g;b++)e.push("");b=0;
+for(d=1;b<c.length;b++)j=parseInt(c[b][0],10),e[j]=f+d,3>d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b<c;b++)j=b%g,d=a[b].className,o=e[j],j=d.replace(f,o),j!=d?a[b].className=h.trim(j):0<o.length&&-1==d.indexOf(o)&&(a[b].className=d+" "+o)}}function ra(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b,c;b=a.oScroll.bInfinite;var d={iCreate:(new Date).getTime(),iStart:b?0:a._iDisplayStart,iEnd:b?a._iDisplayLength:a._iDisplayEnd,iLength:a._iDisplayLength,aaSorting:h.extend(!0,[],a.aaSorting),
+oSearch:h.extend(!0,{},a.oPreviousSearch),aoSearchCols:h.extend(!0,[],a.aoPreSearchCols),abVisCols:[]};b=0;for(c=a.aoColumns.length;b<c;b++)d.abVisCols.push(a.aoColumns[b].bVisible);A(a,"aoStateSaveParams","stateSaveParams",[a,d]);a.fnStateSave.call(a.oInstance,a,d)}}function Sa(a,b){if(a.oFeatures.bStateSave){var c=a.fnStateLoad.call(a.oInstance,a);if(c){var d=A(a,"aoStateLoadParams","stateLoadParams",[a,c]);if(-1===h.inArray(!1,d)){a.oLoadedState=h.extend(!0,{},c);a._iDisplayStart=c.iStart;a.iInitDisplayStart=
+c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();h.extend(a.oPreviousSearch,c.oSearch);h.extend(!0,a.aoPreSearchCols,c.aoSearchCols);b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++)b.saved_aoColumns[d]={},b.saved_aoColumns[d].bVisible=c.abVisCols[d];A(a,"aoStateLoaded","stateLoaded",[a,c])}}}}function s(a){for(var b=0;b<j.settings.length;b++)if(j.settings[b].nTable===a)return j.settings[b];return null}function T(a){for(var b=
+[],a=a.aoData,c=0,d=a.length;c<d;c++)null!==a[c].nTr&&b.push(a[c].nTr);return b}function J(a,b){var c=[],d,e,f,g,h,j;e=0;var o=a.aoData.length;b!==n&&(e=b,o=b+1);for(f=e;f<o;f++)if(j=a.aoData[f],null!==j.nTr){e=[];for(d=j.nTr.firstChild;d;)g=d.nodeName.toLowerCase(),("td"==g||"th"==g)&&e.push(d),d=d.nextSibling;g=d=0;for(h=a.aoColumns.length;g<h;g++)a.aoColumns[g].bVisible?c.push(e[g-d]):(c.push(j._anHidden[g]),d++)}return c}function D(a,b,c){a=null===a?"DataTables warning: "+c:"DataTables warning (table id = '"+
+a.sTableId+"'): "+c;if(0===b)if("alert"==j.ext.sErrMode)alert(a);else throw Error(a);else X.console&&console.log&&console.log(a)}function p(a,b,c,d){d===n&&(d=c);b[c]!==n&&(a[d]=b[c])}function Ta(a,b){var c,d;for(d in b)b.hasOwnProperty(d)&&(c=b[d],"object"===typeof e[d]&&null!==c&&!1===h.isArray(c)?h.extend(!0,a[d],c):a[d]=c);return a}function Ra(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&c(a)}).bind("selectstart.DT",function(){return!1})}
+function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function A(a,b,c,d){for(var b=a[b],e=[],f=b.length-1;0<=f;f--)e.push(b[f].fn.apply(a.oInstance,d));null!==c&&h(a.oInstance).trigger(c,d);return e}function Ua(a){var b=h('<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden"><div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;"><div id="DT_BrowserTest" style="width:100%; height:10px;"></div></div></div>')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize=
+100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f?
+"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("current"==b.order&&"none"==b.filter){c=0;for(d=k.length;c<d;c++)(f=g[k[c]].nTr)&&e.push(f)}else if("current"==b.order&&"applied"==b.filter){c=0;for(d=o.length;c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("original"==
+b.order&&"none"==b.filter){c=0;for(d=g.length;c<d;c++)(f=g[c].nTr)&&e.push(f)}else if("original"==b.order&&"applied"==b.filter){c=0;for(d=g.length;c<d;c++)f=g[c].nTr,-1!==h.inArray(c,o)&&f&&e.push(f)}else D(d,1,"Unknown selection options");e=h(e);c=e.filter(a);e=e.find(a);return h([].concat(h.makeArray(c),h.makeArray(e)))};this._=function(a,b){var c=[],d,e,f=this.$(a,b);d=0;for(e=f.length;d<e;d++)c.push(this.fnGetData(f[d]));return c};this.fnAddData=function(a,b){if(0===a.length)return[];var c=[],
+d,e=s(this[j.ext.iApiIndex]);if("object"===typeof a[0]&&null!==a[0])for(var f=0;f<a.length;f++){d=H(e,a[f]);if(-1==d)return c;c.push(d)}else{d=H(e,a);if(-1==d)return c;c.push(d)}e.aiDisplay=e.aiDisplayMaster.slice();(b===n||b)&&aa(e);return c};this.fnAdjustColumnSizing=function(a){var b=s(this[j.ext.iApiIndex]);k(b);a===n||a?this.fnDraw(!1):(""!==b.oScroll.sX||""!==b.oScroll.sY)&&this.oApi._fnScrollDraw(b)};this.fnClearTable=function(a){var b=s(this[j.ext.iApiIndex]);ga(b);(a===n||a)&&x(b)};this.fnClose=
+function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr),b.aoOpenRows.splice(c,1),0;return 1};this.fnDeleteRow=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,a="object"===typeof a?I(d,a):a,g=d.aoData.splice(a,1);e=0;for(f=d.aoData.length;e<f;e++)null!==d.aoData[e].nTr&&(d.aoData[e].nTr._DT_RowIndex=e);e=h.inArray(a,d.aiDisplay);d.asDataSearch.splice(e,1);ha(d.aiDisplayMaster,
+a);ha(d.aiDisplay,a);"function"===typeof b&&b.call(this,d,g);d._iDisplayStart>=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;i<f;i++)!1===b.aoColumns[i].bVisible&&this.fnSetColumnVis(i,!0)}h(b.nTableWrapper).find("*").andSelf().unbind(".DT");
+h("tbody>tr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc,
+b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i<f;i++)null!==b.aoData[i].nTr&&d.appendChild(b.aoData[i].nTr);!0===b.oFeatures.bAutoWidth&&
+(b.nTable.style.width=q(b.sDestroyWidth));if(f=b.asDestroyStripes.length){a=h(d).children("tr");for(i=0;i<f;i++)a.filter(":nth-child("+f+"n + "+i+")").addClass(b.asDestroyStripes[i])}i=0;for(f=j.settings.length;i<f;i++)j.settings[i]==b&&j.settings.splice(i,1);e=b=null};this.fnDraw=function(a){var b=s(this[j.ext.iApiIndex]);!1===a?(y(b),x(b)):aa(b)};this.fnFilter=function(a,b,c,d,e,f){var g=s(this[j.ext.iApiIndex]);if(g.oFeatures.bFilter){if(c===n||null===c)c=!1;if(d===n||null===d)d=!0;if(e===n||null===
+e)e=!0;if(f===n||null===f)f=!0;if(b===n||null===b){if(K(g,{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f},1),e&&g.aanFeatures.f){b=g.aanFeatures.f;c=0;for(d=b.length;c<d;c++)try{b[c]._DT_Input!=l.activeElement&&h(b[c]._DT_Input).val(a)}catch(o){h(b[c]._DT_Input).val(a)}}}else h.extend(g.aoPreSearchCols[b],{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f}),K(g,g.oPreviousSearch,1)}};this.fnGetData=function(a,b){var c=s(this[j.ext.iApiIndex]);if(a!==n){var d=a;if("object"===typeof a){var e=a.nodeName.toLowerCase();
+"tr"===e?d=I(c,a):"td"===e&&(d=I(c,a.parentNode),b=fa(c,d,a))}return b!==n?v(c,d,b,""):c.aoData[d]!==n?c.aoData[d]._aData:null}return Z(c)};this.fnGetNodes=function(a){var b=s(this[j.ext.iApiIndex]);return a!==n?b.aoData[a]!==n?b.aoData[a].nTr:null:T(b)};this.fnGetPosition=function(a){var b=s(this[j.ext.iApiIndex]),c=a.nodeName.toUpperCase();return"TR"==c?I(b,a):"TD"==c||"TH"==c?(c=I(b,a.parentNode),a=fa(b,c,a),[c,R(b,a),a]):null};this.fnIsOpen=function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<
+b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return!0;return!1};this.fnOpen=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e=T(d);if(-1!==h.inArray(a,e)){this.fnClose(a);var e=l.createElement("tr"),f=l.createElement("td");e.appendChild(f);f.className=c;f.colSpan=t(d);"string"===typeof b?f.innerHTML=b:h(f).html(b);b=h("tr",d.nTBody);-1!=h.inArray(a,b)&&h(e).insertAfter(a);d.aoOpenRows.push({nTr:e,nParent:a});return e}};this.fnPageChange=function(a,b){var c=s(this[j.ext.iApiIndex]);qa(c,a);
+y(c);(b===n||b)&&x(c)};this.fnSetColumnVis=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,g=d.aoColumns,h=d.aoData,o,m;if(g[a].bVisible!=b){if(b){for(e=f=0;e<a;e++)g[e].bVisible&&f++;m=f>=t(d);if(!m)for(e=a;e<g.length;e++)if(g[e].bVisible){o=e;break}e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(m?h[e].nTr.appendChild(h[e]._anHidden[a]):h[e].nTr.insertBefore(h[e]._anHidden[a],J(d,e)[o]))}else{e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(o=J(d,e)[a],h[e]._anHidden[a]=o,o.parentNode.removeChild(o))}g[a].bVisible=
+b;W(d,d.aoHeader);d.nTFoot&&W(d,d.aoFooter);e=0;for(f=d.aoOpenRows.length;e<f;e++)d.aoOpenRows[e].nTr.colSpan=t(d);if(c===n||c)k(d),x(d);ra(d)}};this.fnSettings=function(){return s(this[j.ext.iApiIndex])};this.fnSort=function(a){var b=s(this[j.ext.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){ia(s(this[j.ext.iApiIndex]),a,b,c)};this.fnUpdate=function(a,b,c,d,e){var f=s(this[j.ext.iApiIndex]),b="object"===typeof b?I(f,b):b;if(h.isArray(a)&&c===n){f.aoData[b]._aData=a.slice();
+for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else if(h.isPlainObject(a)&&c===n){f.aoData[b]._aData=h.extend(!0,{},a);for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else{F(f,b,c,a);var a=v(f,b,c,"display"),g=f.aoColumns[c];null!==g.fnRender&&(a=S(f,b,c),g.bUseRendered&&F(f,b,c,a));null!==f.aoData[b].nTr&&(J(f,b)[c].innerHTML=a)}c=h.inArray(b,f.aiDisplay);f.asDataSearch[c]=na(f,Y(f,b,"filter",r(f,"bSearchable")));(e===n||e)&&k(f);(d===n||d)&&aa(f);return 0};
+this.fnVersionCheck=j.ext.fnVersionCheck;this.oApi={_fnExternApiFunc:Va,_fnInitialise:ba,_fnInitComplete:$,_fnLanguageCompat:pa,_fnAddColumn:o,_fnColumnOptions:m,_fnAddData:H,_fnCreateTr:ea,_fnGatherData:ua,_fnBuildHead:va,_fnDrawHead:W,_fnDraw:x,_fnReDraw:aa,_fnAjaxUpdate:wa,_fnAjaxParameters:Ea,_fnAjaxUpdateDraw:Fa,_fnServerParams:ka,_fnAddOptionsHtml:xa,_fnFeatureHtmlTable:Ba,_fnScrollDraw:La,_fnAdjustColumnSizing:k,_fnFeatureHtmlFilter:za,_fnFilterComplete:K,_fnFilterCustom:Ia,_fnFilterColumn:Ha,
+_fnFilter:Ga,_fnBuildSearchArray:la,_fnBuildSearchRow:na,_fnFilterCreateSearch:ma,_fnDataToSearch:Ja,_fnSort:O,_fnSortAttachListener:ia,_fnSortingClasses:P,_fnFeatureHtmlPaginate:Da,_fnPageChange:qa,_fnFeatureHtmlInfo:Ca,_fnUpdateInfo:Ka,_fnFeatureHtmlLength:ya,_fnFeatureHtmlProcessing:Aa,_fnProcessingDisplay:E,_fnVisibleToColumnIndex:G,_fnColumnIndexToVisible:R,_fnNodeToDataIndex:I,_fnVisbleColumns:t,_fnCalculateEnd:y,_fnConvertToWidth:Ma,_fnCalculateColumnWidths:da,_fnScrollingWidthAdjust:Oa,_fnGetWidestNode:Na,
+_fnGetMaxLenString:Pa,_fnStringToCss:q,_fnDetectType:B,_fnSettingsFromNode:s,_fnGetDataMaster:Z,_fnGetTrNodes:T,_fnGetTdNodes:J,_fnEscapeRegex:oa,_fnDeleteIndex:ha,_fnReOrderIndex:u,_fnColumnOrdering:M,_fnLog:D,_fnClearTable:ga,_fnSaveState:ra,_fnLoadState:Sa,_fnCreateCookie:function(a,b,c,d,e){var f=new Date;f.setTime(f.getTime()+1E3*c);var c=X.location.pathname.split("/"),a=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase(),g;null!==e?(g="function"===typeof h.parseJSON?h.parseJSON(b):eval("("+b+")"),
+b=e(a,g,f.toGMTString(),c.join("/")+"/")):b=a+"="+encodeURIComponent(b)+"; expires="+f.toGMTString()+"; path="+c.join("/")+"/";a=l.cookie.split(";");e=b.split(";")[0].length;f=[];if(4096<e+l.cookie.length+10){for(var j=0,o=a.length;j<o;j++)if(-1!=a[j].indexOf(d)){var k=a[j].split("=");try{(g=eval("("+decodeURIComponent(k[1])+")"))&&g.iCreate&&f.push({name:k[0],time:g.iCreate})}catch(m){}}for(f.sort(function(a,b){return b.time-a.time});4096<e+l.cookie.length+10;){if(0===f.length)return;d=f.pop();l.cookie=
+d.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}}l.cookie=b},_fnReadCookie:function(a){for(var b=X.location.pathname.split("/"),a=a+"_"+b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=",b=l.cookie.split(";"),c=0;c<b.length;c++){for(var d=b[c];" "==d.charAt(0);)d=d.substring(1,d.length);if(0===d.indexOf(a))return decodeURIComponent(d.substring(a.length,d.length))}return null},_fnDetectHeader:V,_fnGetUniqueThs:N,_fnScrollBarWidth:Qa,_fnApplyToChildren:C,_fnMap:p,_fnGetRowData:Y,
+_fnGetCellData:v,_fnSetCellData:F,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:L,_fnApplyColumnDefs:ta,_fnBindAction:Ra,_fnExtend:Ta,_fnCallbackReg:z,_fnCallbackFire:A,_fnJsonString:Wa,_fnRender:S,_fnNodeToColumnIndex:fa,_fnInfoMacros:ja,_fnBrowserDetect:Ua,_fnGetColumns:r};h.extend(j.ext.oApi,this.oApi);for(var sa in j.ext.oApi)sa&&(this[sa]=Va(sa));var ca=this;this.each(function(){var a=0,b,c,d;c=this.getAttribute("id");var i=!1,f=!1;if("table"!=this.nodeName.toLowerCase())D(null,0,"Attempted to initialise DataTables on a node which is not a table: "+
+this.nodeName);else{a=0;for(b=j.settings.length;a<b;a++){if(j.settings[a].nTable==this){if(e===n||e.bRetrieve)return j.settings[a].oInstance;if(e.bDestroy){j.settings[a].oInstance.fnDestroy();break}else{D(j.settings[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, pass no arguments or see the docs for bRetrieve and bDestroy");return}}if(j.settings[a].sTableId==this.id){j.settings.splice(a,1);break}}if(null===c||""===c)this.id=c="DataTables_Table_"+j.ext._oExternConfig.iNextUnique++;
+var g=h.extend(!0,{},j.models.oSettings,{nTable:this,oApi:ca.oApi,oInit:e,sDestroyWidth:h(this).width(),sInstance:c,sTableId:c});j.settings.push(g);g.oInstance=1===ca.length?ca:h(this).dataTable();e||(e={});e.oLanguage&&pa(e.oLanguage);e=Ta(h.extend(!0,{},j.defaults),e);p(g.oFeatures,e,"bPaginate");p(g.oFeatures,e,"bLengthChange");p(g.oFeatures,e,"bFilter");p(g.oFeatures,e,"bSort");p(g.oFeatures,e,"bInfo");p(g.oFeatures,e,"bProcessing");p(g.oFeatures,e,"bAutoWidth");p(g.oFeatures,e,"bSortClasses");
+p(g.oFeatures,e,"bServerSide");p(g.oFeatures,e,"bDeferRender");p(g.oScroll,e,"sScrollX","sX");p(g.oScroll,e,"sScrollXInner","sXInner");p(g.oScroll,e,"sScrollY","sY");p(g.oScroll,e,"bScrollCollapse","bCollapse");p(g.oScroll,e,"bScrollInfinite","bInfinite");p(g.oScroll,e,"iScrollLoadGap","iLoadGap");p(g.oScroll,e,"bScrollAutoCss","bAutoCss");p(g,e,"asStripeClasses");p(g,e,"asStripClasses","asStripeClasses");p(g,e,"fnServerData");p(g,e,"fnFormatNumber");p(g,e,"sServerMethod");p(g,e,"aaSorting");p(g,
+e,"aaSortingFixed");p(g,e,"aLengthMenu");p(g,e,"sPaginationType");p(g,e,"sAjaxSource");p(g,e,"sAjaxDataProp");p(g,e,"iCookieDuration");p(g,e,"sCookiePrefix");p(g,e,"sDom");p(g,e,"bSortCellsTop");p(g,e,"iTabIndex");p(g,e,"oSearch","oPreviousSearch");p(g,e,"aoSearchCols","aoPreSearchCols");p(g,e,"iDisplayLength","_iDisplayLength");p(g,e,"bJQueryUI","bJUI");p(g,e,"fnCookieCallback");p(g,e,"fnStateLoad");p(g,e,"fnStateSave");p(g.oLanguage,e,"fnInfoCallback");z(g,"aoDrawCallback",e.fnDrawCallback,"user");
+z(g,"aoServerParams",e.fnServerParams,"user");z(g,"aoStateSaveParams",e.fnStateSaveParams,"user");z(g,"aoStateLoadParams",e.fnStateLoadParams,"user");z(g,"aoStateLoaded",e.fnStateLoaded,"user");z(g,"aoRowCallback",e.fnRowCallback,"user");z(g,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(g,"aoHeaderCallback",e.fnHeaderCallback,"user");z(g,"aoFooterCallback",e.fnFooterCallback,"user");z(g,"aoInitComplete",e.fnInitComplete,"user");z(g,"aoPreDrawCallback",e.fnPreDrawCallback,"user");g.oFeatures.bServerSide&&
+g.oFeatures.bSort&&g.oFeatures.bSortClasses?z(g,"aoDrawCallback",P,"server_side_sort_classes"):g.oFeatures.bDeferRender&&z(g,"aoDrawCallback",P,"defer_sort_classes");e.bJQueryUI?(h.extend(g.oClasses,j.ext.oJUIClasses),e.sDom===j.defaults.sDom&&"lfrtip"===j.defaults.sDom&&(g.sDom='<"H"lfr>t<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart,
+g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0,
+g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a<b;a++)d.hasClass(g.asStripeClasses[a])&&(c=!0,g.asDestroyStripes.push(g.asStripeClasses[a]));c&&d.removeClass(g.asStripeClasses.join(" "))}c=[];a=this.getElementsByTagName("thead");0!==a.length&&(V(g.aoHeader,a[0]),c=N(g));if(null===e.aoColumns){d=[];a=0;for(b=
+c.length;a<b;a++)d.push(null)}else d=e.aoColumns;a=0;for(b=d.length;a<b;a++)e.saved_aoColumns!==n&&e.saved_aoColumns.length==b&&(null===d[a]&&(d[a]={}),d[a].bVisible=e.saved_aoColumns[a].bVisible),o(g,c?c[a]:null);ta(g,e.aoColumnDefs,d,function(a,b){m(g,a,b)});a=0;for(b=g.aaSorting.length;a<b;a++){g.aaSorting[a][0]>=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]=
+k.asSorting[0]);c=0;for(d=k.asSorting.length;c<d;c++)if(g.aaSorting[a][1]==k.asSorting[c]){g.aaSorting[a][2]=c;break}}P(g);Ua(g);a=h(this).children("caption").each(function(){this._captionSide=h(this).css("caption-side")});b=h(this).children("thead");0===b.length&&(b=[l.createElement("thead")],this.appendChild(b[0]));g.nTHead=b[0];b=h(this).children("tbody");0===b.length&&(b=[l.createElement("tbody")],this.appendChild(b[0]));g.nTBody=b[0];g.nTBody.setAttribute("role","alert");g.nTBody.setAttribute("aria-live",
+"polite");g.nTBody.setAttribute("aria-relevant","all");b=h(this).children("tfoot");if(0===b.length&&0<a.length&&(""!==g.oScroll.sX||""!==g.oScroll.sY))b=[l.createElement("tfoot")],this.appendChild(b[0]);0<b.length&&(g.nTFoot=b[0],V(g.aoFooter,g.nTFoot));if(f)for(a=0;a<e.aaData.length;a++)H(g,e.aaData[a]);else ua(g);g.aiDisplay=g.aiDisplayMaster.slice();g.bInitialised=!0;!1===i&&ba(g)}});ca=null;return this};j.fnVersionCheck=function(e){for(var h=function(e,h){for(;e.length<h;)e+="0";return e},m=j.ext.sVersion.split("."),
+e=e.split("."),k="",n="",l=0,t=e.length;l<t;l++)k+=h(m[l],3),n+=h(e[l],3);return parseInt(k,10)>=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;m<h.length;m++)if(h[m].nTable===e||h[m].nScrollHead===e||h[m].nScrollFoot===e)return!0;return!1};j.fnTables=function(e){var o=[];jQuery.each(j.settings,function(j,k){(!e||!0===e&&h(k.nTable).is(":visible"))&&o.push(k.nTable)});return o};j.version="1.9.4";j.settings=[];j.models={};j.models.ext={afnFiltering:[],afnSortData:[],aoFeatures:[],
+aTypes:[],fnVersionCheck:j.fnVersionCheck,iApiIndex:0,ofnSearch:{},oApi:{},oStdClasses:{},oJUIClasses:{},oPagination:{},oSort:{},sVersion:j.version,sErrMode:"alert",_oExternConfig:{iNextUnique:0}};j.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};j.models.oRow={nTr:null,_aData:[],_aSortData:[],_anHidden:[],_sRowStripe:""};j.models.oColumn={aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bUseRendered:null,bVisible:null,_bAutoType:!0,fnCreatedCell:null,fnGetData:null,
+fnRender:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};j.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,
+bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollAutoCss:!0,bScrollCollapse:!1,bScrollInfinite:!1,bServerSide:!1,bSort:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCookieCallback:null,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(e){if(1E3>e)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k<h;k++)0===k%3&&0!==k&&(j=this.oLanguage.sInfoThousands+j),j=e[h-k-1]+j;return j},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,
+fnRowCallback:null,fnServerData:function(e,j,m,k){k.jqXHR=h.ajax({url:e,data:j,success:function(e){e.sError&&k.oApi._fnLog(k,0,e.sError);h(k.oInstance).trigger("xhr",[k,e]);m(e)},dataType:"json",cache:!1,type:k.sServerMethod,error:function(e,h){"parsererror"==h&&k.oApi._fnLog(k,0,"DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})},fnServerParams:null,fnStateLoad:function(e){var e=this.oApi._fnReadCookie(e.sCookiePrefix+e.sInstance),j;try{j=
+"function"===typeof h.parseJSON?h.parseJSON(e):eval("("+e+")")}catch(m){j=null}return j},fnStateLoadParams:null,fnStateLoaded:null,fnStateSave:function(e,h){this.oApi._fnCreateCookie(e.sCookiePrefix+e.sInstance,this.oApi._fnJsonString(h),e.iCookieDuration,e.sCookiePrefix,e.fnCookieCallback)},fnStateSaveParams:null,iCookieDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iScrollLoadGap:100,iTabIndex:0,oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},
+oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sInfoThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},j.models.oSearch),sAjaxDataProp:"aaData",
+sAjaxSource:null,sCookiePrefix:"SpryMedia_DataTables_",sDom:"lfrtip",sPaginationType:"two_button",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET"};j.defaults.columns={aDataSort:null,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bUseRendered:!0,bVisible:!0,fnCreatedCell:null,fnRender:null,iDataSort:-1,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};j.models.oSettings={oFeatures:{bAutoWidth:null,
+bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortClasses:null,bStateSave:null},oScroll:{bAutoCss:null,bCollapse:null,bInfinite:null,iBarWidth:0,iLoadGap:null,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1},aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],asDataSearch:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:null,
+asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iCookieDuration:0,sCookiePrefix:"",fnCookieCallback:null,aoStateSave:[],aoStateLoad:[],
+oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iDisplayEnd:10,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsTotal,10):this.aiDisplayMaster.length},
+fnRecordsDisplay:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsDisplay,10):this.aiDisplay.length},fnDisplayEnd:function(){return this.oFeatures.bServerSide?!1===this.oFeatures.bPaginate||-1==this._iDisplayLength?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iRecordsDisplay):this._iDisplayEnd},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null};j.ext=h.extend(!0,{},j.models.ext);h.extend(j.ext.oStdClasses,
+{sTable:"dataTable",sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",sPageButtonStaticDisabled:"paginate_button paginate_button_disabled",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",
+sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
+sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"",sJUIHeader:"",sJUIFooter:""});h.extend(j.ext.oJUIClasses,j.ext.oStdClasses,{sPagePrevEnabled:"fg-button ui-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",sPageNextEnabled:"fg-button ui-button ui-state-default ui-corner-right",
+sPageNextDisabled:"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-button ui-state-default",sPageButtonActive:"fg-button ui-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPageLast:"last ui-corner-tr ui-corner-br",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",
+sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",
+sScrollHead:"dataTables_scrollHead ui-state-default",sScrollFoot:"dataTables_scrollFoot ui-state-default",sFooterTH:"ui-state-default",sJUIHeader:"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",sJUIFooter:"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"});h.extend(j.ext.oPagination,{two_button:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)},k=!e.bJUI?'<a class="'+
+e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sPrevious+'</a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sNext+"</a>":'<a class="'+e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUIPrev+'"></span></a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUINext+'"></span></a>';h(j).append(k);var l=h("a",j),
+k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l<n;l++)if(k=j[l].firstChild)k.className=0===e._iDisplayStart?h.sPagePrevDisabled:h.sPagePrevEnabled,k=k.nextSibling,
+k.className=e.fnDisplayEnd()==e.fnRecordsDisplay()?h.sPageNextDisabled:h.sPageNextEnabled}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,l=e.oClasses,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)};h(j).append('<a  tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageFirst+'">'+k.sFirst+'</a><a  tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPagePrevious+'">'+k.sPrevious+'</a><span></span><a tabindex="'+e.iTabIndex+'" class="'+
+l.sPageButton+" "+l.sPageNext+'">'+k.sNext+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageLast+'">'+k.sLast+"</a>");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")},
+fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l<m?(r=1,k=l):n<=k?(r=1,k=m):n>=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+=
+n!==m?'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButton+'">'+e.fnFormatNumber(m)+"</a>":'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButtonActive+'">'+e.fnFormatNumber(m)+"</a>";m=0;for(k=M.length;m<k;m++)u=M[m],u.hasChildNodes()&&(h("span:eq(0)",u).html(t).children("a").each(L),u=u.getElementsByTagName("a"),u=[u[0],u[1],u[u.length-2],u[u.length-1]],h(u).removeClass(B.sPageButton+" "+B.sPageButtonActive+" "+B.sPageButtonStaticDisabled),h([u[0],u[1]]).addClass(1==n?B.sPageButtonStaticDisabled:
+B.sPageButton),h([u[2],u[3]]).addClass(0===l||n===l||-1===e._iDisplayLength?B.sPageButtonStaticDisabled:B.sPageButton))}}}});h.extend(j.ext.oSort,{"string-pre":function(e){"string"!=typeof e&&(e=null!==e&&e.toString?e.toString():"");return e.toLowerCase()},"string-asc":function(e,h){return e<h?-1:e>h?1:0},"string-desc":function(e,h){return e<h?1:e>h?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return e<h?-1:e>h?1:0},"html-desc":function(e,h){return e<
+h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null;
+for(var k=1;k<e.length;k++){h=e.charAt(k);if(-1=="0123456789.".indexOf(h))return null;if("."==h){if(j)return null;j=!0}}return"numeric"},function(e){var h=Date.parse(e);return null!==h&&!isNaN(h)||"string"===typeof e&&0===e.length?"date":null},function(e){return"string"===typeof e&&-1!=e.indexOf("<")&&-1!=e.indexOf(">")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&&
+L(jQuery)})(window,document);
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.tools.min.js b/typo3/sysext/documentation/Resources/Public/JavaScript/jquery.tools.min.js
new file mode 100644 (file)
index 0000000..be5bd0c
--- /dev/null
@@ -0,0 +1,2 @@
+(function(a,b){function g(a,b){return(new Date(a,b+1,0)).getDate()}function h(a,b){a=""+a,b=b||2;while(a.length<b)a="0"+a;return a}function k(a,b,c){var d=a.getDate(),e=a.getDay(),g=a.getMonth(),k=a.getFullYear(),l={d:d,dd:h(d),ddd:f[c].shortDays[e],dddd:f[c].days[e],m:g+1,mm:h(g+1),mmm:f[c].shortMonths[g],mmmm:f[c].months[g],yy:String(k).slice(2),yyyy:k},m=b.replace(i,function(a){return a in l?l[a]:a.slice(1,a.length-1)});return j.html(m).html()}function l(a){return parseInt(a,10)}function m(a,b){return a.getFullYear()===b.getFullYear()&&a.getMonth()==b.getMonth()&&a.getDate()==b.getDate()}function n(a){if(a===b)return;if(a.constructor==Date)return a;if(typeof a=="string"){var c=a.split("-");if(c.length==3)return new Date(l(c[0]),l(c[1])-1,l(c[2]));if(!/^-?\d+$/.test(a))return;a=l(a)}var d=new Date;return d.setDate(d.getDate()+a),d}function o(d,h){function M(b,c,e){z=b,w=b.getFullYear(),x=b.getMonth(),y=b.getDate(),e=e||a.Event("api"),e.type="beforeChange",G.trigger(e,[b]);if(e.isDefaultPrevented())return;d.val(k(b,c.format,c.lang)),e.type="change",G.trigger(e),d.data("date",b),i.hide(e)}function N(b){b.type="onShow",G.trigger(b),a(document).bind("keydown.d",function(b){if(b.ctrlKey)return!0;var c=b.keyCode;if(c==8)return d.val(""),i.hide(b);if(c==27||c==9)return i.hide(b);if(a(e).index(c)>=0){if(!C)return i.show(b),b.preventDefault();var f=a("#"+p.weeks+" a"),g=a("."+p.focus),h=f.index(g);g.removeClass(p.focus);if(c==74||c==40)h+=7;else if(c==75||c==38)h-=7;else if(c==76||c==39)h+=1;else if(c==72||c==37)h-=1;return h>41?(i.addMonth(),g=a("#"+p.weeks+" a:eq("+(h-42)+")")):h<0?(i.addMonth(-1),g=a("#"+p.weeks+" a:eq("+(h+42)+")")):g=f.eq(h),g.addClass(p.focus),b.preventDefault()}return c==34?i.addMonth():c==33?i.addMonth(-1):c==36?i.today():(c==13&&(a(b.target).is("select")||a("."+p.focus).click()),a([16,17,18,9]).index(c)>=0)}),a(document).bind("click.d",function(b){var c=b.target;!a(c).parents("#"+p.root).length&&c!=d[0]&&(!t||c!=t[0])&&i.hide(b)})}var i=this,j=new Date,o=j.getFullYear(),p=h.css,q=f[h.lang],r=a("#"+p.root),s=r.find("#"+p.title),t,u,v,w,x,y,z=d.attr("data-value")||h.value||d.val(),A=d.attr("min")||h.min,B=d.attr("max")||h.max,C,D;A===0&&(A="0"),z=n(z)||j,A=n(A||new Date(o+h.yearRange[0],1,1)),B=n(B||new Date(o+h.yearRange[1]+1,1,-1));if(!q)throw"Dateinput: invalid language: "+h.lang;if(d.attr("type")=="date"){var D=d.clone(),E=D.wrap("<div/>").parent().html(),F=a(E.replace(/type/i,"type=text data-orig-type"));h.value&&F.val(h.value),d.replaceWith(F),d=F}d.addClass(p.input);var G=d.add(i);if(!r.length){r=a("<div><div><a/><div/><a/></div><div><div/><div/></div></div>").hide().css({position:"absolute"}).attr("id",p.root),r.children().eq(0).attr("id",p.head).end().eq(1).attr("id",p.body).children().eq(0).attr("id",p.days).end().eq(1).attr("id",p.weeks).end().end().end().find("a").eq(0).attr("id",p.prev).end().eq(1).attr("id",p.next),s=r.find("#"+p.head).find("div").attr("id",p.title);if(h.selectors){var H=a("<select/>").attr("id",p.month),I=a("<select/>").attr("id",p.year);s.html(H.add(I))}var J=r.find("#"+p.days);for(var K=0;K<7;K++)J.append(a("<span/>").text(q.shortDays[(K+h.firstDay)%7]));a("body").append(r)}h.trigger&&(t=a("<a/>").attr("href","#").addClass(p.trigger).click(function(a){return h.toggle?i.toggle():i.show(),a.preventDefault()}).insertAfter(d));var L=r.find("#"+p.weeks);I=r.find("#"+p.year),H=r.find("#"+p.month),a.extend(i,{show:function(b){if(d.attr("readonly")||d.attr("disabled")||C)return;b=b||a.Event(),b.type="onBeforeShow",G.trigger(b);if(b.isDefaultPrevented())return;a.each(c,function(){this.hide()}),C=!0,H.unbind("change").change(function(){i.setValue(I.val(),a(this).val())}),I.unbind("change").change(function(){i.setValue(a(this).val(),H.val())}),u=r.find("#"+p.prev).unbind("click").click(function(a){return u.hasClass(p.disabled)||i.addMonth(-1),!1}),v=r.find("#"+p.next).unbind("click").click(function(a){return v.hasClass(p.disabled)||i.addMonth(),!1}),i.setValue(z);var e=d.offset();return/iPad/i.test(navigator.userAgent)&&(e.top-=a(window).scrollTop()),r.css({top:e.top+d.outerHeight({margins:!0})+h.offset[0],left:e.left+h.offset[1]}),h.speed?r.show(h.speed,function(){N(b)}):(r.show(),N(b)),i},setValue:function(c,d,e){var f=l(d)>=-1?new Date(l(c),l(d),l(e==b||isNaN(e)?1:e)):c||z;f<A?f=A:f>B&&(f=B),typeof c=="string"&&(f=n(c)),c=f.getFullYear(),d=f.getMonth(),e=f.getDate(),d==-1?(d=11,c--):d==12&&(d=0,c++);if(!C)return M(f,h),i;x=d,w=c,y=e;var k=new Date(c,d,1-h.firstDay),o=k.getDay(),r=g(c,d),t=g(c,d-1),D;if(h.selectors){H.empty(),a.each(q.months,function(b,d){A<new Date(c,b+1,1)&&B>new Date(c,b,0)&&H.append(a("<option/>").html(d).attr("value",b))}),I.empty();var E=j.getFullYear();for(var F=E+h.yearRange[0];F<E+h.yearRange[1];F++)A<new Date(F+1,0,1)&&B>new Date(F,0,0)&&I.append(a("<option/>").text(F));H.val(d),I.val(c)}else s.html(q.months[d]+" "+c);L.empty(),u.add(v).removeClass(p.disabled);for(var G=o?0:-7,J,K;G<(o?42:35);G++)J=a("<a/>"),G%7===0&&(D=a("<div/>").addClass(p.week),L.append(D)),G<o?(J.addClass(p.off),K=t-o+G+1,f=new Date(c,d-1,K)):G>=o+r?(J.addClass(p.off),K=G-r-o+1,f=new Date(c,d+1,K)):(K=G-o+1,f=new Date(c,d,K),m(z,f)?J.attr("id",p.current).addClass(p.focus):m(j,f)&&J.attr("id",p.today)),A&&f<A&&J.add(u).addClass(p.disabled),B&&f>B&&J.add(v).addClass(p.disabled),J.attr("href","#"+K).text(K).data("date",f),D.append(J);return L.find("a").click(function(b){var c=a(this);return c.hasClass(p.disabled)||(a("#"+p.current).removeAttr("id"),c.attr("id",p.current),M(c.data("date"),h,b)),!1}),p.sunday&&L.find(p.week).each(function(){var b=h.firstDay?7-h.firstDay:0;a(this).children().slice(b,b+1).addClass(p.sunday)}),i},setMin:function(a,b){return A=n(a),b&&z<A&&i.setValue(A),i},setMax:function(a,b){return B=n(a),b&&z>B&&i.setValue(B),i},today:function(){return i.setValue(j)},addDay:function(a){return this.setValue(w,x,y+(a||1))},addMonth:function(a){var b=x+(a||1),c=g(w,b),d=y<=c?y:c;return this.setValue(w,b,d)},addYear:function(a){return this.setValue(w+(a||1),x,y)},destroy:function(){d.add(document).unbind("click.d").unbind("keydown.d"),r.add(t).remove(),d.removeData("dateinput").removeClass(p.input),D&&d.replaceWith(D)},hide:function(b){if(C){b=a.Event(),b.type="onHide",G.trigger(b),a(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;r.hide(),C=!1}return i},toggle:function(){return i.isOpen()?i.hide():i.show()},getConf:function(){return h},getInput:function(){return d},getCalendar:function(){return r},getValue:function(a){return a?k(z,a,h.lang):z},isOpen:function(){return C}}),a.each(["onBeforeShow","onShow","change","onHide"],function(b,c){a.isFunction(h[c])&&a(i).bind(c,h[c]),i[c]=function(b){return b&&a(i).bind(c,b),i}}),h.editable||d.bind("focus.d click.d",i.show).keydown(function(b){var c=b.keyCode;return!C&&a(e).index(c)>=0?(i.show(b),b.preventDefault()):b.shiftKey||b.ctrlKey||b.altKey||c==9?!0:b.preventDefault()}),n(d.val())&&M(z,h)}a.tools=a.tools||{version:"1.2.6"};var c=[],d,e=[75,76,38,39,74,72,40,37],f={};d=a.tools.dateinput={conf:{format:"mm/dd/yy",selectors:!1,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:b,max:b,trigger:0,toggle:0,editable:0,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(b,c){a.each(c,function(a,b){c[a]=b.split(",")}),f[b]=c}},d.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});var i=/d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g,j=a("<a/>");a.expr[":"].date=function(b){var c=b.getAttribute("type");return c&&c=="date"||!!a(b).data("dateinput")},a.fn.dateinput=function(b){if(this.data("dateinput"))return this;b=a.extend(!0,{},d.conf,b),a.each(b.css,function(a,c){!c&&a!="prefix"&&(b.css[a]=(b.css.prefix||"")+(c||a))});var e;return this.each(function(){var d=new o(a(this),b);c.push(d);var f=d.getInput().data("dateinput",d);e=e?e.add(f):f}),e?e:this}})(jQuery),function(a){function d(d,e){var f=this,g=d.add(f),h=a(window),i,j,k,l=a.tools.expose&&(e.mask||e.expose),m=Math.random().toString().slice(10);l&&(typeof l=="string"&&(l={color:l}),l.closeOnClick=l.closeOnEsc=!1);var n=e.target||d.attr("rel");j=n?a(n):null||d;if(!j.length)throw"Could not find Overlay: "+n;d&&d.index(j)==-1&&d.click(function(a){return f.load(a),a.preventDefault()}),a.extend(f,{load:function(d){if(f.isOpened())return f;var i=c[e.effect];if(!i)throw'Overlay: cannot find effect : "'+e.effect+'"';e.oneInstance&&a.each(b,function(){this.close(d)}),d=d||a.Event(),d.type="onBeforeLoad",g.trigger(d);if(d.isDefaultPrevented())return f;k=!0,l&&a(j).expose(l);var n=e.top,o=e.left,p=j.outerWidth({margin:!0}),q=j.outerHeight({margin:!0});return typeof n=="string"&&(n=n=="center"?Math.max((h.height()-q)/2,0):parseInt(n,10)/100*h.height()),o=="center"&&(o=Math.max((h.width()-p)/2,0)),i[0].call(f,{top:n,left:o},function(){k&&(d.type="onLoad",g.trigger(d))}),l&&e.closeOnClick&&a.mask.getMask().one("click",f.close),e.closeOnClick&&a(document).bind("click."+m,function(b){a(b.target).parents(j).length||f.close(b)}),e.closeOnEsc&&a(document).bind("keydown."+m,function(a){a.keyCode==27&&f.close(a)}),f},close:function(b){if(!f.isOpened())return f;b=b||a.Event(),b.type="onBeforeClose",g.trigger(b);if(b.isDefaultPrevented())return;return k=!1,c[e.effect][1].call(f,function(){b.type="onClose",g.trigger(b)}),a(document).unbind("click."+m).unbind("keydown."+m),l&&a.mask.close(),f},getOverlay:function(){return j},getTrigger:function(){return d},getClosers:function(){return i},isOpened:function(){return k},getConf:function(){return e}}),a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){return b&&a(f).bind(c,b),f}}),i=j.find(e.close||".close"),!i.length&&!e.close&&(i=a('<a class="close"></a>'),j.prepend(i)),i.click(function(a){f.close(a)}),e.load&&f.load()}a.tools=a.tools||{version:"1.2.6"},a.tools.overlay={addEffect:function(a,b,d){c[a]=[b,d]},conf:{close:null,closeOnClick:!0,closeOnEsc:!0,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:!1,mask:null,oneInstance:!0,speed:"normal",target:null,top:"10%"}};var b=[],c={};a.tools.overlay.addEffect("default",function(b,c){var d=this.getConf(),e=a(window);d.fixed||(b.top+=e.scrollTop(),b.left+=e.scrollLeft()),b.position=d.fixed?"fixed":"absolute",this.getOverlay().css(b).fadeIn(d.speed,c)},function(a){this.getOverlay().fadeOut(this.getConf().closeSpeed,a)}),a.fn.overlay=function(c){var e=this.data("overlay");return e?e:(a.isFunction(c)&&(c={onBeforeLoad:c}),c=a.extend(!0,{},a.tools.overlay.conf,c),this.each(function(){e=new d(a(this),c),b.push(e),a(this).data("overlay",e)}),c.api?e:this)}}(jQuery),function(a){function d(a){var b=a.offset();return{top:b.top+a.height()/2,left:b.left+a.width()/2}}var b=a.tools.overlay,c=a(window);a.extend(b.conf,{start:{top:null,left:null},fadeInSpeed:"fast",zIndex:9999});var e=function(b,e){var f=this.getOverlay(),g=this.getConf(),h=this.getTrigger(),i=this,j=f.outerWidth({margin:!0}),k=f.data("img"),l=g.fixed?"fixed":"absolute";if(!k){var m=f.css("backgroundImage");if(!m)throw"background-image CSS property not set for overlay";m=m.slice(m.indexOf("(")+1,m.indexOf(")")).replace(/\"/g,""),f.css("backgroundImage","none"),k=a('<img src="'+m+'"/>'),k.css({border:0,display:"none"}).width(j),a("body").append(k),f.data("img",k)}var n=g.start.top||Math.round(c.height()/2),o=g.start.left||Math.round(c.width()/2);if(h){var p=d(h);n=p.top,o=p.left}g.fixed?(n-=c.scrollTop(),o-=c.scrollLeft()):(b.top+=c.scrollTop(),b.left+=c.scrollLeft()),k.css({position:"absolute",top:n,left:o,width:0,zIndex:g.zIndex}).show(),b.position=l,f.css(b),k.animate({top:f.css("top"),left:f.css("left"),width:j},g.speed,function(){f.css("zIndex",g.zIndex+1).fadeIn(g.fadeInSpeed,function(){i.isOpened()&&!a(this).index(f)?e.call():f.hide()})}).css("position",l)},f=function(b){var e=this.getOverlay().hide(),f=this.getConf(),g=this.getTrigger(),h=e.data("img"),i={top:f.start.top,left:f.start.left,width:0};g&&a.extend(i,d(g)),f.fixed&&h.css({position:"absolute"}).animate({top:"+="+c.scrollTop(),left:"+="+c.scrollLeft()},0),h.animate(i,f.closeSpeed,b)};b.addEffect("apple",e,f)}(jQuery),function(a){function e(a,b){var c=Math.pow(10,b);return Math.round(a*c)/c}function f(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function g(a){var b=a.data("events");return b&&b.onSlide}function h(b,c){function y(a,f,g,h){g===undefined?g=f/m*q:h&&(g-=c.min),r&&(g=Math.round(g/r)*r);if(f===undefined||r)f=g*m/q;if(isNaN(g))return d;f=Math.max(0,Math.min(f,m)),g=f/m*q;if(h||!j)g+=c.min;j&&(h?f=m-f:g=c.max-g),g=e(g,s);var i=a.type=="click";if(x&&k!==undefined&&!i){a.type="onSlide",w.trigger(a,[g,f]);if(a.isDefaultPrevented())return d}var l=i?c.speed:0,t=i?function(){a.type="change",w.trigger(a,[g])}:null;return j?(o.animate({top:f},l,t),c.progress&&p.animate({height:m-f+o.height()/2},l)):(o.animate({left:f},l,t),c.progress&&p.animate({width:f+o.width()/2},l)),k=g,n=f,b.val(g),d}function z(){j=c.vertical||f(i,"height")>f(i,"width"),j?(m=f(i,"height")-f(o,"height"),l=i.offset().top+m):(m=f(i,"width")-f(o,"width"),l=i.offset().left)}function A(){z(),d.setValue(c.value!==undefined?c.value:c.min)}var d=this,h=c.css,i=a("<div><div/><a href='#'/></div>").data("rangeinput",d),j,k,l,m,n;b.before(i);var o=i.addClass(h.slider).find("a").addClass(h.handle),p=i.find("div").addClass(h.progress);a.each("min,max,step,value".split(","),function(a,d){var e=b.attr(d);parseFloat(e)&&(c[d]=parseFloat(e,10))});var q=c.max-c.min,r=c.step=="any"?0:c.step,s=c.precision;if(s===undefined)try{s=r.toString().split(".")[1].length}catch(t){s=0}if(b.attr("type")=="range"){var u=b.clone().wrap("<div/>").parent().html(),v=a(u.replace(/type/i,"type=text data-orig-type"));v.val(c.value),b.replaceWith(v),b=v}b.addClass(h.input);var w=a(d).add(b),x=!0;a.extend(d,{getValue:function(){return k},setValue:function(b,c){return z(),y(c||a.Event("api"),undefined,b,!0)},getConf:function(){return c},getProgress:function(){return p},getHandle:function(){return o},getInput:function(){return b},step:function(b,e){e=e||a.Event();var f=c.step=="any"?1:c.step;d.setValue(k+f*(b||1),e)},stepUp:function(a){return d.step(a||1)},stepDown:function(a){return d.step(-a||-1)}}),a.each("onSlide,change".split(","),function(b,e){a.isFunction(c[e])&&a(d).bind(e,c[e]),d[e]=function(b){return b&&a(d).bind(e,b),d}}),o.drag({drag:!1}).bind("dragStart",function(){z(),x=g(a(d))||g(b)}).bind("drag",function(a,c,d){if(b.is(":disabled"))return!1;y(a,j?c:d)}).bind("dragEnd",function(a){a.isDefaultPrevented()||(a.type="change",w.trigger(a,[k]))}).click(function(a){return a.preventDefault()}),i.click(function(a){if(b.is(":disabled")||a.target==o[0])return a.preventDefault();z();var c=j?o.height()/2:o.width()/2;y(a,j?m-l-c+a.pageY:a.pageX-l-c)}),c.keyboard&&b.keydown(function(c){if(b.attr("readonly"))return;var e=c.keyCode,f=a([75,76,38,33,39]).index(e)!=-1,g=a([74,72,40,34,37]).index(e)!=-1;if((f||g)&&!(c.shiftKey||c.altKey||c.ctrlKey))return f?d.step(e==33?10:1,c):g&&d.step(e==34?-10:-1,c),c.preventDefault()}),b.blur(function(b){var c=a(this).val();c!==k&&d.setValue(c,b)}),a.extend(b[0],{stepUp:d.stepUp,stepDown:d.stepDown}),A(),m||a(window).load(A)}a.tools=a.tools||{version:"1.2.6"};var b;b=a.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:!0,progress:!1,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var c,d;a.fn.drag=function(b){return document.ondragstart=function(){return!1},b=a.extend({x:!0,y:!0,drag:!0},b),c=c||a(document).bind("mousedown mouseup",function(e){var f=a(e.target);if(e.type=="mousedown"&&f.data("drag")){var g=f.position(),h=e.pageX-g.left,i=e.pageY-g.top,j=!0;c.bind("mousemove.drag",function(a){var c=a.pageX-h,e=a.pageY-i,g={};b.x&&(g.left=c),b.y&&(g.top=e),j&&(f.trigger("dragStart"),j=!1),b.drag&&f.css(g),f.trigger("drag",[e,c]),d=f}),e.preventDefault()}else try{d&&d.trigger("dragEnd")}finally{c.unbind("mousemove.drag"),d=null}}),this.data("drag",!0)},a.expr[":"].range=function(b){var c=b.getAttribute("type");return c&&c=="range"||!!a(b).filter("input").data("rangeinput")},a.fn.rangeinput=function(c){if(this.data("rangeinput"))return this;c=a.extend(!0,{},b.conf,c);var d;return this.each(function(){var b=new h(a(this),a.extend(!0,{},c)),e=b.getInput().data("rangeinput",b);d=d?d.add(e):e}),d?d:this}}(jQuery),function(a){function b(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}function e(b,e){var f=this,g=b.add(f),h=b.children(),i=0,j=e.vertical;d||(d=f),h.length>1&&(h=a(e.items,b)),e.size>1&&(e.circular=!1),a.extend(f,{getConf:function(){return e},getIndex:function(){return i},getSize:function(){return f.getItems().size()},getNaviButtons:function(){return n.add(o)},getRoot:function(){return b},getItemWrap:function(){return h},getItems:function(){return h.find(e.item).not("."+e.clonedClass)},move:function(a,b){return f.seekTo(i+a,b)},next:function(a){return f.move(e.size,a)},prev:function(a){return f.move(-e.size,a)},begin:function(a){return f.seekTo(0,a)},end:function(a){return f.seekTo(f.getSize()-1,a)},focus:function(){return d=f,f},addItem:function(b){return b=a(b),e.circular?(h.children().last().before(b),h.children().first().replaceWith(b.clone().addClass(e.clonedClass))):(h.append(b),o.removeClass("disabled")),g.trigger("onAddItem",[b]),f},seekTo:function(b,c,k){b.jquery||(b*=1);if(e.circular&&b===0&&i==-1&&c!==0)return f;if(!e.circular&&b<0||b>f.getSize()||b<-1)return f;var l=b;b.jquery?b=f.getItems().index(b):l=f.getItems().eq(b);var m=a.Event("onBeforeSeek");if(!k){g.trigger(m,[b,c]);if(m.isDefaultPrevented()||!l.length)return f}var n=j?{top:-l.position().top}:{left:-l.position().left};return i=b,d=f,c===undefined&&(c=e.speed),h.animate(n,c,e.easing,k||function(){g.trigger("onSeek",[b])}),f}}),a.each(["onBeforeSeek","onSeek","onAddItem"],function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){return b&&a(f).bind(c,b),f}});if(e.circular){var k=f.getItems().slice(-1).clone().prependTo(h),l=f.getItems().eq(1).clone().appendTo(h);k.add(l).addClass(e.clonedClass),f.onBeforeSeek(function(a,b,c){if(a.isDefaultPrevented())return;if(b==-1)return f.seekTo(k,c,function(){f.end(0)}),a.preventDefault();b==f.getSize()&&f.seekTo(l,c,function(){f.begin(0)})});var m=b.parents().add(b).filter(function(){if(a(this).css("display")==="none")return!0});m.length?(m.show(),f.seekTo(0,0,function(){}),m.hide()):f.seekTo(0,0,function(){})}var n=c(b,e.prev).click(function(a){a.stopPropagation(),f.prev()}),o=c(b,e.next).click(function(a){a.stopPropagation(),f.next()});e.circular||(f.onBeforeSeek(function(a,b){setTimeout(function(){a.isDefaultPrevented()||(n.toggleClass(e.disabledClass,b<=0),o.toggleClass(e.disabledClass,b>=f.getSize()-1))},1)}),e.initialIndex||n.addClass(e.disabledClass)),f.getSize()<2&&n.add(o).addClass(e.disabledClass),e.mousewheel&&a.fn.mousewheel&&b.mousewheel(function(a,b){if(e.mousewheel)return f.move(b<0?1:-1,e.wheelSpeed||50),!1});if(e.touch){var p={};h[0].ontouchstart=function(a){var b=a.touches[0];p.x=b.clientX,p.y=b.clientY},h[0].ontouchmove=function(a){if(a.touches.length==1&&!h.is(":animated")){var b=a.touches[0],c=p.x-b.clientX,d=p.y-b.clientY;f[j&&d>0||!j&&c>0?"next":"prev"](),a.preventDefault()}}}e.keyboard&&a(document).bind("keydown.scrollable",function(b){if(!e.keyboard||b.altKey||b.ctrlKey||b.metaKey||a(b.target).is(":input"))return;if(e.keyboard!="static"&&d!=f)return;var c=b.keyCode;if(!(!j||c!=38&&c!=40))return f.move(c==38?-1:1),b.preventDefault();if(!j&&(c==37||c==39))return f.move(c==37?-1:1),b.preventDefault()}),e.initialIndex&&f.seekTo(e.initialIndex,0,function(){})}a.tools=a.tools||{version:"1.2.6"},a.tools.scrollable={conf:{activeClass:"active",circular:!1,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:"> *",items:".items",keyboard:!0,mousewheel:!1,next:".next",prev:".prev",size:1,speed:400,vertical:!1,touch:!0,wheelSpeed:0}};var d;a.fn.scrollable=function(b){var c=this.data("scrollable");return c?c:(b=a.extend({},a.tools.scrollable.conf,b),this.each(function(){c=new e(a(this),b),a(this).data("scrollable",c)}),b.api?c:this)}}(jQuery),function(a){var b=a.tools.scrollable;b.autoscroll={conf:{autoplay:!0,interval:3e3,autopause:!0}},a.fn.autoscroll=function(c){typeof c=="number"&&(c={interval:c});var d=a.extend({},b.autoscroll.conf,c),e;return this.each(function(){function h(){f=setTimeout(function(){b.next()},d.interval)}var b=a(this).data("scrollable"),c=b.getRoot(),f,g=!1;b&&(e=b),b.play=function(){if(f)return;g=!1,c.bind("onSeek",h),h()},b.pause=function(){f=clearTimeout(f),c.unbind("onSeek",h)},b.resume=function(){g||b.play()},b.stop=function(){g=!0,b.pause()},d.autopause&&c.add(b.getNaviButtons()).hover(b.pause,b.resume),d.autoplay&&b.play()}),d.api?e:this}}(jQuery),function(a){function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}var b=a.tools.scrollable;b.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:!1,idPrefix:null,history:!1}},a.fn.navigator=function(d){typeof d=="string"&&(d={navi:d}),d=a.extend({},b.navigator.conf,d);var e;return this.each(function(){function k(a,c,d){b.seekTo(c),d.preventDefault(),i&&history.pushState({i:c})}function l(){return f.find(d.naviItem||"> *")}function m(b){var c=a("<"+(d.naviItem||"a")+"/>").click(function(c){k(a(this),b,c)});return b===0&&c.addClass(h),d.indexed&&c.text(b+1),d.idPrefix&&c.attr("id",d.idPrefix+b),c.appendTo(f)}var b=a(this).data("scrollable"),f=d.navi.jquery?d.navi:c(b.getRoot(),d.navi),g=b.getNaviButtons(),h=d.activeClass,i=d.history&&!!history.pushState,j=b.getConf().size;b&&(e=b),b.getNaviButtons=function(){return g.add(f)},i&&(history.pushState({i:0}),a(window).bind("popstate",function(a){var c=a.originalEvent.state;c&&b.seekTo(c.i)})),l().length?l().each(function(b){a(this).click(function(c){k(a(this),b,c)})}):a.each(b.getItems(),function(a){a%j==0&&m(a)}),b.onBeforeSeek(function(a,b){setTimeout(function(){if(!a.isDefaultPrevented()){var c=b/j,d=l().eq(c);d.length&&l().removeClass(h).eq(c).addClass(h)}},1)}),b.onAddItem(function(a,c){var d=b.getItems().index(c);d%j==0&&m(d)})}),d.api?e:this}}(jQuery),function(a){function e(c,d,e){var f=this,g=c.add(this),h=c.find(e.tabs),i=d.jquery?d:c.children(d),j;h.length||(h=c.children()),i.length||(i=c.parent().find(d)),i.length||(i=a(d)),a.extend(this,{click:function(c,d){var i=h.eq(c);typeof c=="string"&&c.replace("#","")&&(i=h.filter("[href*="+c.replace("#","")+"]"),c=Math.max(h.index(i),0));if(e.rotate){var k=h.length-1;if(c<0)return f.click(k,d);if(c>k)return f.click(0,d)}if(!i.length){if(j>=0)return f;c=e.initialIndex,i=h.eq(c)}if(c===j)return f;d=d||a.Event(),d.type="onBeforeClick",g.trigger(d,[c]);if(d.isDefaultPrevented())return;return b[e.effect].call(f,c,function(){j=c,d.type="onClick",g.trigger(d,[c])}),h.removeClass(e.current),i.addClass(e.current),f},getConf:function(){return e},getTabs:function(){return h},getPanes:function(){return i},getCurrentPane:function(){return i.eq(j)},getCurrentTab:function(){return h.eq(j)},getIndex:function(){return j},next:function(){return f.click(j+1)},prev:function(){return f.click(j-1)},destroy:function(){return h.unbind(e.event).removeClass(e.current),i.find("a[href^=#]").unbind("click.T"),f}}),a.each("onBeforeClick,onClick".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){return b&&a(f).bind(c,b),f}}),e.history&&a.fn.history&&(a.tools.history.init(h),e.event="history"),h.each(function(b){a(this).bind(e.event,function(a){return f.click(b,a),a.preventDefault()})}),i.find("a[href^=#]").bind("click.T",function(b){f.click(a(this).attr("href"),b)}),location.hash&&e.tabs=="a"&&c.find("[href="+location.hash+"]").length?f.click(location.hash):(e.initialIndex===0||e.initialIndex>0)&&f.click(e.initialIndex)}a.tools=a.tools||{version:"1.2.6"},a.tools.tabs={conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:!1,slideUpSpeed:400,slideDownSpeed:400,history:!1},addEffect:function(a,c){b[a]=c}};var b={"default":function(a,b){this.getPanes().hide().eq(a).show(),b.call()},fade:function(a,b){var c=this.getConf(),d=c.fadeOutSpeed,e=this.getPanes();d?e.fadeOut(d):e.hide(),e.eq(a).fadeIn(c.fadeInSpeed,b)},slide:function(a,b){var c=this.getConf();this.getPanes().slideUp(c.slideUpSpeed),this.getPanes().eq(a).slideDown(c.slideDownSpeed,b)},ajax:function(a,b){this.getPanes().eq(0).load(this.getTabs().eq(a).attr("href"),b)}},c,d;a.tools.tabs.addEffect("horizontal",function(b,e){if(c)return;var f=this.getPanes().eq(b),g=this.getCurrentPane();d||(d=this.getPanes().eq(0).width()),c=!0,f.show(),g.animate({width:0},{step:function(a){f.css("width",d-a)},complete:function(){a(this).hide(),e.call(),c=!1}}),g.length||(e.call(),c=!1)}),a.fn.tabs=function(b,c){var d=this.data("tabs");return d&&(d.destroy(),this.removeData("tabs")),a.isFunction(c)&&(c={onBeforeClick:c}),c=a.extend({},a.tools.tabs.conf,c),this.each(function(){d=new e(a(this),b,c),a(this).data("tabs",d)}),c.api?d:this}}(jQuery),function(a){function c(b,c){function i(c){var d=a(c);return d.length<2?d:b.parent().find(c)}function l(){g=setTimeout(function(){f.next()},c.interval)}var d=this,e=b.add(this),f=b.data("tabs"),g,h=!0,j=i(c.next).click(function(){f.next()}),k=i(c.prev).click(function(){f.prev()});a.extend(d,{getTabs:function(){return f},getConf:function(){return c},play:function(){if(g)return d;var b=a.Event("onBeforePlay");return e.trigger(b),b.isDefaultPrevented()?d:(h=!1,e.trigger("onPlay"),e.bind("onClick",l),l(),d)},pause:function(){if(!g)return d;var b=a.Event("onBeforePause");return e.trigger(b),b.isDefaultPrevented()?d:(g=clearTimeout(g),e.trigger("onPause"),e.unbind("onClick",l),d)},resume:function(){h||d.play()},stop:function(){d.pause(),h=!0}}),a.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","),function(b,e){a.isFunction(c[e])&&a(d).bind(e,c[e]),d[e]=function(b){return a(d).bind(e,b)}}),c.autopause&&f.getTabs().add(j).add(k).add(f.getPanes()).hover(d.pause,d.resume),c.autoplay&&d.play(),c.clickable&&f.getPanes().click(function(){f.next()});if(!f.getConf().rotate){var m=c.disabledClass;f.getIndex()||k.addClass(m),f.onBeforeClick(function(a,b){k.toggleClass(m,!b),j.toggleClass(m,b==f.getTabs().length-1)})}}var b;b=a.tools.tabs.slideshow={conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:!1,autopause:!0,interval:3e3,clickable:!0,api:!1}},a.fn.slideshow=function(d){var e=this.data("slideshow");return e?e:(d=a.extend({},b.conf,d),this.each(function(){e=new c(a(this),d),a(this).data("slideshow",e)}),d.api?e:this)}}(jQuery),function(a){function c(){if(a.browser.msie){var b=a(document).height(),c=a(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,b-c<20?c:b]}return[a(document).width(),a(document).height()]}function d(b){if(b)return b.call(a.mask)}a.tools=a.tools||{version:"1.2.6"};var b;b=a.tools.expose={conf:{maskId:"exposeMask",loadSpeed:"slow",closeSpeed:"fast",closeOnClick:!0,closeOnEsc:!0,zIndex:9998,opacity:.8,startOpacity:0,color:"#fff",onLoad:null,onClose:null}};var e,f,g,h,i;a.mask={load:function(j,k){if(g)return this;typeof j=="string"&&(j={color:j}),j=j||h,h=j=a.extend(a.extend({},b.conf),j),e=a("#"+j.maskId),e.length||(e=a("<div/>").attr("id",j.maskId),a("body").append(e));var l=c();return e.css({position:"absolute",top:0,left:0,width:l[0],height:l[1],display:"none",opacity:j.startOpacity,zIndex:j.zIndex}),j.color&&e.css("backgroundColor",j.color),d(j.onBeforeLoad)===!1?this:(j.closeOnEsc&&a(document).bind("keydown.mask",function(b){b.keyCode==27&&a.mask.close(b)}),j.closeOnClick&&e.bind("click.mask",function(b){a.mask.close(b)}),a(window).bind("resize.mask",function(){a.mask.fit()}),k&&k.length&&(i=k.eq(0).css("zIndex"),a.each(k,function(){var b=a(this);/relative|absolute|fixed/i.test(b.css("position"))||b.css("position","relative")}),f=k.css({zIndex:Math.max(j.zIndex+1,i=="auto"?0:i)})),e.css({display:"block"}).fadeTo(j.loadSpeed,j.opacity,function(){a.mask.fit(),d(j.onLoad),g="full"}),g=!0,this)},close:function(){if(g){if(d(h.onBeforeClose)===!1)return this;e.fadeOut(h.closeSpeed,function(){d(h.onClose),f&&f.css({zIndex:i}),g=!1}),a(document).unbind("keydown.mask"),e.unbind("click.mask"),a(window).unbind("resize.mask")}return this},fit:function(){if(g){var a=c();e.css({width:a[0],height:a[1]})}},getMask:function(){return e},isLoaded:function(a){return a?g=="full":g},getConf:function(){return h},getExposed:function(){return f}},a.fn.mask=function(b){return a.mask.load(b),this},a.fn.expose=function(b){return a.mask.load(b,this),this}}(jQuery),function(){function f(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function g(a,b){var c=[];for(var d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d]));return c}function j(c,d,e){if(h.isSupported(d.version))c.innerHTML=h.getHTML(d,e);else if(d.expressInstall&&h.isSupported([6,65]))c.innerHTML=h.getHTML(f(d,{src:d.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title});else{c.innerHTML.replace(/\s/g,"")||(c.innerHTML="<h2>Flash version "+d.version+" or greater is required</h2>"+"<h3>"+(i[0]>0?"Your version is "+i:"You have no flash plugin installed")+"</h3>"+(c.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+b+"'>here</a></p>"),c.tagName=="A"&&(c.onclick=function(){location.href=b}));if(d.onFail){var g=d.onFail.call(this);typeof g=="string"&&(c.innerHTML=g)}}a&&(window[d.id]=document.getElementById(d.id)),f(this,{getRoot:function(){return c},getOptions:function(){return d},getConf:function(){return e},getApi:function(){return c.firstChild}})}var a=document.all,b="http://www.adobe.com/go/getflashplayer",c=typeof jQuery=="function",d=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,e={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:!0,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:!1,cachebusting:!1};window.attachEvent&&window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){},__flash_savedUnloadHandler=function(){}}),window.flashembed=function(a,b,c){typeof a=="string"&&(a=document.getElementById(a.replace("#","")));if(!a)return;return typeof b=="string"&&(b={src:b}),new j(a,f(f({},e),b),c)};var h=f(window.flashembed,{conf:e,getVersion:function(){var a,b;try{b=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(c){try{a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"),b=a&&a.GetVariable("$version")}catch(e){try{a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"),b=a&&a.GetVariable("$version")}catch(f){}}}return b=d.exec(b),b?[b[1],b[3]]:[0,0]},asString:function(a){if(a===null||a===undefined)return null;var b=typeof a;b=="object"&&a.push&&(b="array");switch(b){case"string":return a=a.replace(new RegExp('(["\\\\])',"g"),"\\$1"),a=a.replace(/^\s?(\d+\.?\d*)%/,"$1pct"),'"'+a+'"';case"array":return"["+g(a,function(a){return h.asString(a)}).join(",")+"]";case"function":return'"function()"';case"object":var c=[];for(var d in a)a.hasOwnProperty(d)&&c.push('"'+d+'":'+h.asString(a[d]));return"{"+c.join(",")+"}"}return String(a).replace(/\s/g," ").replace(/\'/g,'"')},getHTML:function(b,c){b=f({},b);var d='<object width="'+b.width+'" height="'+b.height+'" id="'+b.id+'" name="'+b.id+'"';b.cachebusting&&(b.src+=(b.src.indexOf("?")!=-1?"&":"?")+Math.random()),b.w3c||!a?d+=' data="'+b.src+'" type="application/x-shockwave-flash"':d+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"',d+=">";if(b.w3c||a)d+='<param name="movie" value="'+b.src+'" />';b.width=b.height=b.id=b.w3c=b.src=null,b.onFail=b.version=b.expressInstall=null;for(var e in b)b[e]&&(d+='<param name="'+e+'" value="'+b[e]+'" />');var g="";if(c){for(var i in c)if(c[i]){var j=c[i];g+=i+"="+encodeURIComponent(/function|object/.test(typeof j)?h.asString(j):j)+"&"}g=g.slice(0,-1),d+='<param name="flashvars" value=\''+g+"' />"}return d+="</object>",d},isSupported:function(a){return i[0]>a[0]||i[0]==a[0]&&i[1]>=a[1]}}),i=h.getVersion();c&&(jQuery.tools=jQuery.tools||{version:"1.2.6"},jQuery.tools.flashembed={conf:e},jQuery.fn.flashembed=function(a,b){return this.each
+(function(){jQuery(this).data("flashembed",flashembed(this,a,b))})})}(),function(a){function f(a){if(a){var b=c.contentWindow.document;b.open().close(),b.location.hash=a}}var b,c,d,e;a.tools=a.tools||{version:"1.2.6"},a.tools.history={init:function(g){if(e)return;a.browser.msie&&a.browser.version<"8"?c||(c=a("<iframe/>").attr("src","javascript:false;").hide().get(0),a("body").prepend(c),setInterval(function(){var d=c.contentWindow.document,e=d.location.hash;b!==e&&a(window).trigger("hash",e)},100),f(location.hash||"#")):setInterval(function(){var c=location.hash;c!==b&&a(window).trigger("hash",c)},100),d=d?d.add(g):g,g.click(function(b){var d=a(this).attr("href");c&&f(d);if(d.slice(0,1)!="#")return location.href="#"+d,b.preventDefault()}),e=!0}},a(window).bind("hash",function(c,e){e?d.filter(function(){var b=a(this).attr("href");return b==e||b==e.replace("#","")}).trigger("history",[e]):d.eq(0).trigger("history",[e]),b=e}),a.fn.history=function(b){return a.tools.history.init(this),this.bind("history",b)}}(jQuery),function(a){function c(b){switch(b.type){case"mousemove":return a.extend(b.data,{clientX:b.clientX,clientY:b.clientY,pageX:b.pageX,pageY:b.pageY});case"DOMMouseScroll":a.extend(b,b.data),b.delta=-b.detail/3;break;case"mousewheel":b.delta=b.wheelDelta/120}return b.type="wheel",a.event.handle.call(this,b,b.delta)}a.fn.mousewheel=function(a){return this[a?"bind":"trigger"]("wheel",a)},a.event.special.wheel={setup:function(){a.event.add(this,b,c,{})},teardown:function(){a.event.remove(this,b,c)}};var b=a.browser.mozilla?"DOMMouseScroll"+(a.browser.version<"1.9"?" mousemove":""):"mousewheel"}(jQuery),function(a){function c(b,c,d){var e=d.relative?b.position().top:b.offset().top,f=d.relative?b.position().left:b.offset().left,g=d.position[0];e-=c.outerHeight()-d.offset[0],f+=b.outerWidth()+d.offset[1],/iPad/i.test(navigator.userAgent)&&(e-=a(window).scrollTop());var h=c.outerHeight()+b.outerHeight();g=="center"&&(e+=h/2),g=="bottom"&&(e+=h),g=d.position[1];var i=c.outerWidth()+b.outerWidth();return g=="center"&&(f-=i/2),g=="left"&&(f-=i),{top:e,left:f}}function d(d,e){var f=this,g=d.add(f),h,i=0,j=0,k=d.attr("title"),l=d.attr("data-tooltip"),m=b[e.effect],n,o=d.is(":input"),p=o&&d.is(":checkbox, :radio, select, :button, :submit"),q=d.attr("type"),r=e.events[q]||e.events[o?p?"widget":"input":"def"];if(!m)throw'Nonexistent effect "'+e.effect+'"';r=r.split(/,\s*/);if(r.length!=2)throw"Tooltip: bad events configuration for "+q;d.bind(r[0],function(a){clearTimeout(i),e.predelay?j=setTimeout(function(){f.show(a)},e.predelay):f.show(a)}).bind(r[1],function(a){clearTimeout(j),e.delay?i=setTimeout(function(){f.hide(a)},e.delay):f.hide(a)}),k&&e.cancelDefault&&(d.removeAttr("title"),d.data("title",k)),a.extend(f,{show:function(b){if(!h){l?h=a(l):e.tip?h=a(e.tip).eq(0):k?h=a(e.layout).addClass(e.tipClass).appendTo(document.body).hide().append(k):(h=d.next(),h.length||(h=d.parent().next()));if(!h.length)throw"Cannot find tooltip for "+d}if(f.isShown())return f;h.stop(!0,!0);var o=c(d,h,e);e.tip&&h.html(d.data("title")),b=a.Event(),b.type="onBeforeShow",g.trigger(b,[o]);if(b.isDefaultPrevented())return f;o=c(d,h,e),h.css({position:"absolute",top:o.top,left:o.left}),n=!0,m[0].call(f,function(){b.type="onShow",n="full",g.trigger(b)});var p=e.events.tooltip.split(/,\s*/);return h.data("__set")||(h.unbind(p[0]).bind(p[0],function(){clearTimeout(i),clearTimeout(j)}),p[1]&&!d.is("input:not(:checkbox, :radio), textarea")&&h.unbind(p[1]).bind(p[1],function(a){a.relatedTarget!=d[0]&&d.trigger(r[1].split(" ")[0])}),e.tip||h.data("__set",!0)),f},hide:function(c){if(!h||!f.isShown())return f;c=a.Event(),c.type="onBeforeHide",g.trigger(c);if(c.isDefaultPrevented())return;return n=!1,b[e.effect][1].call(f,function(){c.type="onHide",g.trigger(c)}),f},isShown:function(a){return a?n=="full":n},getConf:function(){return e},getTip:function(){return h},getTrigger:function(){return d}}),a.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){return b&&a(f).bind(c,b),f}})}a.tools=a.tools||{version:"1.2.6"},a.tools.tooltip={conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,fadeIE:!1,position:["top","center"],offset:[0,0],relative:!1,cancelDefault:!0,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,c,d){b[a]=[c,d]}};var b={toggle:[function(a){var b=this.getConf(),c=this.getTip(),d=b.opacity;d<1&&c.css({opacity:d}),c.show(),a.call()},function(a){this.getTip().hide(),a.call()}],fade:[function(b){var c=this.getConf();!a.browser.msie||c.fadeIE?this.getTip().fadeTo(c.fadeInSpeed,c.opacity,b):(this.getTip().show(),b())},function(b){var c=this.getConf();!a.browser.msie||c.fadeIE?this.getTip().fadeOut(c.fadeOutSpeed,b):(this.getTip().hide(),b())}]};a.fn.tooltip=function(b){var c=this.data("tooltip");return c?c:(b=a.extend(!0,{},a.tools.tooltip.conf,b),typeof b.position=="string"&&(b.position=b.position.split(/,?\s/)),this.each(function(){c=new d(a(this),b),a(this).data("tooltip",c)}),b.api?c:this)}}(jQuery),function(a){function c(b){var c=a(window),d=c.width()+c.scrollLeft(),e=c.height()+c.scrollTop();return[b.offset().top<=c.scrollTop(),d<=b.offset().left+b.width(),e<=b.offset().top+b.height(),c.scrollLeft()>=b.offset().left]}function d(a){var b=a.length;while(b--)if(a[b])return!1;return!0}var b=a.tools.tooltip;b.dynamic={conf:{classNames:"top right bottom left"}},a.fn.dynamic=function(e){typeof e=="number"&&(e={speed:e}),e=a.extend({},b.dynamic.conf,e);var f=a.extend(!0,{},e),g=e.classNames.split(/\s/),h;return this.each(function(){var b=a(this).tooltip().onBeforeShow(function(b,e){var i=this.getTip(),j=this.getConf();h||(h=[j.position[0],j.position[1],j.offset[0],j.offset[1],a.extend({},j)]),a.extend(j,h[4]),j.position=[h[0],h[1]],j.offset=[h[2],h[3]],i.css({visibility:"hidden",position:"absolute",top:e.top,left:e.left}).show();var k=a.extend(!0,{},f),l=c(i);if(!d(l)){l[2]&&(a.extend(j,k.top),j.position[0]="top",i.addClass(g[0])),l[3]&&(a.extend(j,k.right),j.position[1]="right",i.addClass(g[1])),l[0]&&(a.extend(j,k.bottom),j.position[0]="bottom",i.addClass(g[2])),l[1]&&(a.extend(j,k.left),j.position[1]="left",i.addClass(g[3]));if(l[0]||l[2])j.offset[0]*=-1;if(l[1]||l[3])j.offset[1]*=-1}i.css({visibility:"visible"}).hide()});b.onBeforeShow(function(){var a=this.getConf(),b=this.getTip();setTimeout(function(){a.position=[h[0],h[1]],a.offset=[h[2],h[3]]},0)}),b.onHide(function(){var a=this.getTip();a.removeClass(e.classNames)}),ret=b}),e.api?ret:this}}(jQuery),function(a){var b=a.tools.tooltip;a.extend(b.conf,{direction:"up",bounce:!1,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!a.browser.msie});var c={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};b.addEffect("slide",function(a){var b=this.getConf(),d=this.getTip(),e=b.slideFade?{opacity:b.opacity}:{},f=c[b.direction]||c.up;e[f[1]]=f[0]+"="+b.slideOffset,b.slideFade&&d.css({opacity:0}),d.show().animate(e,b.slideInSpeed,a)},function(b){var d=this.getConf(),e=d.slideOffset,f=d.slideFade?{opacity:0}:{},g=c[d.direction]||c.up,h=""+g[0];d.bounce&&(h=h=="+"?"-":"+"),f[g[1]]=h+"="+e,this.getTip().animate(f,d.slideOutSpeed,function(){a(this).hide(),b.call()})})}(jQuery),function(a){function h(b,c,d){var e=b.offset().top,f=b.offset().left,g=d.position.split(/,?\s+/),h=g[0],i=g[1];e-=c.outerHeight()-d.offset[0],f+=b.outerWidth()+d.offset[1],/iPad/i.test(navigator.userAgent)&&(e-=a(window).scrollTop());var j=c.outerHeight()+b.outerHeight();h=="center"&&(e+=j/2),h=="bottom"&&(e+=j);var k=b.outerWidth();return i=="center"&&(f-=(k+c.outerWidth())/2),i=="left"&&(f-=k),{top:e,left:f}}function i(a){function b(){return this.getAttribute("type")==a}return b.key="[type="+a+"]",b}function l(b,c,e){function l(b,c,d){if(!e.grouped&&b.length)return;var f;if(d===!1||a.isArray(d)){f=g.messages[c.key||c]||g.messages["*"],f=f[e.lang]||g.messages["*"].en;var h=f.match(/\$\d/g);h&&a.isArray(d)&&a.each(h,function(a){f=f.replace(this,d[a])})}else f=d[e.lang]||d;b.push(f)}var f=this,i=c.add(f);b=b.not(":button, :image, :reset, :submit"),c.attr("novalidate","novalidate"),a.extend(f,{getConf:function(){return e},getForm:function(){return c},getInputs:function(){return b},reflow:function(){return b.each(function(){var b=a(this),c=b.data("msg.el");if(c){var d=h(b,c,e);c.css({top:d.top,left:d.left})}}),f},invalidate:function(c,d){if(!d){var g=[];a.each(c,function(a,c){var d=b.filter("[name='"+a+"']");d.length&&(d.trigger("OI",[c]),g.push({input:d,messages:[c]}))}),c=g,d=a.Event()}return d.type="onFail",i.trigger(d,[c]),d.isDefaultPrevented()||k[e.effect][0].call(f,c,d),f},reset:function(c){return c=c||b,c.removeClass(e.errorClass).each(function(){var b=a(this).data("msg.el");b&&(b.remove(),a(this).data("msg.el",null))}).unbind(e.errorInputEvent||""),f},destroy:function(){return c.unbind(e.formEvent+".V").unbind("reset.V"),b.unbind(e.inputEvent+".V").unbind("change.V"),f.reset()},checkValidity:function(c,g){c=c||b,c=c.not(":disabled");if(!c.length)return!0;g=g||a.Event(),g.type="onBeforeValidate",i.trigger(g,[c]);if(g.isDefaultPrevented())return g.result;var h=[];c.not(":radio:not(:checked)").each(function(){var b=[],c=a(this).data("messages",b),k=d&&c.is(":date")?"onHide.v":e.errorInputEvent+".v";c.unbind(k),a.each(j,function(){var a=this,d=a[0];if(c.filter(d).length){var h=a[1].call(f,c,c.val());if(h!==!0){g.type="onBeforeFail",i.trigger(g,[c,d]);if(g.isDefaultPrevented())return!1;var j=c.attr(e.messageAttr);if(j)return b=[j],!1;l(b,d,h)}}}),b.length&&(h.push({input:c,messages:b}),c.trigger("OI",[b]),e.errorInputEvent&&c.bind(k,function(a){f.checkValidity(c,a)}));if(e.singleError&&h.length)return!1});var m=k[e.effect];if(!m)throw'Validator: cannot find effect "'+e.effect+'"';return h.length?(f.invalidate(h,g),!1):(m[1].call(f,c,g),g.type="onSuccess",i.trigger(g,[c]),c.unbind(e.errorInputEvent+".v"),!0)}}),a.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){return b&&a(f).bind(c,b),f}}),e.formEvent&&c.bind(e.formEvent+".V",function(a){if(!f.checkValidity(null,a))return a.preventDefault();a.target=c,a.type=e.formEvent}),c.bind("reset.V",function(){f.reset()}),b[0]&&b[0].validity&&b.each(function(){this.oninvalid=function(){return!1}}),c[0]&&(c[0].checkValidity=f.checkValidity),e.inputEvent&&b.bind(e.inputEvent+".V",function(b){f.checkValidity(a(this),b)}),b.filter(":checkbox, select").filter("[required]").bind("change.V",function(b){var c=a(this);(this.checked||c.is("select")&&a(this).val())&&k[e.effect][1].call(f,c,b)});var m=b.filter(":radio").change(function(a){f.checkValidity(m,a)});a(window).resize(function(){f.reflow()})}a.tools=a.tools||{version:"1.2.6"};var b=/\[type=([a-z]+)\]/,c=/^-?[0-9]*(\.[0-9]+)?$/,d=a.tools.dateinput,e=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,f=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,g;g=a.tools.validator={conf:{grouped:!1,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:!1,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(b,c){a.each(c,function(a,c){g.messages[a]=g.messages[a]||{},g.messages[a][b]=c})},localizeFn:function(b,c){g.messages[b]=g.messages[b]||{},a.extend(g.messages[b],c)},fn:function(c,d,e){a.isFunction(d)?e=d:(typeof d=="string"&&(d={en:d}),this.messages[c.key||c]=d);var f=b.exec(c);f&&(c=i(f[1])),j.push([c,e])},addEffect:function(a,b,c){k[a]=[b,c]}};var j=[],k={"default":[function(b){var c=this.getConf();a.each(b,function(b,d){var e=d.input;e.addClass(c.errorClass);var f=e.data("msg.el");f||(f=a(c.message).addClass(c.messageClass).appendTo(document.body),e.data("msg.el",f)),f.css({visibility:"hidden"}).find("p").remove(),a.each(d.messages,function(b,c){a("<p/>").html(c).appendTo(f)}),f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});var g=h(e,f,c);f.css({visibility:"visible",position:"absolute",top:g.top,left:g.left}).fadeIn(c.speed)})},function(b){var c=this.getConf();b.removeClass(c.errorClass).each(function(){var b=a(this).data("msg.el");b&&b.css({visibility:"hidden"})})}]};a.each("email,url,number".split(","),function(b,c){a.expr[":"][c]=function(a){return a.getAttribute("type")===c}}),a.fn.oninvalid=function(a){return this[a?"bind":"trigger"]("OI",a)},g.fn(":email","Please enter a valid email address",function(a,b){return!b||e.test(b)}),g.fn(":url","Please enter a valid URL",function(a,b){return!b||f.test(b)}),g.fn(":number","Please enter a numeric value.",function(a,b){return c.test(b)}),g.fn("[max]","Please enter a value no larger than $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("max");return parseFloat(b)<=parseFloat(c)?!0:[c]}),g.fn("[min]","Please enter a value of at least $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("min");return parseFloat(b)>=parseFloat(c)?!0:[c]}),g.fn("[required]","Please complete this mandatory field.",function(a,b){return a.is(":checkbox")?a.is(":checked"):!!b}),g.fn("[pattern]",function(a){var b=new RegExp("^"+a.attr("pattern")+"$");return b.test(a.val())}),a.fn.validator=function(b){var c=this.data("validator");return c&&(c.destroy(),this.removeData("validator")),b=a.extend(!0,{},g.conf,b),this.is("form")?this.each(function(){var d=a(this);c=new l(d.find(":input"),d,b),d.data("validator",c)}):(c=new l(this,this.eq(0).closest("form"),b),this.data("validator",c))}}(jQuery);
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/main.js b/typo3/sysext/documentation/Resources/Public/JavaScript/main.js
new file mode 100644 (file)
index 0000000..f938b00
--- /dev/null
@@ -0,0 +1,72 @@
+TYPO3.DocumentationApplication = {
+       datatable: null,
+       // Utility method to retrieve query parameters
+       getUrlVars: function getUrlVars() {
+               var vars = [], hash;
+               var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+               for(var i = 0; i < hashes.length; i++) {
+                       hash = hashes[i].split('=');
+                       vars.push(hash[0]);
+                       vars[hash[0]] = hash[1];
+               }
+               return vars;
+       },
+       // Initializes the data table, depending on the current view
+       initializeView: function() {
+               var getVars = this.getUrlVars();
+               // getVars[1] contains the name of the action key
+               // List view is the default view
+               if (getVars[getVars[1]] == 'manage') {
+                       this.documentationManageView(getVars);
+               } else {
+                       this.documentationListView(getVars);
+               }
+       },
+       // Initializes the list view
+       documentationListView: function(getVars) {
+               this.datatable = $('#typo3-documentation-list').dataTable({
+                       'bPaginate': false,
+                       'bJQueryUI': true,
+                       'bLengthChange': false,
+                       'iDisplayLength': 15,
+                       'bStateSave': true
+               });
+
+               // restore filter
+               if (this.datatable.length && getVars['search']) {
+                       this.datatable.fnFilter(getVars['search']);
+               }
+       },
+       // Initializes the management view
+       documentationManageView: function(getVars) {
+               this.datatable = $('#typo3-documentation-manage').dataTable({
+                       'bPaginate': false,
+                       'bJQueryUI': true,
+                       'bLengthChange': false,
+                       'iDisplayLength': 15,
+                       'bStateSave': true,
+                       'aaSorting': [[ 1, 'asc' ]]
+               });
+
+               // restore filter
+               if (this.datatable.length && getVars['search']) {
+                       this.datatable.fnFilter(getVars['search']);
+               }
+       }
+};
+
+// IIFE for faster access to $ and save $ use
+(function ($) {
+
+       $(document).ready(function() {
+               // Initialize the view
+               TYPO3.DocumentationApplication.initializeView();
+
+               // Make the data table filter react to the clearing of the filter field
+               $('.dataTables_wrapper .dataTables_filter input').clearable({
+                       onClear: function() {
+                               TYPO3.DocumentationApplication.datatable.fnFilter('');
+                       }
+               });
+       });
+}(jQuery));
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentFormatTest.php b/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentFormatTest.php
new file mode 100644 (file)
index 0000000..66d7f0d
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+namespace TYPO3\CMS\Documentation\Tests;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case for class \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat.
+ */
+class DocumentFormatTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = new \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat();
+       }
+
+       public function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * @test
+        */
+       public function setFormatForStringSetsFormat() {
+               $this->fixture->setFormat('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getFormat()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setPathForStringSetsPath() {
+               $this->fixture->setPath('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getPath()
+               );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTest.php b/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTest.php
new file mode 100644 (file)
index 0000000..203b58d
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+namespace TYPO3\CMS\Documentation\Tests;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case for class \TYPO3\CMS\Documentation\Domain\Model\Document.
+ */
+class DocumentTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Documentation\Domain\Model\Document
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = new \TYPO3\CMS\Documentation\Domain\Model\Document();
+       }
+
+       public function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * @test
+        */
+       public function setPackageKeyForStringSetsPackageKey() {
+               $this->fixture->setPackageKey('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getPackageKey()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setIconForStringSetsTitle() {
+               $this->fixture->setIcon('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getIcon()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function getTranslationsReturnsInitialValueForDocumentTranslation() {
+               $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $this->assertEquals(
+                       $newObjectStorage,
+                       $this->fixture->getTranslations()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setTranslationsForObjectStorageContainingDocumentTranslationSetsTranslations() {
+               $translation = new \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation();
+               $objectStorageHoldingExactlyOneTranslations = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $objectStorageHoldingExactlyOneTranslations->attach($translation);
+               $this->fixture->setTranslations($objectStorageHoldingExactlyOneTranslations);
+
+               $this->assertSame(
+                       $objectStorageHoldingExactlyOneTranslations,
+                       $this->fixture->getTranslations()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function addTranslationToObjectStorageHoldingTranslations() {
+               $translation = new \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation();
+               $objectStorageHoldingExactlyOneTranslation = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $objectStorageHoldingExactlyOneTranslation->attach($translation);
+               $this->fixture->addTranslation($translation);
+
+               $this->assertEquals(
+                       $objectStorageHoldingExactlyOneTranslation,
+                       $this->fixture->getTranslations()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function removeTranslationFromObjectStorageHoldingTranslations() {
+               $translation = new \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation();
+               $localObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $localObjectStorage->attach($translation);
+               $localObjectStorage->detach($translation);
+               $this->fixture->addTranslation($translation);
+               $this->fixture->removeTranslation($translation);
+
+               $this->assertEquals(
+                       $localObjectStorage,
+                       $this->fixture->getTranslations()
+               );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTranslationTest.php b/typo3/sysext/documentation/Tests/Unit/Domain/Model/DocumentTranslationTest.php
new file mode 100644 (file)
index 0000000..4242752
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+namespace TYPO3\CMS\Documentation\Tests;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Xavier Perseguers <xavier@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script 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.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case for class \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation.
+ */
+class DocumentTranslationTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+
+       /**
+        * @var \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = new \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation();
+       }
+
+       public function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * @test
+        */
+       public function setLanguageForStringSetsLocale() {
+               $this->fixture->setLanguage('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getLanguage()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setTitleForStringSetsTitle() {
+               $this->fixture->setTitle('Conceived at T3DD13');
+
+               $this->assertSame(
+                       'Conceived at T3DD13',
+                       $this->fixture->getTitle()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function getFormatsReturnsInitialValueForDocumentFormat() {
+               $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $this->assertEquals(
+                       $newObjectStorage,
+                       $this->fixture->getFormats()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setFormatsForObjectStorageContainingDocumentFormatSetsFormats() {
+               $format = new \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat();
+               $objectStorageHoldingExactlyOneFormats = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $objectStorageHoldingExactlyOneFormats->attach($format);
+               $this->fixture->setFormats($objectStorageHoldingExactlyOneFormats);
+
+               $this->assertSame(
+                       $objectStorageHoldingExactlyOneFormats,
+                       $this->fixture->getFormats()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function addFormatToObjectStorageHoldingFormats() {
+               $format = new \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat();
+               $objectStorageHoldingExactlyOneFormat = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $objectStorageHoldingExactlyOneFormat->attach($format);
+               $this->fixture->addFormat($format);
+
+               $this->assertEquals(
+                       $objectStorageHoldingExactlyOneFormat,
+                       $this->fixture->getFormats()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function removeFormatFromObjectStorageHoldingFormats() {
+               $format = new \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat();
+               $localObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+               $localObjectStorage->attach($format);
+               $localObjectStorage->detach($format);
+               $this->fixture->addFormat($format);
+               $this->fixture->removeFormat($format);
+
+               $this->assertEquals(
+                       $localObjectStorage,
+                       $this->fixture->getFormats()
+               );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/ext_emconf.php b/typo3/sysext/documentation/ext_emconf.php
new file mode 100644 (file)
index 0000000..bd30d2e
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+/***************************************************************
+ * Extension Manager/Repository config file for ext: "documentation"
+ *
+ * Auto generated by Extension Builder 2013-07-04
+ *
+ * Manual updates:
+ * Only the data in the array - anything else is removed by next write.
+ * "version" and "dependencies" must not be touched!
+ ***************************************************************/
+
+$EM_CONF[$_EXTKEY] = array(
+       'title' => 'Documentation',
+       'description' => 'Backend module for TYPO3 to list and show documentation of loaded extensions as well as custom documents.',
+       'category' => 'be',
+       'author' => 'Xavier Perseguers, Francois Suter',
+       'author_email' => 'xavier@typo3.org, francois.suter@typo3.org',
+       'author_company' => '',
+       'shy' => '',
+       'priority' => '',
+       'module' => '',
+       'state' => 'stable',
+       'internal' => '',
+       'uploadfolder' => '0',
+       'createDirs' => '',
+       'modify_tables' => '',
+       'clearCacheOnLoad' => 0,
+       'lockType' => '',
+       'version' => '6.2.0',
+       'constraints' => array(
+               'depends' => array(
+                       'extbase' => '6.2.0-6.2.99',
+                       'fluid' => '6.2.0-6.2.99',
+                       'typo3' => '6.2.0-6.2.99',
+               ),
+               'conflicts' => array(
+               ),
+               'suggests' => array(
+               ),
+       ),
+);
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/ext_icon.gif b/typo3/sysext/documentation/ext_icon.gif
new file mode 100644 (file)
index 0000000..ef027d3
Binary files /dev/null and b/typo3/sysext/documentation/ext_icon.gif differ
diff --git a/typo3/sysext/documentation/ext_tables.php b/typo3/sysext/documentation/ext_tables.php
new file mode 100644 (file)
index 0000000..b40c42b
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die('Access denied.');
+}
+
+if (TYPO3_MODE === 'BE') {
+       // Registers a Backend Module
+       \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
+               'TYPO3.CMS.' . $_EXTKEY,
+               'help',                         // Make module a submodule of 'help'
+               'documentation',        // Submodule key
+               'top',                          // Position
+               array(
+                       'Document' => 'list, manage, download',
+               ),
+               array(
+                       'access' => 'user,group',
+                       'icon'   => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
+                       'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_mod.xlf',
+               )
+       );
+}
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Documentation');
+
+?>
\ No newline at end of file