diff --git a/.travis.yml b/.travis.yml index 9284368abf20b63885d4b7a4dc9e3bf60b6020bd..d990cf834471e84db73561f3ad4e2d63202c5068 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ before_script: - phpenv rehash - composer install - npm install -g eslint@"<5.0.0" + - npm install -g jshint@"2.9.6" cache: directories: @@ -21,4 +22,4 @@ cache: - $HOME/.composer/cache/files script: - - vendor/bin/phing eslint phpunitfast phpcs-console php-cs-fixer-dryrun + - vendor/bin/phing eslint jshint phpunitfast phpcs-console php-cs-fixer-dryrun diff --git a/Gruntfile.js b/Gruntfile.js index f5769783342cf57c0676d9475edd6a181d6dba39..e0ca99043be53f33a8f7b2f8892d21e360fd4d52 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,7 +17,7 @@ module.exports = function(grunt) { // First identify mixins: var mixinMatches = config.match(/["']mixins["']\s*=>\s*\[([^\]]+)\]/); if (mixinMatches !== null) { - var mixinParts = mixinMatches[1].split(',') + var mixinParts = mixinMatches[1].split(','); for (var i = 0; i < mixinParts.length; i++) { parts[1] = mixinParts[i].trim().replace(/['"]/g, ''); retVal.push(parts.join('/') + '/'); diff --git a/Vagrantfile b/Vagrantfile index 544c26a124ff410901fec96006a8904cf484750e..44d8b801dfea7a213a79d21e695b9e76b7a6ac26 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -27,6 +27,7 @@ Vagrant.configure("2") do |config| # Network configuration to forward ports. config.vm.network :forwarded_port, guest: 80, host: 4567 config.vm.network :forwarded_port, guest: 8080, host: 4568 + config.vm.synced_folder ".", "/vagrant", :owner => 'ubuntu' # Enable provisioning with a shell script. Additional provisioners such as # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the @@ -41,7 +42,7 @@ Vagrant.configure("2") do |config| # Install package dependencies. apt-get update apt-get install -y git zip unzip apache2 default-jdk mysql-server - apt-get install -y libapache2-mod-php php-mbstring php-pear php php-dev php-gd php-intl php-json php-ldap php-mysql php-xml php-curl + apt-get install -y libapache2-mod-php php-mbstring php-pear php php-dev php-gd php-intl php-json php-ldap php-mysql php-soap php-xml php-curl # Install composer. php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" diff --git a/build.xml b/build.xml index d389674afa4107c3c5c3fd6f1eac30380e7b44ae..2555af944b350e95f714b3ea2655622a73e7c5a7 100644 --- a/build.xml +++ b/build.xml @@ -28,7 +28,7 @@ <property name="solr_version" value="7.3.1" /> <property name="phpdoc_version" value="2.9.0" /> - <property name="version" value="5.0.1" /> + <property name="version" value="5.1" /> <!-- We only need the -p switch if the password is non-blank --> <if><not><equals arg1="${mysqlrootpass}" arg2="" /></not><then> @@ -67,6 +67,7 @@ <phingcall target="pdepend"/> <phingcall target="phploc"/> <phingcall target="eslint-report"/> + <phingcall target="jshint-report"/> </target> <!-- Report rule violations with PHPMD (mess detector) --> @@ -118,7 +119,15 @@ <exec command="eslint -c ${srcdir}/.eslintrc.js ${srcdir}/themes/bootstrap3/js/*.js --fix" escape="false" passthru="true" /> </target> <target name="eslint-report"> - <exec command="eslint -c ${srcdir}/.eslintrc.js ${srcdir}/themes/bootstrap3/js/*.js --format checkstyle -o ${builddir}/reports/eslint.xml" escape="false" /> + <exec command="eslint -c ${srcdir}/.eslintrc.js ${srcdir}/themes/bootstrap3/js/*.js --format checkstyle -o ${builddir}/reports/eslint-checkstyle.xml" escape="false" /> + </target> + + <!-- JSHint --> + <target name="jshint"> + <exec command="jshint --config=${srcdir}/tests/jshint.json --exclude=themes/*/js/vendor ${srcdir}/themes" checkreturn="true" passthru="true" /> + </target> + <target name="jshint-report"> + <exec command="jshint --config=${srcdir}/tests/jshint.json --exclude=themes/*/js/vendor --reporter=checkstyle ${srcdir}/themes > ${builddir}/reports/jshint-checkstyle.xml" /> </target> <!-- PHP API Documentation --> diff --git a/composer.json b/composer.json index 5974b3b99b0e02a472553ef125df0ff308a17ffb..a0341cf58340c79b3bc9bd6a92e521cfb0c4e31a 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ "cap60552/php-sip2": "1.0.0", "endroid/qr-code": "2.5.0", "ghislainf/zf2-whoops": "dev-master#2649cf7caf400409942ddc3f8fe15b89381fc74e", - "jasig/phpcas": "1.3.5", - "matthiasmullie/minify": "1.3.60", + "jasig/phpcas": "1.3.6", + "matthiasmullie/minify": "1.3.61", "ocramius/proxy-manager": "2.0.4", "oyejorge/less.php": "1.7.0.14", "pear/archive_tar": "^1.4", @@ -34,14 +34,14 @@ "pear/http_request2": "2.3.0", "pear/validate_ispn": "dev-master", "phing/phing": "2.16.1", - "serialssolutions/summon": "1.1.0", - "symfony/yaml": "3.4.10", + "serialssolutions/summon": "1.2.0", + "symfony/yaml": "3.4.21", "swagger-api/swagger-ui": "2.2.10", - "vufind-org/vufindcode": "1.1.0", + "vufind-org/vufindcode": "1.1.1", "vufind-org/vufinddate": "1.0.0", "vufind-org/vufindharvest": "2.4.0", "vufind-org/vufindhttp": "2.2.0", - "yajra/laravel-pdo-via-oci8": "1.3.6", + "yajra/laravel-pdo-via-oci8": "1.3.7", "zendframework/zend-cache": "2.8.2", "zendframework/zend-captcha": "2.8.0", "zendframework/zend-code": "3.1.0", @@ -53,12 +53,13 @@ "zendframework/zend-escaper": "2.6.0", "zendframework/zend-eventmanager": "3.2.1", "zendframework/zend-feed": "2.10.3", - "zendframework/zend-filter": "2.8.0", - "zendframework/zend-http": "2.8.2", + "zendframework/zend-filter": "2.9.1", + "zendframework/zend-form": "2.14.0", + "zendframework/zend-http": "2.9.1", "zendframework/zend-i18n": "2.9.0", "zendframework/zend-loader": "2.6.0", "zendframework/zend-log": "2.10.0", - "zendframework/zend-mail": "2.8.0", + "zendframework/zend-mail": "2.10.0", "zendframework/zend-modulemanager": "2.8.2", "zendframework/zend-mvc": "3.1.1", "zendframework/zend-mvc-console": "1.2.0", @@ -66,13 +67,13 @@ "zendframework/zend-mvc-plugin-flashmessenger": "1.1.0", "zendframework/zend-paginator": "2.8.1", "zendframework/zend-serializer": "2.9.0", - "zendframework/zend-servicemanager": "3.3.2", + "zendframework/zend-servicemanager": "3.4.0", "zendframework/zend-session": "2.8.5", "zendframework/zend-soap": "2.7.0", - "zendframework/zend-stdlib": "3.2.0", + "zendframework/zend-stdlib": "3.2.1", "zendframework/zend-text": "2.7.0", - "zendframework/zend-validator": "2.10.2", - "zendframework/zend-view": "2.10.0", + "zendframework/zend-validator": "2.11.0", + "zendframework/zend-view": "2.11.1", "zendframework/zendrest": "2.0.2", "zendframework/zendservice-amazon": "2.3.0", "zendframework/zendservice-recaptcha": "3.1.0", @@ -83,12 +84,12 @@ "require-dev": { "behat/mink": "1.7.1", "behat/mink-selenium2-driver": "1.3.1", - "friendsofphp/php-cs-fixer": "2.11.1", + "friendsofphp/php-cs-fixer": "2.14.0", "phploc/phploc": "4.0.1", "phpmd/phpmd": "2.6.0", - "phpunit/phpunit": "6.5.8", + "phpunit/phpunit": "6.5.13", "sebastian/phpcpd": "3.0.1", - "squizlabs/php_codesniffer": "3.2.3" + "squizlabs/php_codesniffer": "3.4.0" }, "scripts": { "phing-install-dependencies": "phing installsolr installswaggerui", diff --git a/config/application.config.php b/config/application.config.php index d72316b3f27ed88885ccda1136ece11f22e4933d..b03a2416f9c369307c570a8e4f31db52cac6197c 100644 --- a/config/application.config.php +++ b/config/application.config.php @@ -2,10 +2,10 @@ // Set up modules: $modules = [ - 'Zend\Router', 'ZfcRbac', + 'Zend\Form', 'Zend\Router', 'ZfcRbac', 'VuFindTheme', 'VuFindSearch', 'VuFind', 'VuFindAdmin', 'VuFindApi' ]; -if (PHP_SAPI == 'cli' && !defined('VUFIND_PHPUNIT_RUNNING')) { +if (PHP_SAPI == 'cli' && APPLICATION_ENV !== 'testing') { $modules[] = 'Zend\Mvc\Console'; $modules[] = 'VuFindConsole'; } @@ -52,7 +52,7 @@ if (!is_dir($cacheDir)) { } // Enable caching unless in dev mode or running tests: -$useCache = APPLICATION_ENV != 'development' && !defined('VUFIND_PHPUNIT_RUNNING'); +$useCache = APPLICATION_ENV != 'development' && APPLICATION_ENV != 'testing'; // Build configuration: return [ diff --git a/config/autoload/global.php b/config/autoload/global.php index 5ce1434a77848f6891552c00fd995660f9429a8f..e96a65d7456bb3d2d0550cc484a910ec847ee35c 100644 --- a/config/autoload/global.php +++ b/config/autoload/global.php @@ -2,7 +2,7 @@ /** * Global Configuration Override * - * You can use this file for overridding configuration values from modules, etc. + * You can use this file for overriding configuration values from modules, etc. * You would place values in here that are agnostic to the environment and not * sensitive to security. * diff --git a/config/vufind/Aleph.ini b/config/vufind/Aleph.ini index 5d24bb1782545529e3edef660907fd41ba063efc..3387a448a98d5a2b7b4ca69e3ddf0a2ca6373a31 100644 --- a/config/vufind/Aleph.ini +++ b/config/vufind/Aleph.ini @@ -17,6 +17,9 @@ xport = 80 ; debug mode for logging errors debug = false +; override the host, and dlfport settings for Aleph REST API requests (optional) +;dlfbaseurl = http://aleph.mylibrary.edu:1891/rest-dlf/ + ; bibliographic library -- the library that your bibs are in - normally XXX01 ; where XXX is a prefix that you have configured. It's the library you would ; search in your cataloging client. diff --git a/config/vufind/Demo.ini b/config/vufind/Demo.ini index 87cb023f6e8e71142ce1e75338ae7459a6d02c6e..ca5936a68f65077e753ac862553f9526dfa8c0d6 100644 --- a/config/vufind/Demo.ini +++ b/config/vufind/Demo.ini @@ -87,6 +87,14 @@ renewMyItems = 50 ;pattern = "alphanumeric" ;hint = "Your optional custom hint can go here." +[Loans] +; Whether to support paging in the "ILS". Default is false, which means that all +; loans are always returned from the driver. +;paging = true + +; If paging is enabled, how many results can be returned at a time. Default is 100. +;max_page_size = 100 + [TransactionHistory] ; By default the loan history is disabled. Uncomment the following line to enable it. ;enabled = true diff --git a/config/vufind/EDS.ini b/config/vufind/EDS.ini index 07bf4aa9ecdaf50413d67c0c41b255624e569a98..0354ae03da0830828688005d69d8ea4ba56f5c78 100644 --- a/config/vufind/EDS.ini +++ b/config/vufind/EDS.ini @@ -222,6 +222,9 @@ enabled = true ; Define a default_handler default_handler = Eds +; Auto-submit autocomplete on click or enter +auto_submit = true + ; In this section, set the key equal to a search type from [Basic_Searches] and ; the value equal to an autocomplete handler in order to customize autocompletion ; behavior when that search type is selected. (default: Eds:rawqueries) diff --git a/config/vufind/FeedbackForms.yaml b/config/vufind/FeedbackForms.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f875cbe20050e989a83e0db0a30c9d6ea6575149 --- /dev/null +++ b/config/vufind/FeedbackForms.yaml @@ -0,0 +1,143 @@ +--- +# Listing of configured forms. +# +# Configured forms are listed in the top level 'forms' array and can accessed via the URL: +# /Feedback/Form/<form-id> +# +# The main Feedback form (id: FeedbackSite) can be accessed with a shorter URL /Feedback +# +# Form supports the following options: +# +# enabled (boolean) Is the form enabled? (default = true) +# useCaptcha (boolean) Should the form use Captcha validation? Requires the "feedback" +# option to be turned on in the config.ini [Captcha] form setting. +# (default = true, if Captcha turned on for feedback overall). +# title (string) Form title (translation key) +# onlyForLoggedUsers (boolean) Require the user to be logged in to see the form +# (default = false) +# emailSubject (string) Email subject (translation key). (default = email_subject +# value from config.ini [Feedback] section, or 'VuFind Feedback') +# The subject may contain placeholders (for example %%receiver%%) +# that are replaced with submitted form values. +# recipient +# name (string) Recipient name (default = recipient_name setting from config.ini +# [Feedback] section) +# email (string) Recipient email address (default = recipient_email setting from +# config.ini [Feedback] section) +# response (string) Reponse after form submit (translation key) +# senderInfoRequired (boolean) Require sender to fill out name and email fields +# +# help +# pre (string) Help text displayed at the beginning of the form (translation key). +# post (string) Help text displayed at the end of the form (translation key) +# +# Help texts may contain HTML-formatting. +# +# fields (array) List of form elements with the following options: +# +# name (string) Element name +# label (string) Element label (translation key) +# required (boolean) Is the element required? +# settings (array) HTML attributes as key-value pairs, for example: +# - [class, "custom-css-class another-class"] +# type (string) Element type (text|textarea|email|url|select) +# help (string) Element help text (translation key) +# +# And for select elements one of: +# +# options (array) List of select values (translation keys) +# +# or +# +# optionGroups (array) List of option groups with keys: +# label (string) Group label (translation key) +# options (array) List of select values (translation keys) +# +#----------------------------------------------------------------------------------- + +forms: + + # Main Feedback form + + FeedbackSite: + title: Send us your feedback! + enabled: true + useCaptcha: true + #recipient: + # name: Your Library + # email: feedback@myuniversity.edu + + onlyForLoggedUsers: false + #emailSubject: VuFind Feedback + response: Thank you for your feedback. + senderInfoRequired: false + + #help: + # pre: feedback_help_pre + # post: feedback_help_post + + fields: + - name: message + type: textarea + label: Comments + required: true + settings: + # help: message_help + + # Example for an acquisition request form + + AcquisitionRequest: + enabled: false + title: Acquisition Request + onlyForLoggedUsers: false + emailSubject: Acquisition Request + title: Acquisition Request, + response: Thank you for your feedback. + + recipient: + name: Your Library + email: feedback@myuniversity.edu + + help: + pre: acquisition_request_info_pre + post: acquisition_request_info_post + + fields: + - name: receiver + type: select + label: acquisition_request_receiver + required: true, + options: + - Feedback + - bar + + - name: receiver2 + type: select + label: acquisition_request_receiver + required: true, + optionGroups: + - label: Library 1 + options: + - Branch 1 + - Branch 2 + - Branch 3 + + - label: Library 2 + options: + - Branch 1 + - Branch 2 + + - name: title + type: text + label: Title + required: true + + - name: author + type: text + label: Author + required: true + + - name: format + type: text + label: Format + required: true diff --git a/config/vufind/Folio.ini b/config/vufind/Folio.ini new file mode 100644 index 0000000000000000000000000000000000000000..94dadbd80867a68b97d248d48ecff1e45945cb24 --- /dev/null +++ b/config/vufind/Folio.ini @@ -0,0 +1,4 @@ +[Folio] +base_url = https://localhost:9130 +username = diku_admin +password = admin diff --git a/config/vufind/KohaILSDI.ini b/config/vufind/KohaILSDI.ini index be92848d7a6ce906c2b40db7a7d470632b79bbf7..2d1bf660d6c0c14c53708ea736fd5f903b8b0f7a 100755 --- a/config/vufind/KohaILSDI.ini +++ b/config/vufind/KohaILSDI.ini @@ -46,7 +46,7 @@ defaultRequiredDate = 0:1:0 ; extraHoldFields - A colon-separated list used to display extra visible fields in the ; place holds form. Supported values are "comments", "requiredByDate" and ; "pickUpLocation" -; Note: As of the time of writing, eventhough ILSDI API docs have long declared +; Note: As of the time of writing, even though ILSDI API docs have long declared ; support for 'comments' and 'requiredByDate' options when placing holds, these ; features might not yet be implemented (nulling any input passed to the appropriate ; functions). Should you decide to use them in extraHoldFields, please check that data diff --git a/config/vufind/LibGuides.ini b/config/vufind/LibGuides.ini index 7259b38f9df73d078309134eaf4c4f4558fd27d3..9e91e418b0e02314acac90cdbca59e5939d49575 100644 --- a/config/vufind/LibGuides.ini +++ b/config/vufind/LibGuides.ini @@ -7,7 +7,10 @@ timeout = 30 iid = my-id ; API version to use (1 or 2) -version = 1 +version = 2 + +; Base URL for API +baseUrl = https://lgapi.libapps.com/widgets.php ; This section controls the result limit options for search results. default_limit ; sets the default number of results per page. limit_options is a comma-separated diff --git a/config/vufind/SierraRest.ini b/config/vufind/SierraRest.ini index c702bcb5dc39e1d5554d5367b5d2e0e15e8e4c58..4f0074fddbe7a3f3c537f9a5a2c65051be66a6c0 100644 --- a/config/vufind/SierraRest.ini +++ b/config/vufind/SierraRest.ini @@ -12,6 +12,9 @@ host = "https://sandbox.iii.com/iii/sierra-api" client_key = "something" ; Sierra API client secret client_secret = "very_secret" +; Sierra API version available (defaults to highest one required for full +; functionality in the driver) +;api_version = 5 ; Timeout for HTTP requests http_timeout = 30 ; Redirect URL entered in Sierra for the patron-specific authentication (does not diff --git a/config/vufind/config.ini b/config/vufind/config.ini index ceea0595542652d7661248d18305afe69b6806c6..32294490505fdd77754b3401b49744105e671dd9 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -145,7 +145,7 @@ allowSavedSearches = true ; features (such as display of hierarchies). nonJavascriptSupportEnabled = false ; Generator value to display in an HTML header <meta> tag: -generator = "VuFind 5.0.1" +generator = "VuFind 5.1.0" ; This section allows you to configure the mechanism used for storing user ; sessions. Available types: File, Memcache, Database. @@ -178,6 +178,9 @@ secure = false ; the browser from ever sending cookies over an unencrypted connection (i.e. ; before being redirected to HTTPS). Default is false. ;only_secure = true +; Whether to set cookies set by the server (apart from cart function) "HTTP only" so +; that they cannot be accessed by scripts. Default is true. +;http_only = false ; Set the domain used for cookies (sometimes useful for sharing the cookies across ; subdomains); by default, cookies will be restricted to the current hostname. ;domain = ".example.edu" @@ -335,7 +338,7 @@ title_level_holds_mode = "disabled" ;method = LDAP ;method = ILS method = Database -;method = AlmaDatabase +;method = AlmaDatabase ;method = Shibboleth ;method = SIP2 ;method = CAS @@ -355,6 +358,14 @@ method = Database ; hideLogin in the [Settings] section of NoILS.ini for an example. hideLogin = false +; When set to true, uses AJAX calls to annotate the account menu with +; notifications (overdue items, total fines, etc.) +enableAjax = true + +; When set to true, replicates the account menu as a drop-down next to the +; account link in the header. +enableDropdown = false + ; Set this to false if you would like to store local passwords in plain text ; (only applies when method = Database or AlmaDatabase above). hash_passwords = false @@ -407,7 +418,7 @@ ils_encryption_key = false ; Uncomment this line to switch on "privacy mode" in which no user information ; will be stored in the database. Note that this is incompatible with social ; features, password resets, and many other features. It is not recommended for -; use with "Database" or "AlmaDatabase" authentication, since the user will be +; use with "Database" or "AlmaDatabase" authentication, since the user will be ; forced to create a new account upon every login. ;privacy = true @@ -702,7 +713,8 @@ database = mysql://root@localhost/vufind ;coversize = false ; You can select Syndetics, LibraryThing, Summon, Amazon, Booksite, OpenLibrary, -; Contentcafe, Buchhandel.de, Google Books, and/or LocalFile. +; Contentcafe, Buchhandel.de, Google Books, BrowZine and/or LocalFile. +; Note: BrowZine requires you to have BrowZine.ini configured appropriately. ; Note: Summon service takes a Serials Solutions client key, NOT Summon API key! ; For LocalFile:PathToFile, you may use a combination of directory path information ; and tokens for filename and image type. If you have multiple directories @@ -721,7 +733,7 @@ database = mysql://root@localhost/vufind ; %vufind-home% - The VUFIND_HOME environment variable ; %vufind-local-dir% - The VUFIND_LOCAL_DIR environment variable ; Example: LocalFile:%vufind-local-dir%/path/to/file/%size%/issn/%issn%.%anyimage% -;coverimages = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,LocalFile:PathToFile +;coverimages = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,BrowZine,LocalFile:PathToFile ; This setting controls which services will have images cached on your local disk. ; Set to true to cache all applicable services. Set to false to disable caching. Set @@ -1012,14 +1024,28 @@ pw = "Password" ;[DPLA] ;apiKey = http://dp.la/info/developers/codex/policies/#get-a-key +; These settings affect dynamic DOI-based link inclusion; this can provide links +; to full text or contextual information. +[DOI] +; This setting controls whether or not DOI-based links are enabled, and which +; API is used to fetch the data. Currently supported options: BrowZine (requires +; credentials to be configured in BrowZine.ini) or false (to disable). Disabled +; by default. +;resolver = BrowZine + +; The following settings control where DOI-based links are displayed: +show_in_results = true ; include in search results +show_in_record = false ; include in core record metadata +show_in_holdings = false ; include in holdings tab of record view + ; These settings affect OpenURL generation and presentation; OpenURLs are used to ; help users find resources through your link resolver and to manage citations in ; Zotero. [OpenURL] -; If a resolver base URL is enabled, it will be used to link ISSNs to your link -; resolver and to access articles in Summon if that module is enabled. Earlier -; versions of VuFind included some parameters as part of the URL; at this point, -; any extra parameters will be ignored -- please provide only the base URL. +; If a resolver base URL is enabled, it will be used to link from records to your +; OpenURL resolver. An OpenURL resolver is typically used to e.g. link to full text +; from article metadata, but it may provide other services too. Extra parameters may +; be added if necessary. ;url = "http://openurl.myuniversity.edu/sfx_local" ; This string will be included as part of your OpenURL referer ID (the full string @@ -1031,7 +1057,7 @@ rfr_id = vufind.svn.sourceforge.net ; By specifying your link resolver type, you can allow VuFind to optimize its ; OpenURLs for a particular platform. Current legal values: "sfx", "360link", -; "EZB", "Redi," "demo" or "other" (default is "other" if commented out; "demo" +; "EZB", "Redi," "demo" or "generic" (default is "generic" if commented out; "demo" ; generates fake values for use in testing the embed setting below). ;resolver = sfx @@ -1152,6 +1178,11 @@ url = https://www.myendnoteweb.com/EndNoteWeb.html ; you use both set_field and set_query, be careful about the names you choose ; for your set queries. set_query names will trump set_field values when ; there are collisions. +; +; If vufind_api_format_fields is set, the listed fields (as defined in +; SearchApiRecordFields.yaml) are returned when metadata prefix +; "oai_vufind_json" is used. +; ;[OAI] ;identifier = myuniversity.edu ;repository_name = "MyUniversity Catalog" @@ -1159,6 +1190,7 @@ url = https://www.myendnoteweb.com/EndNoteWeb.html ;set_field = "format" ;set_query['eod_books'] = "institution:kfu AND publishDate:[1911 TO 1911]" ;set_query['eod_ebooks'] = "format:eBook" +;vufind_api_format_fields = "id,authors,cleanIsbn,cleanIssn,formats,title" ; Proxy Server is Optional. [Proxy] @@ -1318,6 +1350,7 @@ sl = "Slovene" ar = "Arabic" bn = "Bengali" gl = "Galician" +vi = "Vietnamese" ; This section contains special cases for languages such as right-to-left support [LanguageSettings] @@ -1581,11 +1614,16 @@ treeSearchLimit = 100 ; This section will be used to configure the feedback module. ; Set "tab_enabled" to true in order to enable the feedback module. +; Forms are configured in FeedbackForms.yaml [Feedback] ;tab_enabled = true + +; Default values for form recipient and email subject, if not overridden for a +; specific form in FeedbackForms.yaml ;recipient_email = "feedback@myuniversity.edu" ;recipient_name = "Your Library" ;email_subject = "VuFind Feedback" + ; This is the information for where feedback emails are sent from. ;sender_email = "noreply@vufind.org" ;sender_name = "VuFind Feedback" @@ -1671,8 +1709,11 @@ treeSearchLimit = 100 ;secretKey = "https://www.google.com/recaptcha/admin/create" ; Valid theme values: dark, light ;theme = light -; Valid forms values: changePassword, email, feedback, newAccount, passwordRecovery, sms, userComments +; Valid forms values: changePassword, email, feedback, newAccount, passwordRecovery, +; sms, userComments ; Use * for all supported forms +; Note: when "feedback" is active, Captcha can be conditionally disabled on a +; form-by-form basis with the useCaptcha setting in FeedbackForms.yaml. ;forms = changePassword, email, newAccount, passwordRecovery, sms diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini index 447696c215c76b37612d55384f54bc7525b00e90..ff183ddf4e980e2442a726c393a66b597678c29c 100644 --- a/config/vufind/searches.ini +++ b/config/vufind/searches.ini @@ -56,6 +56,10 @@ default_top_recommend[] = TopFacets:ResultsTop default_top_recommend[] = SpellingSuggestions ;default_top_recommend[] = VisualFacets:Visual_Settings default_side_recommend[] = SideFacets:Results:CheckboxFacets +; SideFacetsDeferred is an alternative to SideFacets. Using it will defer loading of +; any facet until it's actually displayed. This can improve search performance and +; decrease server load especially with larger indexes. +;default_side_recommend[] = SideFacetsDeferred:Results:CheckboxFacets ;default_noresults_recommend[] = SwitchTab default_noresults_recommend[] = SwitchType default_noresults_recommend[] = SwitchQuery:::fuzzy @@ -337,9 +341,9 @@ CallNumber = callnumber-sort ; Display a link to the Channeled Browse functionality leading to channels of ; records related to the current search. ; MapSelection -; Enable geographic searching capability by activating this module. -; Records must be indexed using the geographic search and display fields. -; See the marc_local.properties file for more information on indexing. +; Enable geographic searching capability by activating this module. +; Records must be indexed using the geographic search and display fields. +; See the marc_local.properties file for more information on indexing. ; See the [MapSelection] section of the geofeatures.ini file for more information. ; PubDateVisAjax:[zooming]:[facet field 1]:[facet field 2]:...:[facet field n] ; Display a visualization of publication dates for each of the specified facet @@ -502,6 +506,8 @@ sort = "last_indexed desc" enabled = true ; This handler will be used for all search types not covered by [Autocomplete_Types] default_handler = Solr +; Auto-submit autocomplete on click or enter +auto_submit = true ; In this section, set the key equal to a search handler from searchspecs.yaml and ; the value equal to an autocomplete handler in order to customize autocompletion @@ -631,7 +637,7 @@ view=full ; This section defines the default parameters for the geographic search ; functionality found in the MapSelection recommendation module. ; To enable this feature, uncomment the default_top_recommend[] = MapSelection -; in the default recommendations section. To set the configuration settings +; in the default recommendations section. To set the configuration settings ; for this feature, adjust the parameters in the geofeatures.ini file. [MapSelection] ; These configuration settings have been superseded by the geofeatures.ini file. diff --git a/config/vufind/sitemap.ini b/config/vufind/sitemap.ini index 9b9782327c220079ae9ec111ac92b0cb8d77381c..27dc2e4f67a7337d71be4cfde65f65c425d50090 100644 --- a/config/vufind/sitemap.ini +++ b/config/vufind/sitemap.ini @@ -43,11 +43,11 @@ fileLocation = /tmp index[] = "Solr,/Record/" ;index[] = "SolrAuth,/Authority/Record?id=" -; This setting controls how IDs are retrieved from the index. It may be 'terms' -; (the default, and the faster option) to use the terms component, or 'search' -; to retrieve results using a normal search (which is useful if you need to -; apply hidden filters to your results, or if you do not have terms enabled). -retrievalMode = terms +; This setting controls how IDs are retrieved from the index. It may be +; 'search' (the default, most compatible but slower method), or 'terms' (the +; faster option). Note that 'terms' method does not support hidden filters or +; other limiting options and requires that the index has terms enabled. +retrievalMode = search ; The SitemapIndex Section contains settings affecting the generation of ; a sitemap index file which groups multiple sitemap files. The sitemap diff --git a/harvest/batch-delete.sh b/harvest/batch-delete.sh index f2c5b05a3192d61c9c9017fba75d218b3f2ab493..f517ac498ad6005c6b199c79ca8aec820c02ef96 100755 --- a/harvest/batch-delete.sh +++ b/harvest/batch-delete.sh @@ -3,8 +3,13 @@ # Make sure VUFIND_HOME is set: if [ -z "$VUFIND_HOME" ] then - echo "Please set the VUFIND_HOME environment variable." - exit 1 + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)"/.. + if [ "$VUFIND_HOME" = /.. ] + then + exit 1 + fi fi SKIP_OPTIMIZE=0 diff --git a/harvest/batch-import-marc-auth.sh b/harvest/batch-import-marc-auth.sh index 40bae23a7f3cb584a70493a5011b33ad66242a45..8b676bcf0d70acb6f155357139efcaface6f41a2 100755 --- a/harvest/batch-import-marc-auth.sh +++ b/harvest/batch-import-marc-auth.sh @@ -3,8 +3,13 @@ # Make sure VUFIND_HOME is set: if [ -z "$VUFIND_HOME" ] then - echo "Please set the VUFIND_HOME environment variable." - exit 1 + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + export VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)"/.. + if [ "$VUFIND_HOME" = /.. ] + then + exit 1 + fi fi # Find harvest directory for future use diff --git a/harvest/batch-import-marc.sh b/harvest/batch-import-marc.sh index e026e110ff63733cf0949c61408614c14bd6993e..6c76c4a71927b7d615afbcf6bf7c5317c258f675 100755 --- a/harvest/batch-import-marc.sh +++ b/harvest/batch-import-marc.sh @@ -3,8 +3,13 @@ # Make sure VUFIND_HOME is set: if [ -z "$VUFIND_HOME" ] then - echo "Please set the VUFIND_HOME environment variable." - exit 1 + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + export VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)"/.. + if [ "$VUFIND_HOME" = /.. ] + then + exit 1 + fi fi # Find harvest directory for future use diff --git a/harvest/batch-import-xsl.sh b/harvest/batch-import-xsl.sh index 00e26cb9a2da85afe58d350e016d5df429f0952c..d433e1bfe25df89f5fb7b9c855518318306a4b08 100755 --- a/harvest/batch-import-xsl.sh +++ b/harvest/batch-import-xsl.sh @@ -3,10 +3,16 @@ # Make sure VUFIND_HOME is set: if [ -z "$VUFIND_HOME" ] then - echo "Please set the VUFIND_HOME environment variable." - exit 1 + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)"/.. + if [ "$VUFIND_HOME" = /.. ] + then + exit 1 + fi fi + SKIP_OPTIMIZE=0 while getopts ":s" OPT diff --git a/import-marc-auth.bat b/import-marc-auth.bat index bcef07eb90b4bc81267465b5dc99d4e0ce3c9c3f..e6b0004ac1e8113a8329c373b4346fce7dda9868 100644 --- a/import-marc-auth.bat +++ b/import-marc-auth.bat @@ -9,7 +9,7 @@ goto end rem Make sure we know where the VuFind home directory lives: if not "!%VUFIND_HOME%!"=="!!" goto vufindhomefound -rem VUFIND_HOME not set -- try to call env.bat to +rem VUFIND_HOME not set -- try to call env.bat to rem fix the problem before we give up completely if exist env.bat goto useenvbat rem If env.bat doesn't exist, the user hasn't run the installer yet. @@ -23,22 +23,6 @@ echo You need to set the VUFIND_HOME environmental variable before running this goto end :vufindhomefound -rem Always use the standard authority mappings; if the user specified an override -rem file, add that to the setting. -if not exist %VUFIND_LOCAL_DIR%\import\marc_auth.properties goto nolocalmappings -set MAPPINGS_FILE=%VUFIND_LOCAL_DIR%\import\marc_auth.properties -goto mappingsset -:nolocalmappings -set MAPPINGS_FILE=%VUFIND_HOME%\import\marc_auth.properties -:mappingsset -if "!%2!"=="!!" goto noextramappings -if not exist %VUFIND_LOCAL_DIR%\import\%2 goto nolocalextramappings -set MAPPINGS_FILE=%MAPPINGS_FILE%,%VUFIND_LOCAL_DIR%\import\%2 -goto noextramappings -:nolocalextramappings -set MAPPINGS_FILE=%MAPPINGS_FILE%,%VUFIND_HOME%\import\%2 -:noextramappings - rem Override some settings in the standard import script: if not exist %VUFIND_LOCAL_DIR%\import\import_auth.properties goto nolocalproperties set PROPERTIES_FILE=%VUFIND_LOCAL_DIR%\import\import_auth.properties @@ -47,10 +31,31 @@ goto propertiesfound set PROPERTIES_FILE=%VUFIND_HOME%\import\import_auth.properties :propertiesfound +rem Always use the authority mappings from PROPERTIES_FILE +rem if the user specified an override file, add that to the setting. +set MAPPINGS_FILENAMES="" +for /f "delims=" %%a in ('findstr "^solr.indexer.properties" %PROPERTIES_FILE%') do set MAPPINGS_FILENAMES=%%a +set MAPPINGS_FILENAMES="%MAPPINGS_FILENAMES:solr.indexer.properties=%" +if not "%2"=="" set MAPPINGS_FILENAMES=%MAPPINGS_FILENAMES%,%2 +set MAPPINGS_FILENAMES=%MAPPINGS_FILENAMES:"=% + +setlocal EnableDelayedExpansion +set MAPPINGS_FILES="" +for %%a in (%MAPPINGS_FILENAMES%) do ( + if not !MAPPINGS_FILES!=="" set MAPPINGS_FILES=!MAPPINGS_FILES!, + if exist %VUFIND_LOCAL_DIR%\import\%%a ( + set MAPPINGS_FILES=!MAPPINGS_FILES!%VUFIND_LOCAL_DIR%\import\%%a + ) else ( + set MAPPINGS_FILES=!MAPPINGS_FILES!%VUFIND_HOME%\import\%%a + ) +) +set MAPPINGS_FILES=%MAPPINGS_FILES:~2,99999% +setlocal DisableDelayedExpansion + set SOLRCORE="authority" -set EXTRA_SOLRMARC_SETTINGS="-Dsolr.indexer.properties=%MAPPINGS_FILE%" +set EXTRA_SOLRMARC_SETTINGS="-Dsolr.indexer.properties=%MAPPINGS_FILES%" rem Call the standard script: call %VUFIND_HOME%\import-marc.bat %1 -:end \ No newline at end of file +:end diff --git a/import-marc-auth.sh b/import-marc-auth.sh index 9ca73e68dd93ca56e0ad908b76289f81fdab0a47..d543d17c621dcf3d048c58e7ffb835141e9a15c8 100755 --- a/import-marc-auth.sh +++ b/import-marc-auth.sh @@ -12,21 +12,17 @@ then exit $E_BADARGS fi -# Always use the standard authority mappings; if the user specified an override -# file, add that to the setting. -if [ -f "$VUFIND_LOCAL_DIR/import/marc_auth.properties" ] +################################################## +# Set VUFIND_HOME +################################################## +if [ -z "$VUFIND_HOME" ] then - MAPPINGS_FILE="$VUFIND_LOCAL_DIR/import/marc_auth.properties" -else - MAPPINGS_FILE="$VUFIND_HOME/import/marc_auth.properties" -fi -if [ $# -gt 1 ] -then - if [ -f "$VUFIND_LOCAL_DIR/import/$2" ] + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + export VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)" + if [ -z "$VUFIND_HOME" ] then - MAPPINGS_FILE="$MAPPINGS_FILE,$VUFIND_LOCAL_DIR/import/$2" - else - MAPPINGS_FILE="$MAPPINGS_FILE,$VUFIND_HOME/import/$2" + exit 1 fi fi @@ -37,8 +33,31 @@ then else export PROPERTIES_FILE="$VUFIND_HOME/import/import_auth.properties" fi + +# Always use the authority mappings from PROPERTIES_FILE +# if the user specified an override file, add that to the setting. +MAPPINGS_FILENAMES=($(sed --quiet --expression='s/^\(solr.indexer.properties\s*=\s*\)\(.*\)/\2/p' $PROPERTIES_FILE | tr "," " ")) +if [ $# -gt 1 ] +then + MAPPINGS_FILENAMES+=($2) +fi + +MAPPINGS_FILES="" +for MAPPINGS_FILENAME in ${MAPPINGS_FILENAMES[@]}; do + if [ -n "$MAPPINGS_FILES" ]; then + MAPPINGS_FILES+="," + fi + + if [ -f "$VUFIND_LOCAL_DIR/import/$MAPPINGS_FILENAME" ] + then + MAPPINGS_FILES+="$VUFIND_LOCAL_DIR/import/$MAPPINGS_FILENAME" + else + MAPPINGS_FILES+="$VUFIND_HOME/import/$MAPPINGS_FILENAME" + fi +done + export SOLRCORE="authority" -export EXTRA_SOLRMARC_SETTINGS="-Dsolr.indexer.properties=$MAPPINGS_FILE" +export EXTRA_SOLRMARC_SETTINGS="-Dsolr.indexer.properties=$MAPPINGS_FILES" # Call the standard script: -$VUFIND_HOME/import-marc.sh $1 \ No newline at end of file +$VUFIND_HOME/import-marc.sh $1 diff --git a/import-marc.sh b/import-marc.sh index 82e8d1b26cc388e91b1a1a5da4a394fb0b0ca34f..4965ca45b33e47393fe7b31440a8e8f4e98738c7 100755 --- a/import-marc.sh +++ b/import-marc.sh @@ -67,7 +67,11 @@ if [ -z "$VUFIND_HOME" ] then # set VUFIND_HOME to the absolute path of the directory containing this script # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself - export VUFIND_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" + export VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)" + if [ -z "$VUFIND_HOME" ] + then + exit 1 + fi fi if [ -z "$VUFIND_LOCAL_DIR" ] diff --git a/import/bin/import.sh b/import/bin/import.sh index 26f58baadbcb8ff23cc11f6d8d0c6de9136f72b7..afb93bd0bb1e1c3b19ea2010aa81f67afd74d1da 100644 --- a/import/bin/import.sh +++ b/import/bin/import.sh @@ -43,20 +43,29 @@ fi ################################################## -# Set SOLR_HOME +# Set VUFIND_HOME ################################################## -if [ -z "$SOLR_HOME" ] +if [ -z "$VUFIND_HOME" ] then - if [ -z "$VUFIND_HOME" ] + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)"/../.. + if [ "$VUFIND_HOME" = /../.. ] then - echo "You need to set the VUFIND_HOME environmental variable before running this script." exit 1 - else - SOLR_HOME="$VUFIND_HOME/solr" fi fi +################################################## +# Set SOLR_HOME +################################################## +if [ -z "$SOLR_HOME" ] +then + SOLR_HOME="$VUFIND_HOME/solr" +fi + + ################################################## # Set SOLRMARC_HOME ################################################## diff --git a/import/browse-indexing.jar b/import/browse-indexing.jar index 1d403fa2b75d3c07781b5eac4eec46e9c2c6070f..33c3cc8c7314035197f020b4cf26659c4b3476e5 100644 Binary files a/import/browse-indexing.jar and b/import/browse-indexing.jar differ diff --git a/import/dspace-dim.properties b/import/dspace-dim.properties new file mode 100644 index 0000000000000000000000000000000000000000..e9e9e2a257cc7c246d52c2e79830e27caad0cc5b --- /dev/null +++ b/import/dspace-dim.properties @@ -0,0 +1,30 @@ +; XSLT Import Settings for DSpace (using DIM metadata) +[General] +; REQUIRED: Name of XSLT file to apply. Path is relative to the import/xsl directory +; of the VuFind installation (or your local override directory). +xslt = dspace-dim.xsl +; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat +; this line to register multiple PHP functions. +;php_function[] = str_replace +; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. +; The class must live within a PHP namespace. You may specify a fully-qualified +; name; if you do not include a namespace, the class will automatically be assumed +; to live in the \VuFind\XSLT\Import namespace. +custom_class[] = VuFind +; OPTIONAL: If true, all custom_class settings above will be passed to the XSLT with +; their namespaces stripped off; for example, \VuFind\XSLT\Import\VuFind would be +; treated as \VuFind in XSLT files. This allows more compact syntax within XSLT +; files, but it can lead to name conflicts if used carelessly. If set to false, you +; must use fully-qualified names in your XSLT. The false setting is recommended, but +; the current default is "true" for compatibility with legacy configurations. +truncate_custom_class = true + +; XSLT parameters -- any key/value pairs set here will be passed as parameters to +; the XSLT file, allowing local values to be set without modifying XSLT code. +[Parameters] +institution = "My University" +collection = "DSpace" +; By default, any URL beginning with "http" will be indexed; however, you can +; specify a more narrow prefix here if you wish to filter to a particular subset +; of URLs indexed into VuFind. +;urlPrefix = "http://hdl.handle.net" diff --git a/import/index_java/src/org/vufind/index/GeoTools.java b/import/index_java/src/org/vufind/index/GeoTools.java index db00d3975830ecf50339de207ea75d72d90763f7..4d9a33b4977e662fb42b7acd0b2a3d39466eb99a 100644 --- a/import/index_java/src/org/vufind/index/GeoTools.java +++ b/import/index_java/src/org/vufind/index/GeoTools.java @@ -167,7 +167,7 @@ public class GeoTools out.println(logFilename + "\t" + recNum + "\t" + msgError + "\t" + coordinates); out.close(); } catch (IOException e) { - System.out.println("io exception occured"); + System.out.println("io exception occurred"); e.printStackTrace(); } } else { diff --git a/import/lib/classgraph-4.1.6.jar b/import/lib/classgraph-4.1.6.jar new file mode 100644 index 0000000000000000000000000000000000000000..a0788bc1b2d882cd446e304b5ad1843ed221e802 Binary files /dev/null and b/import/lib/classgraph-4.1.6.jar differ diff --git a/import/lib/fast-classpath-scanner-1.91.4.jar b/import/lib/fast-classpath-scanner-1.91.4.jar deleted file mode 100644 index 45684e86863d56f8b30e04247c6a63372b4e4a12..0000000000000000000000000000000000000000 Binary files a/import/lib/fast-classpath-scanner-1.91.4.jar and /dev/null differ diff --git a/import/solrmarc_core_3.1.jar b/import/solrmarc_core_3.2.jar similarity index 63% rename from import/solrmarc_core_3.1.jar rename to import/solrmarc_core_3.2.jar index c161a970f447a1c607db1a943bf793ff71acfed7..57a4769999664fb277dadefef5235c877ab42a73 100644 Binary files a/import/solrmarc_core_3.1.jar and b/import/solrmarc_core_3.2.jar differ diff --git a/import/xsl/dspace-dim.xsl b/import/xsl/dspace-dim.xsl new file mode 100644 index 0000000000000000000000000000000000000000..530f49e6a7a4a6ce8d91b438064b37586a374537 --- /dev/null +++ b/import/xsl/dspace-dim.xsl @@ -0,0 +1,264 @@ +<!-- available fields are defined in solr/biblio/conf/schema.xml --> +<!-- This document was written for Biblioteca Brasiliana Guita e José Mindlin + by Fabio Chagas da Silva (fabio.chagas.silva@usp.br, GitHub: @fabio-stdio). + It takes metadata directly from dim to index in Solr. It is based on dspace.xsl. + + The choices of fields were made based on which metadata is most interesting + for the user of the library and which Solr fields in schema.xml are close to + the metadata of choice. Those choices were made supervised by the librarian + of Brasiliana Guita e José Mindlin, Rodrigo Garcia (garcia.rodrigo@gmail.com). + + Additional fields (and significant adjustments) were added based on the work + of Roland Keck. +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" + xmlns:php="http://php.net/xsl" + xmlns:xlink="http://www.w3.org/2001/XMLSchema-instance"> + <xsl:output method="xml" indent="yes" encoding="utf-8"/> + <xsl:param name="institution">My University</xsl:param> + <xsl:param name="collection">DSpace</xsl:param> + <xsl:template match="dim:dim"> + <add> + <doc> + <!-- Those fields are treated the same as in dspace.xsl, except + for the tags + --> + + <!-- ID --> + <!-- Important: This relies on an <identifier> tag being injected + by the OAI-PMH harvester. + --> + <field name="id"> + <xsl:value-of select="//identifier"/> + </field> + + <!-- RECORDTYPE --> + <field name="recordtype">dspace</field> + + <!-- ALLFIELDS --> + <xsl:for-each select="//dim:field"> + <xsl:if test="string-length(.) > 0"> + <field name="allfields"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:if> + </xsl:for-each> + + <!-- INSTITUTION --> + <field name="institution"> + <xsl:value-of select="$institution" /> + </field> + + <!-- COLLECTION --> + <field name="collection"> + <xsl:value-of select="$collection" /> + </field> + + <!-- TITLE --> + <xsl:if test= "//dim:field[@element='title']"> + <field name="title"> + <xsl:value-of select="//dim:field[@element='title']"/> + </field> + <field name="title_short"> + <xsl:value-of select="//dim:field[@element='title']"/> + </field> + <field name="title_full"> + <xsl:value-of select="//dim:field[@element='title']"/> + </field> + <field name="title_sort"> + <xsl:value-of select="php:function('VuFind::stripArticles', string(//dim:field[@element='title'][normalize-space()]))"/> + </field> + </xsl:if> + + <!-- AUTHOR --> + <xsl:if test="//dim:field[@element='contributor' and @qualifier='author']"> + <xsl:for-each select="//dim:field[@element='contributor' and @qualifier='author']"> + <field name="author"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- CO AUTHOR --> + <xsl:if test="//dim:field[@element='contributor' and @qualifier='other']"> + <xsl:for-each select="//dim:field[@element='contributor' and @qualifier='other']"> + <field name="author2"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- EDITOR (treated as corporate author as per Roland Keck's example; + this may vary by institution. + --> + <xsl:if test="//dim:field[@element='contributor' and @qualifier='editor']"> + <xsl:for-each select="//dim:field[@element='contributor' and @qualifier='editor']"> + <field name="author_corporate"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- SUBJECT --> + <xsl:if test="//dim:field[@element='subject']"> + <xsl:for-each select="//dim:field[@element='subject']"> + <field name="topic"> + <xsl:value-of select="normalize-space(.)"/> + </field> + <field name="topic_facet"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- Published Date --> + <xsl:if test="//dim:field[@element='date' and @qualifier='issued']"> + <field name="publishDate"> + <xsl:value-of select="//dim:field[@element='date' and @qualifier='issued']"/> + </field> + <field name="publishDateSort"> + <xsl:value-of select="substring(//dim:field[@element='date' and @qualifier='issued'], 1, 4)" /> + </field> + </xsl:if> + + <!-- Language --> + <xsl:if test="//dim:field[@element='language' and @qualifier='iso']"> + <field name="language"> + <xsl:value-of select="php:function('VuFind::mapString', normalize-space(string(//dim:field[@element='language' and @qualifier='iso'])), 'language_map_iso639-1.properties')"/> + </field> + </xsl:if> + + <!-- Relation --> + <xsl:if test="//dim:field[@element='relation' and @qualifier = 'ispartof']"> + <field name="container_title"> + <xsl:value-of select="normalize-space(//dim:field[@element='relation' and @qualifier = 'ispartof'])"/> + </field> + </xsl:if> + <xsl:if test="//dim:field[@element='relation' and @qualifier = 'ispartofvolume']"> + <field name="container_volume"> + <xsl:value-of select="normalize-space(//dim:field[@element='relation' and @qualifier = 'ispartofvolume'])"/> + </field> + </xsl:if> + + <!-- Publisher --> + <xsl:if test="//dim:field[@element='publisher']"> + <field name="publisher"> + <xsl:value-of select="//dim:field[@element='publisher']"/> + </field> + </xsl:if> + + <!-- Extent --> + <xsl:if test="//dim:field[@element='format' and @qualifier='extent']"> + <field name="physical"> + <xsl:value-of select="//dim:field[@element='format' and @qualifier='extent']"/> + </field> + </xsl:if> + + <!-- Format --> + <xsl:if test="//dim:field[@element='format' and @qualifier='medium']"> + <field name="format"> + <xsl:value-of select="//dim:field[@element='format' and @qualifier='medium']"/> + </field> + </xsl:if> + + <!-- Type --> + <xsl:if test="//dim:field[@element='type']"> + <field name="format"> + <xsl:value-of select="//dim:field[@element='type']"/> + </field> + </xsl:if> + + <!-- Alternative Title --> + <xsl:if test="//dim:field[@element='title' and @qualifier='alternative']"> + <xsl:for-each select="//dim:field[@element='title' and @qualifier='alternative']"> + <field name="title_alt"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- Description --> + <!-- Two if blocks are used in description, one to check its + existence and another, within the for-each loop to not print + a dim:field[@element='description' and @qualifier='provenance']. + + Although, the field with only attribute @element='description' + doesn't print, an inelegant solution was found and implemented + + A text tag is included for the new line character after + printing the value in the field with the attribute + @element='description' only. + + Within the for-each loop was included (as mentioned earlier) + an if block. After printing all values with descriptions, + except for description and provenance, concatenate with new + line character. + --> + <xsl:if test="//dim:field[@element='description' and @qualifier='abstract']"> + <field name="description"> + <xsl:for-each select="//dim:field[@element='description' and @qualifier='abstract']"> + <xsl:value-of select="concat(., '
')"/> + </xsl:for-each> + </field> + </xsl:if> + + <xsl:if test="//dim:field[@element='description' and @qualifier='edition']"> + <field name="edition"> + <xsl:value-of select="normalize-space(//dim:field[@element='description' and @qualifier='edition'])"/> + </field> + </xsl:if> + + <!-- Volume (dc.relation.requires) --> + <xsl:if test="//dim:field[@element='relation' and @qualifier='requires']"> + <field name="container_volume"> + <xsl:value-of select="//dim:field[@element='relation' and @qualifier='requires']"/> + </field> + </xsl:if> + + <!-- Table of contents --> + <xsl:if test="//dim:field[@element='description' and @qualifier='tableofcontents']"> + <field name="contents"> + <xsl:value-of select="//dim:field[@element='description' and @qualifier='tableofcontents']"/> + </field> + </xsl:if> + + <!-- Spatial --> + <xsl:if test="//dim:field[@qualifier='spatial']"> + <xsl:for-each select="//dim:field[@qualifier='spatial']"> + <field name="geographic_facet"> + <xsl:value-of select="normalize-space(.)"/> + </field> + </xsl:for-each> + </xsl:if> + + <!-- ISBN --> + <xsl:if test="//dim:field[@qualifier='isbn']"> + <field name="isbn"> + <xsl:value-of select="//dim:field[@qualifier='isbn']"/> + </field> + </xsl:if> + + <!-- ISSN --> + <xsl:if test="//dim:field[@qualifier='issn']"> + <field name="issn"> + <xsl:value-of select="//dim:field[@qualifier='issn']"/> + </field> + </xsl:if> + + <!-- URL --> + <xsl:for-each select="//dim:field[@element='identifier']"> + <xsl:if test="string-length(.) > 0"> + <xsl:if test="@qualifier = 'uri'"> + <field name="url"> + <xsl:value-of select="normalize-space(.)" /> + </field> + </xsl:if> + </xsl:if> + </xsl:for-each> + </doc> + </add> + </xsl:template> +</xsl:stylesheet> diff --git a/index-alphabetic-browse.sh b/index-alphabetic-browse.sh index 928c7109e277e97e1f0e094292009174bc110f39..50d4b44fea12ae2f9ae9ec165c0a055736881924 100755 --- a/index-alphabetic-browse.sh +++ b/index-alphabetic-browse.sh @@ -10,11 +10,22 @@ else JAVA="java" fi + +################################################## +# Set VUFIND_HOME +################################################## if [ -z "$VUFIND_HOME" ] then - VUFIND_HOME=`dirname $0` + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)" + if [ -z "$VUFIND_HOME" ] + then + exit 1 + fi fi + if [ -z "$SOLR_HOME" ] then SOLR_HOME="$VUFIND_HOME/solr/vufind" diff --git a/install.php b/install.php index d2462409d80f79f6710fd6549d7d3761f3eec52c..7cb9b514050c07ff24298887c9945424e4442f2a 100644 --- a/install.php +++ b/install.php @@ -50,7 +50,7 @@ try { 'module-name=s' => 'What module name would you like to use? Use disabled, to not use', 'basepath=s' => - 'What base path should be used in VuFind\'s URL? [/vufind]', + "What base path should be used in VuFind's URL? [{$basePath}]", 'multisite-w' => 'Specify we are going to setup a multisite. Options: directory and host', 'hostname=s' => diff --git a/languages/CallNumberFirst/vi.ini b/languages/CallNumberFirst/vi.ini new file mode 100644 index 0000000000000000000000000000000000000000..8e3784d8622414d330ef4e921308a268febf8c1e --- /dev/null +++ b/languages/CallNumberFirst/vi.ini @@ -0,0 +1,21 @@ +A - General Works = "A - Công việc chung" +B - Philosophy, Psychology, Religion = "B - Triết há»c, Tâm lý há»c, Tôn giáo" +C - Historical Sciences = "C - Lịch sá» khoa há»c" +D - World History = "D - Lịch sá» thế giá»›i" +E - United States History = "E - Lịch sá» nÆ°á»›c Mỹ" +F - General American History = "F - Lịch sá» chung của Mỹ" +G - Geography, Anthropology, Recreation = "G - Äịa lý, Nhân loại há»c, Giải trÃ" +H - Social Science = "H - Khoa há»c xã há»™i" +J - Political Science = "J - ChÃnh sách khoa há»c" +K - Law = "K - Pháp luáºt" +L - Education = "L - Giáo dục" +M - Music = "M - Âm nhạc" +N - Fine Arts = "N - Mỹ thuáºt" +P - Language and Literature = "P - Ngôn ngữ và văn há»c" +Q - Science = "Q - Khoa há»c" +R - Medicine = "R - Y há»c" +S - Agriculture = "S - Nông nghiệp" +T - Technology = "T - Công nghệ" +U - Military Science = "U - Khoa há»c quân sá»±" +V - Naval Science = "V - Khoa há»c hải quân" +Z - Library Science = "Z - ThÆ° viện khoa há»c" diff --git a/languages/CreatorRoles/vi.ini b/languages/CreatorRoles/vi.ini new file mode 100644 index 0000000000000000000000000000000000000000..ef9a2a45fe5bd5a6b61ce021f24dc96d3bbdfa82 --- /dev/null +++ b/languages/CreatorRoles/vi.ini @@ -0,0 +1,356 @@ +; This file includes translations for author relator terms/abbreviations of the following standards: +; * MARC Code List for Relators (http://www.loc.gov/marc/relators/relacode.html) +; including discontinued codes: clb, grt, voc +; * German RAK Code List (recommended) for Relators +; * German RAK Code List for Relators extended by HBZ +; * German RAK Code List for Relators extended by GBV +; * German RAK Code List for Relators extended by SWB +; (http://swbtools.bsz-bw.de/cgi-bin/help.pl?cmd=kat&val=3010) +; Note: In some cases, terms are case sensitive, and case determines meaning; +; for example, see Beiträger vs. beiträger. +abr = "NgÆ°á»i tóm tắt" +acp = "Biên kịch nghệ thuáºt" +act = "Diá»…n viên" +adi = "Giám đốc nghệ thuáºt" +adp = "NgÆ°á»i phá»ng theo" +Adressat = "NgÆ°á»i nháºn" +adressat = "NgÆ°á»i nháºn" +aft = "Tác giả của lá»i kết, lá»i ghi cuối sách, v.v." +angebl hrsg = "Nhà xuất bản không đáng tin cáºy" +angebl komp = "Tác giả / nhà soạn nhạc không đáng tin cáºy" +Angebl Verf = "Tác giả không đáng tin cáºy" +angebl verf = "Tác giả không đáng tin cáºy" +angebl übers = "Dịch giả không đáng tin cáºy" +animation = "Hoạt hình" +anl = "Chuyên viên phân tÃch" +anm = "Há»a sÄ© phim hoạt hình" +ann = "NgÆ°á»i chú thÃch" +ant = "ThÆ° mục tiá»n Ä‘á»" +ape = "Bên bị kháng cáo" +apl = "Bên kháng cáo" +app = "Nguyên cáo" +aqt = "Tác giả trong trÃch dẫn hoặc tóm tắt văn bản" +arc = "Kiến trúc sÆ°" +ard = "Giám đốc nghệ thuáºt" +arr = "NgÆ°á»i cải biên" +art = "Nghệ sÄ©" +asg = "NgÆ°á»i được uá»· nhiệm" +asn = "Tên liên kết" +ato = "NgÆ°á»i viết bản thảo" +att = "Tên được phân bổ" +auc = "NgÆ°á»i đấu giá" +aud = "Tác giả của há»™p thoại" +Auftraggeber = "Máy khách" +aui = "Tác giả giá»›i thiệu, v.v." +aus = "Biên kịch" +aut = "Tác giả" +bdd = "Thiết kế đóng sách" +Bearb = "Biên táºp viên" +bearb = "Biên táºp viên" +Begr = "Nhà tà i trợ" +begr = "Nhà tà i trợ" +Beiträger = "NgÆ°á»i cộng sÆ°Ì£" +beiträger = "NgÆ°á»i cộng sÆ°Ì£ văn há»c" +beiträger k = "NgÆ°á»i cộng sÆ°Ì£ nghệ thuáºt" +beiträger m = "NgÆ°á»i cộng sÆ°Ì£ âm nhạc" +bjd = "Nhà thiết kế kìa sách" +bkd = "Nhà thiết kế sách" +bkp = "Nhà thiết kế sách" +blw = "NgÆ°á»i viết lá»i giá»›i thiệu sách" +bnd = "NgÆ°á»i đóng sách" +bpd = "Nhà thiết kế Bookplate" +brd = "Broadcaster" +brl = "Chữ nổi Braille" +bsl = "NgÆ°á»i bán sách" +bühnenbild = "Äặt nhà thiết kế" +cas = "Caster" +ccp = "Khái niệm" +choreinstud = "Diá»…n táºp hợp xÆ°á»›ng" +choreogr = "Biên đạo múa" +chr = "Biên đạo múa" +clb = "Cá»™ng tác viên" +cli = "Client" +cll = "ThÆ° pháp" +clr = "Chuyên gia chỉnh mà u" +clt = "Collotyper" +cmm = "NgÆ°á»i bình luáºn" +cmp = "Nhà soạn nhạc" +cmt = "Thợ sắp chữ" +cnd = "Nhạc trưởng" +cng = "Nhà điện ảnh" +cns = "Nhân viên kiểm duyệt" +coe = "Contestant-appellee" +col = "NgÆ°á»i sÆ°u tầm" +com = "NgÆ°á»i biên soạn" +con = "Chuyên viên bảo quản" +cor = "Cán bá»™ Ä‘Ã o tạo" +cos = "NgÆ°á»i tranh luáºn" +cot = "Contestant-appellant" +cou = "Court governed" +cov = "Thiết kế bìa" +cpc = "NgÆ°á»i khiếu nại vá» bản quyá»n" +cpe = "Complainant-appellee" +cph = "Chủ bản quyá»n" +cpl = "NgÆ°á»i khiếu nại" +cpt = "Complainant-appellant" +cre = "NgÆ°á»i sáng tạo" +crp = "Phóng viên" +crr = "NgÆ°á»i kiểm duyệt" +crt = "Court reporter" +csl = "TÆ° vấn" +csp = "TÆ° vấn cho má»™t dá»± án" +cst = "Nhà thiết kế trang phục" +ctb = "NgÆ°Æ¡Í€i cộng sÆ°Ì£" +cte = "Contestee-appellee" +ctg = "NgÆ°á»i vẽ bản đồ" +ctr = "Nhà thầu" +cts = "Contestee" +ctt = "Contestee-appellant" +cur = "NgÆ°á»i phụ trách" +cwt = "Bình luáºn cho văn bản viết" +darst = "NgÆ°á»i biểu diá»…n" +dbp = "Vị trà phân phối" +dfd = "Defendant" +dfe = "Defendant-appellee" +dft = "Defendant-appellant" +dgg = "CÆ¡ quan cấp bằng" +dgs = "Giám sát Ä‘á»™" +dir = "Nhạc trưởng" +dis = "Dissertant" +dln = "Delineator" +dnc = "VÅ© công" +dnr = "Nhà tà i trợ" +dpc = "Mô tả" +dpt = "NgÆ°á»i gá»i tiá»n" +drehbuch = "Biên kịch" +drm = "NgÆ°Æ¡Í€i thảo văn kiện" +drt = "Giám đốc" +dsr = "Nhà thiết kế" +dst = "Nhà phân phối" +dtc = "Cá»™ng tác viên dữ liệu" +dte = "Dedicatee" +dtm = "Trình quản lý dữ liệu" +dto = "NgÆ°á»i cống hiến" +dub = "Tác giả đáng yêu" +edc = "Biên táºp biên soạn" +edm = "Biên táºp viên của công việc di chuyển hình ảnh" +edt = "Biên táºp viên" +egr = "Engraver" +elg = "Thợ Ä‘iện" +elt = "NgÆ°á»i in mạ" +eng = "Kỹ sÆ°" +enj = "Ban hà nh thẩm quyá»n" +etr = "ThÆ¡Ì£ khăÍc bằng a ciÍt" +evp = "Äịa Ä‘iểm tổ chức sá»± kiện" +exp = "Chuyên gia" +fac = "NgÆ°á»i fax" +fds = "Nhà phân phối phim" +fld = "Giám đốc lÄ©nh vá»±c" +flm = "Biên táºp phim" +fmd = "Äạo diá»…n phim" +fmk = "Nhà là m phim" +fmo = "Chủ cÅ©" +fmp = "Nhà sản xuất phim" +fnd = "Nhà tà i trợ" +Forts = "SÆ°Ì£ nôÍi tiêÍp" +fotogr = "Nhiếp ảnh gia" +fpy = "Bên thứ nhất" +frg = "NgÆ°Æ¡Í€i giả maÌ£o" +gis = "Chuyên gia thông tin địa lý" +grt = "Kỹ thuáºt viên đồ há»a" +hg = "Nhà xuất bản" +his = "CÆ¡ quan chủ quản" +hnr = "Honoree" +Hrsg = "Nhà xuất bản" +hrsg = "Nhà xuất bản" +hst = "Host" +Ill = "NgÆ°á»i vẽ tranh minh há»a" +ill = "NgÆ°á»i vẽ tranh minh há»a" +ilu = "Äèn chiếu sáng" +ins = "NgÆ°á»i đăng ký" +inszenierung = "Quản lý sân khấu" +interpr = "Thông dịch viên" +interpret = "Thông dịch viên" +interviewer = "NgÆ°á»i phá»ng vấn" +interviewter = "NgÆ°á»i được phá»ng vấn" +inv = "NgÆ°á»i phát minh" +isb = "CÆ¡ quan phát hà nh" +itr = "Nhạc công cụ" +ive = "NgÆ°á»i được phá»ng vấn" +ivr = "NgÆ°á»i phá»ng vấn" +jud = "Thẩm phán" +jug = "Thẩm quyá»n quản lý" +kad = "Tác giả chÃnh thức" +kamera = "Máy ảnh" +kartograph = "NgÆ°á»i vẽ bản đồ" +komm = "NgÆ°á»i bình luáºn" +Komment = "NgÆ°á»i bình luáºn" +Komp = "Nhà soạn nhạc" +komp = "Nhà soạn nhạc" +Korresp = "Phóng viên" +kostüm = "Nhà thiết kế trang phục" +lbr = "Phòng thà nghiệm" +lbt = "Librettist" +ldr = "Laboratory director" +led = "Lead" +lee = "Libelee-appellee" +lel = "Libelee" +len = "NgÆ°á»i cho mượn" +let = "Libelee-appellant" +lgd = "Thiết kế ánh sáng" +lie = "Libelant-appellee" +lil = "Libelant" +lit = "Libelant-appellant" +lsa = "Kiến trúc cảnh quan" +lse = "NgÆ°á»i được cấp phép" +lso = "NgÆ°á»i cấp phép" +ltg = "ngÆ°á»i in thaÌ£ch bản" +lyr = "NgÆ°á»i viết lá»i" +mcp = "NgÆ°á»i sao chép âm nhạc" +mdc = "Liên hệ siêu dữ liệu" +med = "Trung bình" +mfp = "NÆ¡i chế tạo" +mfr = "Nhà chế tạo" +mitarb = "Cá»™ng tác viên" +mod = "Máy Ä‘iá»u tiêÍt" +moderation = "Kiểm duyệt" +mon = "Mà n hình" +mrb = "Marbler" +mrk = "Trình chỉnh sá»a đánh dấu" +msd = "Giám đốc âm nhạc" +mte = "Máy khắc kim loại" +mtk = "NgÆ°á»i tiếp nháºn nguyên bản" +mus = "Nhạc sÄ©" +mutmassl Verf = "Tác giả giả định" +mutmassl VerfKomp = "Tác giả / nhà soạn nhạc giả định " +mutmaßl hrsg = "Nhà xuất bản giả định" +Mutmaßl Verf = "Tác giả giả định" +mutmaßl verf = "Tác giả giả định" +mutmaßl übers = "Dịch giả định" +Nachr = "Tác giả của lá»i kết, lá»i ghi cuối sách, v.v." +nrt = "NgÆ°á»i dẫn chuyện" +opn = "Äối thủ" +org = "NgÆ°á»i khởi tạo" +orm = "NgÆ°á»i tổ chức" +osp = "NgÆ°á»i trình bà y trên mà n hình" +oth = "Khác" +own = "Chủ" +pan = "Tham luáºn viên" +pat = "NgÆ°á»i bảo trợ" +pbd = "Giám đốc xuất bản" +pbl = "Nhà xuất bản" +pdr = "Giám đốc dá»± án" +pfr = "NgÆ°á»i sá»a lá»—i" +pht = "Nhiếp ảnh gia" +plt = "NgÆ°á»i báo cáo" +pma = "CÆ¡ quan cấp phép" +pmn = "Giám đốc sản xuất" +pop = "Máy in tấm" +ppm = "Nhà sản xuất giấy" +ppt = "NgÆ°á»i Ä‘iá»u khiển con rối" +pra = "Lá»i khen ngợi" +prc = "Quy trình liên hệ" +prd = "Nhân viên sản xuất" +pre = "NgÆ°á»i trình bà y" +prf = "NgÆ°Æ¡Í€i thi haÍ€nh" +prg = "Láºp trình viên" +prm = "Máy in" +prn = "Công ty sản xuất" +pro = "Nhà sản xuất" +prod = "Nhà sản xuất" +prp = "NÆ¡i sản xuất" +prs = "Thiết kế sản xuất" +prt = "Thợ in" +prv = "Các nhà cung cấp" +präses = "Lá»i khen ngợi" +pta = "Ứng viên sáng chế" +pte = "Plaintiff-appellee" +ptf = "Plaintiff" +pth = "NgÆ°á»i giữ bằng sáng chế" +ptt = "Plaintiff-appellant" +pup = "NÆ¡i xuất bản" +rbr = "Phiếu tá»± đánh giá" +rcd = "NgÆ°á»i ghi âm" +rce = "Kỹ sÆ° thu âm" +rcp = "NgÆ°á»i nháºn" +rdd = "Giám đốc Ä‘Ã i phát thanh" +realisation = "Hiện thá»±c hóa" +Red = "NgÆ°Æ¡Í€i biên tập" +red = "NgÆ°Æ¡Í€i biên tập" +regie = "Giám đốc" +ren = "Trình kết xuất đồ há»a" +reporter = "Phóng viên" +res = "Nghiên cứu viên" +resp = "Respondent" +rev = "NgÆ°á»i đánh giá" +rpc = "Nhà sản xuất radio" +rps = "Kho" +rpt = "Phóng viên" +rpy = "Bên có trách nhiệm" +rse = "Respondent-appellee" +rsg = "Sắp xếp lại" +rsp = "NgÆ°á»i trả lá»i" +rsr = "NgÆ°á»i phục hồi" +rst = "Respondent-appellant" +rth = "Trưởng nhóm nghiên cứu" +rtm = "Thà nh viên nhóm nghiên cứu" +sad = "Cố Vân Khoa hoÌ£c" +Sammler = "NgÆ°á»i sÆ°u tầm" +sammler = "NgÆ°á»i sÆ°u tầm" +sce = "NgÆ°á»i viết kịch bản" +Schreiber = "Nhà văn" +scl = "Nhà điêu khắc" +scr = "NgÆ°á»i sao chép bản thảo" +sds = "Nhà thiết kế âm thanh" +sec = "ThÆ° ký" +sgd = "Äạo diá»…n sân khấu" +sgn = "NgÆ°á»i ký tên" +sht = "Máy chủ há»— trợ" +sll = "NgÆ°á»i bán" +sng = "Ca sÄ©" +spk = "Diển giả" +spn = "Nhà tà i trợ" +sprecher = "Diển giả" +spy = "Bên thứ hai" +srv = "Kiểm soát viên" +std = "Äặt nhà thiết kế" +stecher = "NgÆ°á»i thợ khắc" +stg = "Cà i đặt" +stl = "NgÆ°á»i kể chuyện" +stm = "Quản lý sân khấu" +stn = "CÆ¡ quan tiêu chuẩn" +str = "Khuôn mẫu" +tcd = "Giám đốc kÄ© thuáºt" +tch = "Giáo viên" +textverf = "Tác giả" +ths = "Cố vấn luáºn án" +tld = "Giám đốc truyá»n hình" +tlp = "Nhà sản xuất truyá»n hình" +trc = "NgÆ°á»i chuyển nhượng" +trl = "Thông diÌ£ch viên" +tyd = "Kiểu thiết kế" +tyg = "NgÆ°á»i viết chữ" +tänzer = "VÅ© công" +uvp = "Äịa Ä‘iểm đại há»c" +vac = "Diá»…n viên lồng tiếng" +vdg = "NgÆ°á»i quay phim" +Verstorb = "NgÆ°á»i đã khuất" +verstorb = "NgÆ°á»i đã khuất" +voc = "Ca sÄ©" +vorl = "Bản nháp" +Vorr = "Tác giả giá»›i thiệu, v.v." +wac = "Tác giả của bình luáºn được thêm và o" +wal = "Tác giả của lá»i bà i hát thêm" +wam = "Tác giả của tà i liệu Ä‘i kèm" +wat = "Tác giả của văn bản được thêm" +wdc = "NgÆ°á»i tiá»u phu" +wde = "Máy khắc gá»—" +widmungsempfänger = "Dedicatee" +win = "Nhà văn giá»›i thiệu" +wit = "Nhân chứng" +wpr = "Tác giả của lá»i nói đầu" +wst = "Tác giả của ná»™i dung văn bản bổ sung" +zeichner = "NgÆ°Æ¡Í€i thảo văn thÆ°" +zensor = "Kiểm duyệt" +Ãœbers = "Thông diÌ£ch viên" +übers = "thông diÌ£ch viên" diff --git a/languages/HoldingStatus/vi.ini b/languages/HoldingStatus/vi.ini new file mode 100644 index 0000000000000000000000000000000000000000..7f12c25322b29a43a55a17ec7e63bb045d9ab36c --- /dev/null +++ b/languages/HoldingStatus/vi.ini @@ -0,0 +1,4 @@ +service_available_presentation = "Chỉ sá» dụng trong thÆ° viện" +service_loan = "Cho mượn" +service_presentation = "Trong sá» dụng thÆ° viện" +services_available_html = "Có sẵn cho %%list%%" diff --git a/languages/ar.ini b/languages/ar.ini index 0d234aab9388f59655369ca8c2867a5e9cacba5d..ef0a72ba12413dae183d4c08dcc6f36fc765b89b 100644 --- a/languages/ar.ini +++ b/languages/ar.ini @@ -8,6 +8,7 @@ access_denied = "تم رÙض الوصول." Accession Number = "رقم الانضمام" Account = "Øساب" account_block_options_missing = "تمت إزالة بعض الخيارات نظرا لوجود Øظر على Øسابك. التÙاصيل: %%details%%" +account_has_alerts = "توجد تنبيهات Ù„Øسابك" Add a Library Card = "أض٠بطاقة مكتبة" Add a Note = "إضاÙØ© ملاØظة" Add Tag = "إضاÙØ© وسم" @@ -47,6 +48,7 @@ Advanced Search = "بØØ« متقدم" advSearchError_noRights = "عذراً، لكنك لا تملك صلاØية تØرير هذا البØØ«. ربما انتهت جلسة متصÙØÙƒ ØŸ" advSearchError_notAdvanced = "البØØ« الذي طلبت تØريره ليس بØثا متقدماً." advSearchError_notFound = "لم يتم العثور على البØØ« الذي طلبته." +ajax_load_interrupted = "تمت مقاطعة التØميل" ajaxview_label_information = "معلومات" ajaxview_label_tools = "أدوات" All = "الكل" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "هل ترغب ÙÙŠ Ø¥ Contents = "المØتويات" Contributing Source = "المصدر المساهم" Contributors = "المساهمون" +Coordinates = "Ø¥Øداثيات" Copies = "النسخ" Copy = "النسخة" Copyright = "Øقوق النسخ" @@ -364,6 +367,8 @@ external_auth_heading = "الوصول إلى المادة المرخصة" external_auth_login_message = "تسجيل الدخول للوصول إلى المادة المرخصة " external_auth_unauthorized = "غير Ù…ØµØ±Ø Ù„Ùƒ بالوصول إلى المادة المرخصة" external_auth_unauthorized_desc = "لا توÙر طريقة تسجيل دخولك وصولا إلى المادة المرخصة. يرجى تسجيل الخروج ثم إعادة تسجيل الدخول بطريقة أخرى." +facet_list_empty = "لا تتواÙر أي بيانات" +facet_list_for = "قائمة البØØ« النطاقي Ù„ %%field%%" FAQs = "الأسئلة الشائعة" fav_delete = "Øذ٠المÙضلة المØددة" fav_delete_deleting = "تم ØØ°Ù Ù…Ùضلتك." @@ -381,6 +386,8 @@ fav_list_delete_fail = "عذرا، لقد Øدث خطـأ. لم يتم ØØ°Ù Ù‚ Favorites = "المÙضلة" Fee = "رسم" Feedback = "تغذية راجعة" +feedback_email = "البريد الالكتروني" +feedback_login_required = "يجب تسجيل دخولك أولا" feedback_name = "الاسم" Field of activity = "Øقل النشاط" File Description = "وص٠الملÙ" @@ -392,6 +399,7 @@ Find More = "ابØØ« عن المزيد" Find New Items = "ابØØ« عن مواد جديدة" Finding Aid = "ابØØ« عن Aid" Fine = "غرامة" +Fine Date = "تاريخ الغرامة" fine_limit_patron = "لقد وصلت للØد الأقصى للغرامات ولا يمكن تجديد المواد" Fines = "الغرامات" First = "الأول" @@ -411,6 +419,7 @@ Geographic Search = "بØØ« جغراÙÙŠ" Geographic Terms = "مصطلØات جغراÙية" Geography = "المنطقة" Get full text = "اØصل على النص الكامل" +Get more information = "اØصل على المزيد من المعلومات" Get RSS Feed = "Ø£Øصل على تغذية RSS" Globe = "عالم" Go = "اذهب" @@ -447,6 +456,7 @@ history_saved_searches = "بØوثك المØÙوظة" history_search = "البØØ« عن" history_time = "وقت" hold_available = "Ù…ØªØ§Ø Ù„Ù„Ø§Ù„ØªÙ‚Ø§Ø·" +hold_available_until = "Ù…ØªØ§Ø Ù„Ù„Ø§Ù„ØªÙ‚Ø§Ø· Øتى %%date%%" hold_cancel = "إلغاء الØجز" hold_cancel_all = "إلغاء كل الØجوزات" hold_cancel_fail = "لم يتم إلغاء طلبك. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة" @@ -510,6 +520,7 @@ ill_request_processed = "معالج" ill_request_profile_html = "لمعلومات عن طلب الاستعارة بين المكتبات، يرجى إنشاء <a href="%%url%%">مل٠Ùهرسة مكتبتك</a>." ill_request_submit_text = "وضع طلب" Illustrated = "Ù…ÙˆØ¶Ø Ø¨Ø±Ø³ÙˆÙ…Ø§Øª توضيØية" +ils_account_create_error = "لا يمكن إنشاء Øسابك ÙÙŠ نظام إدارة مكتبتنا. إذا استمرت المشكلة، يرجى الاتصال بمكتبتك." ils_action_unavailable = "الخاصية المطلوبة غير متاØØ© ببطاقة المكتبة النشطة." ils_connection_failed = "نظام إدارة مكتبتنا قيد الصيانة Øاليا." ils_offline_holdings_message = "معلومات إتاØØ© المواد والمقتنيات غير متاØØ© Øاليا. الرجاء قبول اعتذارنا عن أي إزعاج قد يسببه ذلك والاتصال بنا للمزيد من المساعدة:" @@ -584,6 +595,7 @@ Library Catalog Search = "بØØ« Ùهرس المكتبة" Library Catalog Search Result = "Ù†ØªØ§Ø¦Ø Ø¨ØØ« Ùهرس المكتبة" Library Catalog Username = "اسم مستخدم Ùهرس المكتبة" Library Web Search = "بØØ« ويب المكتبة" +library_card_edit_password_placeholder = "كلمة مرور جديدة" lightbox_error = "خطأ: لا يمكن تØميل المربع المنبثق" Limit To = "تØديد إلى" List = "قائمة" @@ -825,7 +837,7 @@ Refine Results = "ØªÙ†Ù‚ÙŠØ Ø§Ù„Ù†ØªØ§Ø¦Ø¬" Region = "المنطقة" relais_available = "هذه المادة متاØØ© عبر الإعارة بين المكتبات. هل ترغب ÙÙŠ طلبها؟ " relais_checking = "جاري التØقق من الإتاØØ©..." -relais_error_html = "لقد Øدثت مشكلة بخصوص هذا الطلب. انقر <a href="%%url%%" target='new'>هنا</a> لطلب هذه المادة باستخدام الموقع الالكتروني للإعارة بين المكتبات.</a>" +relais_error_html = "لقد Øدثت مشكلة بخصوص هذا الطلب. انقر <a href="%%url%%" target='new'>هنا</a> لطلب هذه المادة باستخدام الموقع الالكتروني للإعارة بين المكتبات." relais_request = "طلب إعارة بين المكتبات" relais_requesting = "جاري الطلب..." relais_search = "بØØ« الإعارة بين المكتبات" @@ -843,9 +855,11 @@ renew_error = "لم نستطع تجديد مادتك (موادك) - يرجى ا renew_fail = "لا يمكن تجديد هذه المادة" renew_item = "تجديد المادة" renew_item_due = "المادة مستØقة خلال ال 24 ساعة القادمة" +renew_item_due_tooltip = "مواد مستØقة ÙÙŠ وقت قريب" renew_item_limit = "لقد وصلت هذه المادة Ù„Øد التجديد لها" renew_item_no = "لا يمكن تجديد هذه المادة" renew_item_overdue = "المادة متأخرة" +renew_item_overdue_tooltip = "مواد متأخرة" renew_item_requested = "تم طلب هذه المادة بواسطة مستخدم آخر" renew_select_box = "تجديد المادة" renew_selected = "تجديد المواد المØددة" @@ -894,6 +908,7 @@ search_match = "مطابقة" search_NOT = "لا توجد مصطلØات" search_OR = "أي مصطلØ" search_save_success = "تم ØÙظ البØØ« بنجاØ." +search_terms = "مصطلØات البØØ«" search_unsave_success = "تم Øذ٠البØØ« المØÙوظ بنجاØ." seconds_abbrev = "s" see all = "انظر الكل" @@ -1078,6 +1093,7 @@ Video = "الÙيديو" Video Clips = "مقاطع الÙيديو" Videos = "الÙيديوهات" View Book Bag = "عرض سلة الكتب" +View Complete Issue = "عرض المشكلة بالكامل" View Full Collection = "عرض المجموعة كاملة" View Full Record = "عرض التسجيلة الكاملة" View in EDS = "أعرض ÙÙŠ EDS" diff --git a/languages/bn.ini b/languages/bn.ini index 570949cdda6255f731ad965bdef16b6945b42aab..13c0381f681e7b2eb86e0b3084ca5f4667100986 100644 --- a/languages/bn.ini +++ b/languages/bn.ini @@ -9,6 +9,7 @@ access_denied = "পরিষেবা বনà§à¦§à¥¤" Accession Number = "পরিগà§à¦°à¦¹à¦¨ সংখà§à¦¯à¦¾" Account = "অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ" account_block_options_missing = "আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ বà§à¦²à¦• করার জনà§à¦¯ কিছৠসà§à¦¬à¦¿à¦§à¦¾ পà§à¦°à¦¤à§à¦¯à¦¾à¦¹à¦¾à¦° করা হয়েছে । বিশদে জানà§à¦¨ : %%details%%" +account_has_alerts = "আপনার জনà§à¦¯ জরà§à¦°à¦¿ বারà§à¦¤à¦¾ আছে" Add a Library Card = "গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার কারà§à¦¡ যà§à¦•à§à¦¤ করà§à¦¨" Add a Note = "টীকা যà§à¦•à§à¦¤ করà§à¦¨" Add Tag = "টà§à¦¯à¦¾à¦— যà§à¦•à§à¦¤ করà§à¦¨" @@ -48,6 +49,7 @@ Advanced Search = "বিসà§à¦¤à§ƒà¦¤ অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨" advSearchError_noRights = "দà§à¦ƒà¦–িতঃ আপনার অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨à¦Ÿà¦¿ সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করার অনà§à¦®à¦¤à¦¿ নেই । সমà§à¦à¦¬à¦¤ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¾à¦° সেশনের মেয়াদ শেষ ।" advSearchError_notAdvanced = "তà§à¦°à§à¦Ÿà¦¿à¦ƒ অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করার অনà§à¦°à§‹à¦§à¦Ÿà¦¿ বিসà§à¦¤à§ƒà¦¤ সারà§à¦š নয়" advSearchError_notFound = "যে অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨à¦Ÿà¦¿ আপনি অনà§à¦°à§‹à¦§ করেছেন তা পাওয়া যায়নি ।" +ajax_load_interrupted = "পà§à¦°à¦²à§‡à¦– পà§à¦°à¦¦à¦°à§à¦¶à¦¨ বাধাপà§à¦°à¦¾à¦ªà§à¦¤ হয়েছে" ajaxview_label_information = "তথà§à¦¯" ajaxview_label_tools = "সরঞà§à¦œà¦¾à¦®à¦¸à¦®à§‚হ" All = "সমসà§à¦¤" @@ -235,6 +237,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "আপনি কি Contents = "সামগà§à¦°à§€à¦—à§à¦²à¦¿" Contributing Source = "সংগà§à¦°à¦¹à§‡à¦° অবদান" Contributors = "অবদানকারীরা" +Coordinates = "à¦à§Œà¦—োলিক সà§à¦¥à¦¾à¦¨à¦¾à¦™à§à¦•" Copies = "পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿à¦—à§à¦²à¦¿" Copy = "পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿" Copyright = "গà§à¦°à¦¹à¦¸à§à¦¬à¦¤à§à¦¬" @@ -365,6 +368,8 @@ external_auth_heading = "সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করা গà§à¦° external_auth_login_message = "লগ ইন করà§à¦¨ : সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করা গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার সমà§à¦ªà¦¦à§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨" external_auth_unauthorized = "সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করা গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার সমà§à¦ªà¦¦à§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦° করার জনà§à¦¯ আপনার পà§à¦°à§Ÿà§‹à¦œà¦¨à§€à§Ÿ অনà§à¦®à§‹à¦¦à¦¨ নেই" external_auth_unauthorized_desc = "আপনার বরà§à¦¤à¦®à¦¾à¦¨ লগ ইন পদà§à¦§à¦¤à¦¿ সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করা গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার সমà§à¦ªà¦¦à§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦° করার জনà§à¦¯ পà§à¦°à§Ÿà§‹à¦œà¦¨à§€à§Ÿ অনà§à¦®à§‹à¦¦à¦¨ পà§à¦°à¦¦à¦¾à¦¨ করছে না । লগ আউট করে অনà§à¦¯ লগ ইন পদà§à¦§à¦¤à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨ " +facet_list_empty = "উপাতà§à¦¤ বা পà§à¦°à¦²à§‡à¦– উপলবà§à¦§ নয়" +facet_list_for = "বিà¦à¦¾à¦— উপবিà¦à¦¾à¦— তালিকা %%field%%" FAQs = "জিজà§à¦žà¦¾à¦¸à¦¿à¦¤ পà§à¦°à¦¶à§à¦¨à¦¾à¦¬à¦²à§€" fav_delete = "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ পছনà§à¦¦ তালিকাগà§à¦²à¦¿ মà§à¦›à§à¦¨" fav_delete_deleting = "আপনার পà§à¦°à¦¿à¦¯à¦¼ পছনà§à¦¦ তালিকাগà§à¦²à¦¿ মোছা হয়েছে।" @@ -382,6 +387,8 @@ fav_list_delete_fail = "দà§à¦ƒà¦–িত, à¦à¦•à¦Ÿà¦¿ তà§à¦°à§à¦Ÿà¦¿ ঘ Favorites = "উপাদানটি সংরকà§à¦·à¦¨ করা হয়েছে" Fee = "খরচ" Feedback = "পà§à¦°à¦¤à¦¿à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾ পাঠান" +feedback_email = "ই-মেইল" +feedback_login_required = "আপনি আগে লগইন করà§à¦¨" feedback_name = "নাম" Field of activity = "বিষয় দকà§à¦·à¦¤à¦¾" File Description = "ফাইলের বিবরণ" @@ -393,6 +400,7 @@ Find More = "আরও অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ " Find New Items = "নতà§à¦¨ উপাদান অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ " Finding Aid = "খোà¦à¦œà¦¾à¦° উপায়" Fine = "জরিমানা" +Fine Date = "জরিমানা তারিখ" fine_limit_patron = "আপনি আপনার জরিমানা সীমাতে পৌà¦à¦›à§‡à¦›à§‡à¦¨ à¦à¦¬à¦‚ উপাদানটি পà§à¦¨à¦°à§à¦¨à¦¬à§€à¦•à¦°à¦£ করা যাবে না" Fines = "জরিমানা" First = "পà§à¦°à¦¥à¦®" @@ -412,6 +420,7 @@ Geographic Search = "à¦à§Œà¦—লিক অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨" Geographic Terms = "à¦à§Œà¦—লিক শবà§à¦¦à¦¾à¦¬à¦²à§€" Geography = "à¦à§‚গল" Get full text = "সমà§à¦ªà§‚রà§à¦£ পাঠপাওয়ার জনà§à¦¯" +Get more information = "আরো তথà§à¦¯ জানà§à¦¨" Get RSS Feed = "আরà¦à¦¸à¦à¦¸ পà§à¦°à¦¤à¦¿à¦•à§à¦°à¦¿à§Ÿà¦¾ পাওয়ার জনà§à¦¯" Globe = "গোলাকার" Go = "যান" @@ -448,6 +457,7 @@ history_saved_searches = "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨à¦—à§à¦²à¦¿ সংরক history_search = "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨" history_time = "সময়" hold_available = "Aপিকআপের জনà§à¦¯" +hold_available_until = "à¦à¦‡ তারিখ অবধি পরিগà§à¦°à¦¹à¦¨à§‡à¦° জনà§à¦¯ উপলবà§à¦§ %%date%%" hold_cancel = "হোলà§à¦¡ বাতিল করà§à¦¨" hold_cancel_all = "সমসà§à¦¤ হোলà§à¦¡ বাতিল করা হয়েছে" hold_cancel_fail = "আপনার অনà§à¦°à§‹à¦§ বাতিল করা হয় নি। আরও সহায়তার জনà§à¦¯ সঞà§à¦šà¦¾à¦°à¦¨ ডেসà§à¦•à§‡ যোগাযোগ করà§à¦¨" @@ -511,6 +521,7 @@ ill_request_processed = "সমà§à¦ªà§‚রà§à¦¨à¦Ÿà¦¿ পà§à¦°à¦•à§à¦°à¦¿à§Ÿ ill_request_profile_html = "আনà§à¦¤à¦ƒà¦—à§à¦°à¦¨à§à¦¥à¦¾à¦—ার ঋণ অনà§à¦°à§‹à¦§à§‡à¦° জনà§à¦¯ তথà§à¦¯ , অনà§à¦—à§à¦°à¦¹ করে ঠিক করà§à¦¨ <a href="%%url%%">Library Catalog Profile</a>." ill_request_submit_text = "অনà§à¦°à§‹à¦§ করà§à¦¨" Illustrated = "ছবিযà§à¦•à§à¦¤" +ils_account_create_error = "গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার বà§à¦¯à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦ªà¦• সফটওয়à§à¦¯à¦¾à¦°à¦Ÿà¦¿ আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ তৈরী করতে পারেনি। সমাধানের জনà§à¦¯ গà§à¦°à¦¨à§à¦¥à¦¾à¦—ারে যোগাযোগ করà§à¦¨à¥¤" ils_action_unavailable = "অসমরà§à¦¥à¦¿à¦¤ অনà§à¦°à§‹à¦§à¥¤ আপনার সকà§à¦°à¦¿à§Ÿ গà§à¦°à¦¨à§à¦¥à¦¾à¦—ার সদসà§à¦¯à¦ªà¦¤à§à¦° à¦à¦‡ সà§à¦¬à¦¿à¦§à¦¾ পà§à¦°à¦¦à¦¾à¦¨ করে না।" ils_connection_failed = "অটোমেশন সফটওয়à§à¦¯à¦¾à¦°à§‡à¦° সঙà§à¦—ে সমà§à¦ªà¦°à§à¦• ছিনà§à¦¨ হয়েছে। আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ সমà§à¦ªà¦°à§à¦•à¦¿à¦¤ তথà§à¦¯ উপলবà§à¦§ নয়। সমাধানের জনà§à¦¯ আপনার গà§à¦°à¦¨à§à¦¥à¦¾à¦—ারে যোগাযোগ করà§à¦¨à¥¤" ils_offline_holdings_message = "হোলà§à¦¡à¦¿à¦‚স à¦à¦¬à¦‚ উপাদানটির পà§à¦°à¦¾à¦ªà§à¦¯à¦¤à¦¾ বরà§à¦¤à¦®à¦¾à¦¨à§‡ অনà§à¦ªà¦²à¦¬à§à¦§à¥¤ আপনার সবরকম অসà§à¦¬à¦¿à¦§à¦¾à¦° জনà§à¦¯ আমরা দà§à¦ƒà¦–িত à¦à¦¬à¦‚ অনà§à¦¯à¦¾à¦¨à§à¦¯ সহায়তার জনà§à¦¯ আমাদের সাথে যোগাযোগ করà§à¦¨à¦ƒ" @@ -585,6 +596,7 @@ Library Catalog Search = "গà§à¦°à¦¨à§à¦¥à¦¤à¦¾à¦²à¦¿à¦•à¦¾ অনà§à¦¸à¦¨ Library Catalog Search Result = "গà§à¦°à¦¨à§à¦¥à¦¤à¦¾à¦²à¦¿à¦•à¦¾à¦° অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ ফলাফল" Library Catalog Username = "গà§à¦°à¦¨à§à¦¥à¦¤à¦¾à¦²à¦¿à¦•à¦¾ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° নাম" Library Web Search = "গà§à¦°à¦¨à§à¦¥à¦¤à¦¾à¦²à¦¿à¦•à¦¾à¦°à¦—à§à¦°à¦¨à§à¦¥à¦¾à¦—ার ওয়েব অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨" +library_card_edit_password_placeholder = "নতà§à¦¨ পাসওইয়ারà§à¦¡" lightbox_error = "তà§à¦°à§à¦Ÿà¦¿à¦ƒ পপআপ বকà§à¦¸ লোড করা যাবে না" Limit To = "পরিধির মধà§à¦¯à§‡" List = "তালিকা" @@ -844,9 +856,11 @@ renew_error = "আমরা আপনার উপাদানটি পà§à¦¨ renew_fail = "à¦à¦‡ উপাদানটি পà§à¦¨à¦°à§à¦¨à¦¬à§€à¦•à¦°à¦£ করা যাবে না" renew_item = "উপাদান নবীকরণ" renew_item_due = "উপাদানটি আগামী 24 ঘনà§à¦Ÿà¦¾à¦° মধà§à¦¯à§‡ ফেরত দিতে হবে" +renew_item_due_tooltip = "পà§à¦°à¦²à§‡à¦– ফেরত দেওয়ার সময় à¦à¦—িয়ে আসছে" renew_item_limit = "à¦à¦‡ উপাদানটি মেয়াদানà§à¦¤à§‡ নবায়নের সীমায় পৌà¦à¦›à§‡à¦›à§‡" renew_item_no = "à¦à¦‡ উপাদানটি পà§à¦¨à¦°à§à¦¨à¦¬à§€à¦•à¦°à¦£ করা যাবে না" renew_item_overdue = "উপাদানের মেয়াদ-উতà§à¦¤à§€à¦°à§à¦¨" +renew_item_overdue_tooltip = "পà§à¦°à¦²à§‡à¦– ফেরত দেওয়ার সময় অতীত" renew_item_requested = "à¦à¦‡ উপাদানটি à¦à¦•à¦œà¦¨ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ দà§à¦¬à¦¾à¦°à¦¾ অনà§à¦°à§‹à¦§ করা হয়েছে" renew_select_box = "উপাদান নবীকরণ" renew_selected = "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ উপাদানগà§à¦²à¦¿ নবীকরণ" @@ -895,6 +909,7 @@ search_match = "সদৃশ" search_NOT = "শরà§à¦¤à¦¾à¦¬à¦²à§€ নেই" search_OR = "যেকোনো শরà§à¦¤à¦¾à¦¬à¦²à§€" search_save_success = "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ সফলà¦à¦¾à¦¬à§‡ সংরকà§à¦·à¦¿à¦¤à¥¤" +search_terms = "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨à§‡ বà§à¦¯à¦¬à¦¹à§ƒà¦¤ শবà§à¦¦à¦¾à¦¬à¦²à§€" search_unsave_success = "সংরকà§à¦·à¦¿à¦¤ অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ সফলà¦à¦¾à¦¬à§‡ সরানো হয়েছে।" seconds_abbrev = "সেকেনà§à¦¡ " see all = "সবগà§à¦²à¦¿ দেখà§à¦¨" @@ -1079,6 +1094,7 @@ Video = "à¦à¦¿à¦¡à¦¿à¦“" Video Clips = "à¦à¦¿à¦¡à¦¿à¦“ কà§à¦²à¦¿à¦ªà¦¸" Videos = "à¦à¦¿à¦¡à¦¿à¦“" View Book Bag = "গà§à¦°à¦¨à§à¦¥à¦¸à¦®à§à¦à¦¾à¦° দেখà§à¦¨" +View Complete Issue = "পতà§à¦°à¦¿à¦•à¦¾à¦° সমসà§à¦¤ সংখà§à¦¯à¦¾ দেখà§à¦¨" View Full Collection = "সমà§à¦ªà§‚রà§à¦£ সংগà§à¦°à¦¹ দেখà§à¦¨" View Full Record = "সমà§à¦ªà§‚রà§à¦£ নথি দেখà§à¦¨" View in EDS = "EDS ঠদেখà§à¦¨" diff --git a/languages/ca.ini b/languages/ca.ini index a838eda0f94e32bb74a373d469c699d46ad9f11c..32616e7f2819ea74bbe9ace69303e30d2b8d7841 100644 --- a/languages/ca.ini +++ b/languages/ca.ini @@ -392,6 +392,8 @@ fav_list_delete_fail = "Disculpeu, hi ha hagut un error. La vostra llista no s Favorites = "Favorits" Fee = "Quota" Feedback = "Feedback" +feedback_email = "Correu electrònic" +feedback_login_required = "Abans heu d’iniciar sessió." feedback_name = "Nom" Field of activity = "Camp d'activitat" File Description = "Descripció del fitxer" @@ -595,6 +597,7 @@ Library Catalog Search = "Cerca al catà leg de la bibliotec" Library Catalog Search Result = "Resultat de la cerca al Catà leg de la Biblioteca" Library Catalog Username = "Nom d’usuari del Catà leg de la Biblioteca" Library Web Search = "Cerca al web de la Biblioteca" +library_card_edit_password_placeholder = "Nova contrasenya" lightbox_error = "Error: No es pot carregar caixa emergent" Limit To = "Limitar a" List = "Llistat" @@ -836,7 +839,7 @@ Refine Results = "Refinar resultats" Region = "Regió" relais_available = "Aquest registre està disponible amb prèstec interbibliotecari. Voldira demanar-ho?" relais_checking = "Comprovant disponivilitat..." -relais_error_html = "Hi ha hagut un problema amb la seva sol·licitut. Clickeu <a href="%%url%%" target='new'>here</a> per demanar-lo via préstec interbibliotecari.</a>" +relais_error_html = "Hi ha hagut un problema amb la seva sol·licitut. Clickeu <a href="%%url%%" target='new'>here</a> per demanar-lo via préstec interbibliotecari." relais_request = "Solicitud de préstec interbibliotecari" relais_requesting = "Demanant..." relais_search = "Cerca de préstec interbibliotecari" diff --git a/languages/cs.ini b/languages/cs.ini index e9cf6212802939822a279b986ded2b16fa1072db..ce1a8ac75f01fa9d6ae10aec9ee7188f8a14f09c 100644 --- a/languages/cs.ini +++ b/languages/cs.ini @@ -1,4 +1,4 @@ -; Translation: opensource.knihovna.cz, Michal Denár, Josef Moravec, last updated 5. 6. 2018 +; Translation: opensource.knihovna.cz, Michal Denár, Josef Moravec, last updated 7. 1. 2019 Abstract = "Abstrakt" Access = "PÅ™Ãstup" Access URL = "PÅ™Ãstupová URL adresa" @@ -6,6 +6,7 @@ access_denied = "PÅ™Ãstup odepÅ™en." Accession Number = "PÅ™Ãstupové ÄÃslo" Account = "ÚÄet" account_block_options_missing = "NÄ›které možnosti ovládánà Ätenářského konta byly omezeny, protože je vaÅ¡e konto zablokováno: %%details%%" +account_has_alerts = "UpozornÄ›nà souvisejÃcà s vaÅ¡Ãm úÄtem" Add a Library Card = "PÅ™ipojit dalšà úÄet" Add a Note = "PÅ™idat poznámku" Add Tag = "PÅ™idat tag" @@ -45,6 +46,7 @@ Advanced Search = "PokroÄilé vyhledávánÃ" advSearchError_noRights = "Bohužel nemáte oprávnÄ›nà upravovat toto vyhledávánÃ. Možná doÅ¡lo k automatickému odhlášenà po delÅ¡Ã neÄinnosti." advSearchError_notAdvanced = "VyhledávánÃ, které chcete upravit, nenà pokroÄilé vyhledávánÃ." advSearchError_notFound = "Požadované vyhledávánà nebylo nalezeno." +ajax_load_interrupted = "Nahrávánà bylo pÅ™eruÅ¡eno" ajaxview_label_information = "Informace" ajaxview_label_tools = "Nástroje" All = "VÅ¡e" @@ -232,6 +234,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Opravdu chcete zruÅ¡it Contents = "Obsah" Contributing Source = "PÅ™ispÃvajÃcà zdroj" Contributors = "PÅ™ispÄ›vatelé" +Coordinates = "SouÅ™adnice" Copies = "Jednotky" Copy = "Jednotka" Copyright = "Copyright" @@ -362,6 +365,8 @@ external_auth_heading = "PÅ™Ãstup k licencovaným zdrojům" external_auth_login_message = "Pro pÅ™Ãstup k licencovaným zdrojům se pÅ™ihlaste" external_auth_unauthorized = "Nemáte oprávnÄ›nà pro pÅ™Ãstup k licencovaným zdrojům" external_auth_unauthorized_desc = "Tento způsob pÅ™ihlášneà nelze využÃt k ověřenà pÅ™Ãstupu k licencovaným zdrojům. OdhlaÅ¡te se a použijte jiný způsob pÅ™ihlášenÃ." +facet_list_empty = "Data nejsou k dispozici" +facet_list_for = "Seznam hodnot pro upÅ™esnÄ›nà podle: %%field%%" FAQs = "ÄŒasto kladené otázky" fav_delete = "Smazat vybrané oblÃbené položky" fav_delete_deleting = "VaÅ¡e oblÃbené budou smazány." @@ -379,6 +384,8 @@ fav_list_delete_fail = "Promiňte, ale doÅ¡lo k chybÄ›. Váš seznam nebyl odstr Favorites = "OblÃbené" Fee = "Poplatek" Feedback = "Váš názor" +feedback_email = "Poslat emailem" +feedback_login_required = "Nejprve se musÃte pÅ™ihlásit." feedback_name = "Jméno" Field of activity = "Oblast působenÃ" File Description = "Popis souboru" @@ -390,6 +397,7 @@ Find More = "Objevte vÃce" Find New Items = "Vyhledávat v nových titulech" Finding Aid = "Pomůcka pro vyhledávánÃ" Fine = "UpomÃnka" +Fine Date = "Datum vytvoÅ™enà poplatku" fine_limit_patron = "Dosáhli jste VaÅ¡eho limitu upomÃnek, vaÅ¡e výpůjÄky proto nelze prodloužit." Fines = "UpomÃnky" First = "PrvnÃ" @@ -409,6 +417,7 @@ Geographic Search = "Geografické vyhledávánÃ" Geographic Terms = "Geografický termÃn" Geography = "Geografie" Get full text = "ZÃskat plný text" +Get more information = "Zjistit podrobnosti o pÅ™Ãstupu" Get RSS Feed = "RSS" Globe = "SvÄ›t" Go = "OK" @@ -445,6 +454,7 @@ history_saved_searches = "Uložená vyhledávánÃ" history_search = "Vyhledávacà dotaz" history_time = "Datum a Äas" hold_available = "PÅ™ipraveno k vyzvednutÃ" +hold_available_until = "Dostupné k vyzvednutà do %%date%%" hold_cancel = "ZruÅ¡it požadavek" hold_cancel_all = "ZruÅ¡it vÅ¡echny požadavky" hold_cancel_fail = "Váš požadavek se nepodaÅ™ilo zruÅ¡it. Kontaktujte pracovnÃky knihovny pro dalÅ¡Ã informace." @@ -459,7 +469,7 @@ hold_error_fail = "Váš požadavek selhal. Kontaktujte pracovnÃky knihovny pro hold_invalid_pickup = "Neplatné mÃsto vyzvednutÃ. Zkuste to znovu." hold_invalid_request_group = "Byla vybrána neplatná skupina požadavků. Zkuste to znovu, prosÃm" hold_items_available = "Nelze vytvoÅ™it požadavek na dokument, který je k dispozici." -hold_login = "PÅ™ihláste se" +hold_login = "PÅ™ihlaste se" hold_place = "Zadat požadavek" hold_place_fail_missing = "Váš požadavek selhal. Chybà nÄ›které údaje. Kontaktujte pracovnÃky knihovny pro dalÅ¡Ã informace." hold_place_success_html = "Váš požadavek byl úspěšnÄ› vložen. <a href="%%url%%">VaÅ¡e rezervace a objednávky</a>." @@ -508,6 +518,7 @@ ill_request_processed = "Zpracováno" ill_request_profile_html = "Pro informace o meziknihovnÃch výpůjÄkách je nutné mÃt <a href="%%url%%">úÄet v knihovnÄ›</a>." ill_request_submit_text = "Objednat MVS" Illustrated = "Ilustrováno" +ils_account_create_error = "NepodaÅ™ilo se vytvoÅ™it Váš úÄet v knihovnÃm systému. Pokud problém pÅ™etrvává, kontaktujte knihovnu." ils_action_unavailable = "Pro aktuálnÄ› nastavený Ätenářský průkaz nenà tato funkce dostupná." ils_connection_failed = "PrávÄ› probÃhá údržba knihovnÃho systému." ils_offline_holdings_message = "V souÄasné dobÄ› nejsou dostupné informace o dostupnosti. Omlouváme se Vám za nepÅ™Ãjemnosti. Neváhejte nás kontaktovat a my se pokusÃme zjistit požadované informace jinou cestou:" @@ -582,6 +593,7 @@ Library Catalog Search = "Vyhledávánà v katalogu" Library Catalog Search Result = "Výsledky hledánà v knihovnÃm katalogu" Library Catalog Username = "Uživatelské jméno" Library Web Search = "Vyhledávánà na webu knihovny" +library_card_edit_password_placeholder = "Nové heslo" lightbox_error = "Chyba: nemohu otevÅ™Ãt vyskakovacà okno" Limit To = "Omezit na" List = "Seznam" @@ -823,7 +835,7 @@ Refine Results = "UpÅ™esnit hledánÃ" Region = "Oblast" relais_available = "Tento dokument je dostupný v rámci meziknihovnà výpůjÄnà služby. Chcete jej objednat?" relais_checking = "ZjiÅ¡Å¥uji dostupnost..." -relais_error_html = "PÅ™i zpracovánà požadavku se vyskytla chyba. KliknÄ›te <a href="%%url%%" target='new'>zde</a> pro objednánà dokumentu na stránkách systému pro meziknihovnà výpůjÄky.</a>" +relais_error_html = "PÅ™i zpracovánà požadavku se vyskytla chyba. KliknÄ›te <a href="%%url%%" target='new'>zde</a> pro objednánà dokumentu na stránkách systému pro meziknihovnà výpůjÄky." relais_request = "Objednávka meziknihovnà výpůjÄky" relais_requesting = "Objednávám..." relais_search = "Hledat v meziknihovnÃch výpůjÄkách" @@ -841,9 +853,11 @@ renew_error = "Nelze prodloužit VaÅ¡e výpůjÄky - obraÅ¥te se na knihovnÃky renew_fail = "VýpůjÄku nelze prodloužit" renew_item = "Prodloužit výpůjÄku" renew_item_due = "Jednotky s termÃnem vrácenà v následujÃcÃch 24 hodinách" +renew_item_due_tooltip = "VýpůjÄky s blÞÃcÃm se termÃnem vrácenÃ" renew_item_limit = "Tato jednotka již dosáhla maximálnÃho poÄtu prodlouženÃ" renew_item_no = "Nelze prodloužit" renew_item_overdue = "MÄ›lo být vráceno" +renew_item_overdue_tooltip = "VýpůjÄky s pÅ™ekroÄeným termÃnem vrácenÃ" renew_item_requested = "Tuto položku již požaduje jiný uživatel" renew_select_box = "Prodloužit výpůjÄku" renew_selected = "Prodloužit vybrané" @@ -892,6 +906,7 @@ search_match = "Shoda" search_NOT = "ŽÃDNÉ výrazy" search_OR = "LIBOVOLNÉ výrazy" search_save_success = "Hledánà bylo uloženo." +search_terms = "Vyhledávacà termÃny" search_unsave_success = "Uložené hledánà bylo vymazáno." seconds_abbrev = " s." see all = "Zobrazit vÅ¡e" @@ -1076,6 +1091,7 @@ Video = "Video" Video Clips = "Video klipy" Videos = "Videa" View Book Bag = "Prohlédnout obsah koÅ¡Ãku" +View Complete Issue = "Zobrazit celé ÄÃslo" View Full Collection = "Zobrazit celou sbÃrku" View Full Record = "Zobrazit úplný záznam" View in EDS = "Zobrazit v EDS" diff --git a/languages/cy.ini b/languages/cy.ini index d5df9bb43fb9672bf81aa5cde3ddabf44d7dc9f7..3138218d52aa193ba494e4303e37866888d92fd5 100644 --- a/languages/cy.ini +++ b/languages/cy.ini @@ -8,6 +8,7 @@ access_denied = "Mynediad wedi'i wrthod." Accession Number = "Cyfeirnod" Account = "Cyfrif" account_block_options_missing = "Mae rhai o'r dewisiadau wedi'u tynnu'n ôl o ganlyniad i rwystr ar eich cyfrif. Manylion: %%details%%" +account_has_alerts = "Mae negeseuon ar eich cyfrif" Add a Library Card = "Ychwanegu Cerdyn Llyfrgell" Add a Note = "Ychwanegu Nodyn" Add Tag = "Ychwanegu Tag" @@ -47,6 +48,7 @@ Advanced Search = "Chwiliad Uwch" advSearchError_noRights = "Mae'n ddrwg gennym, ond nid oes hawl gennych olygu'r chwiliad hwnnw. Efallai bod eich sesiwn pori wedi dod i ben?" advSearchError_notAdvanced = "Nid yw'r chwiliad yr ydych wedi ceisio ei olygu'n chwiliad uwch" advSearchError_notFound = "Ni ddaethpwyd o hyd i'r chwiliad a geisiwyd" +ajax_load_interrupted = "Llwytho wedi ei atal" ajaxview_label_information = "Gwybodaeth" ajaxview_label_tools = "Offer" All = "Popeth" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Ydych chi'n dymuno can Contents = "Cynnwys" Contributing Source = "Ffynhonnell" Contributors = "Cyfranwyr" +Coordinates = "Cyfesurynnau" Copies = "Copïau" Copy = "Copi" Copyright = "Hawlfraint" @@ -364,6 +367,8 @@ external_auth_heading = "Mynediad i ddeunydd trwyddedig" external_auth_login_message = "Mewngofnodwch i gael mynediad i ddeunydd trwyddedig" external_auth_unauthorized = "Nid ydych wedi'ch awdurdodi i gael mynediad i ddeunydd trwyddedig" external_auth_unauthorized_desc = "Nid yw'ch dull mewngofnodi yn rhoi mynediad i ddeunydd trwyddedig. Allgofnodwch yna menwgofnodwch gan ddefnyddio dull arall." +facet_list_empty = "Dim data ar gael" +facet_list_for = "Rhestr ffased ar gyfer %%field%%" FAQs = "Cwestiynau Cyffredin" fav_delete = "Dileu Ffefrynnau Dethol" fav_delete_deleting = "Mae eich ffefryn(nau) yn cael eu dileu." @@ -381,6 +386,8 @@ fav_list_delete_fail = "Mae'n ddrwg gennym, mae gwall wedi digwydd. Ni ddilëwyd Favorites = "Ffefrynnau" Fee = "Fee" Feedback = "Adborth" +feedback_email = "E-bost" +feedback_login_required = "Rhaid i chi fewngofnodi yn gyntaf." feedback_name = "Enw" Field of activity = "Maes gweithgarwch" File Description = "Disgrifiad Ffeil" @@ -392,6 +399,7 @@ Find More = "Canfod Mwy" Find New Items = "Canfod Eitemau Newydd" Finding Aid = "Cymorth Canfod" Fine = "Dirwy" +Fine Date = "Dyddiad Dirwy" fine_limit_patron = "Rydych chi wedi cyrraedd eich terfyn dirwyon ac ni allwch adnewyddu eitemau" Fines = "Dirwyon" First = "Cyntaf" @@ -411,6 +419,7 @@ Geographic Search = "Chwiliad daearyddol" Geographic Terms = "Termau Daearyddol" Geography = "Daearyddiaeth" Get full text = "Cael y testun llawn" +Get more information = "Mwy o wybodaeth" Get RSS Feed = "Cael Porthiant RSS" Globe = "Glôb" Go = "Ewch" @@ -447,6 +456,7 @@ history_saved_searches = "Fy Chwiliadau" history_search = "Chwilio" history_time = "Amser" hold_available = "Ar gael i Gasglu" +hold_available_until = "Ar gael i’w Gasglu Tan %%date%%" hold_cancel = "Canslo'r Daliad" hold_cancel_all = "Canslo'r Holl Ddaliadau" hold_cancel_fail = "Ni chanslwyd eich cais. Cysylltwch â'r ddesg fenthyca am gymorth pellach" @@ -510,6 +520,7 @@ ill_request_processed = "Proseswyd" ill_request_profile_html = "Am wybodaeth am gais am Fenthyciad Rhwnglyfrgellol, rhaid i chi sefydlu'ch <a href="%%url%%">Proffil Catalog Llyfrgell</a>." ill_request_submit_text = "Cyflwyno'r Cais" Illustrated = "Darluniadol" +ils_account_create_error = "Ni lwyddwyd i greu eich cyfrif ar ein system rheolaeth llyfrgell. Os yw’r broblem yn parhau, cysylltwch â’ch llyfrgell os gwelwch yn dda." ils_action_unavailable = "Nid yw'r weithred y gofynnwyd amdani ar gael gyda'r cerdyn llyfrgell gweithredol." ils_connection_failed = "Rydym yn gwneud gwaith cynnal a chadw ar ein System Rheoli'r Llyfrgell ar hyn o bryd" ils_offline_holdings_message = "Nid yw gwybodaeth am y stoc nac am argaeledd yr eitemau ar gael ar hyn o bryd. Rydym yn ymddiheuro am unrhyw anhwylustod. Cysylltwch â ni am ragor o wybodaeth." @@ -584,6 +595,7 @@ Library Catalog Search = "Chwilio Catalog y Llyfrgell" Library Catalog Search Result = "Canlyniad Chwiliad Catalog y Llyfrgell" Library Catalog Username = "Enw Defnyddiwr Catalog y Llyfrgell" Library Web Search = "Chwilio Gwe'r Llyfrgell" +library_card_edit_password_placeholder = "Cyfrinair Newydd" lightbox_error = "Gwall: Ni Ellir Llwytho'r Bocs Naidlen" Limit To = "Cyfyngu i" List = "Rhestr" @@ -843,9 +855,11 @@ renew_error = "Methom ag adnewyddu eich eitem(au) - Cysylltwch ag aelod o staff" renew_fail = "Ni ellir adnewyddu'r eitem hon" renew_item = "Adnewyddu Eitem" renew_item_due = "Eitem yn ddyledus o fewn y 24 awr nesaf" +renew_item_due_tooltip = "Eitemau i’w dychwelyd yn fuan" renew_item_limit = "Mae'r eitem hon wedi cyrraedd ei therfyn adnewyddu" renew_item_no = "Nid oes modd adnewyddu'r eitem hon" renew_item_overdue = "Eitem yn Orddyledus" +renew_item_overdue_tooltip = "Eitemau hwyr" renew_item_requested = "Mae'r eitem hon wedi'i geisio gan ddefnyddiwr arall" renew_select_box = "Adnewyddu Eitem" renew_selected = "Adnewyddu Eitemau a Ddewiswyd" @@ -894,6 +908,7 @@ search_match = "Cyfateb" search_NOT = "NOT" search_OR = "OR" search_save_success = "Cadwyd y chwiliad yn llwyddiannus." +search_terms = "Chwilio termau" search_unsave_success = "Cafwyd gwared ar y chwiliad a gadwyd yn llwyddiannus." seconds_abbrev = "e" see all = "Gweld pob un" @@ -1078,6 +1093,7 @@ Video = "Fideo" Video Clips = "Clipiau Fideo" Videos = "Fideos" View Book Bag = "Dangos Bag Llyfrau" +View Complete Issue = "Gweld y Cyhoeddiad a Gwblhawyd" View Full Collection = "Gweld yr Holl Gasgliad" View Full Record = "Gweld y Cofnod Llawn" View in EDS = "Gweld mewn EDS" diff --git a/languages/da.ini b/languages/da.ini index 767dbd599e899134fbf781b9ccddd87c2d90288d..8e36300fe459fa3c6b2cb6dd5a3c0eb5d03c6358 100644 --- a/languages/da.ini +++ b/languages/da.ini @@ -253,6 +253,8 @@ fav_list_delete_cancel = "Denne liste blev ikke slettet." fav_list_delete_fail = "Vi beklager. Der er sket en fejl. Den liste blev ikke slettet." Favorites = "Favoritter" Fee = "Betaling" +feedback_email = "Email" +feedback_login_required = "Du skal først være logget ind." Find = "Find" Find More = "Find flere" Find New Items = "Find nye værkerâ€" diff --git a/languages/de.ini b/languages/de.ini index c397cf2320e339c60f5e1f0e102c8651a7622f25..65c20885ca2e0c0498a279062349acb22bec1b07 100644 --- a/languages/de.ini +++ b/languages/de.ini @@ -7,6 +7,7 @@ access_denied = "Zugriff nicht erlaubt." Accession Number = "Dokumentencode" Account = "Konto" account_block_options_missing = "Einige Selektionen wurden aufgrund von Einschränkungen Ihres Benutzerkontos entfernt. Details: %%details%%" +account_has_alerts = "Warnmeldungen für ihr Konto vorhanden" Add a Library Card = "Bibliotheksausweis hinzufügen" Add a Note = "Bemerkung hinzufügen" Add Tag = "Tag hinzufügen" @@ -46,6 +47,7 @@ Advanced Search = "Erweiterte Suche" advSearchError_noRights = "Tut mir Leid, aber Sie dürfen die Suche nicht ändern. Vielleicht ist Ihre Sitzung abgelaufen?" advSearchError_notAdvanced = "Die angeforderte Suche ist keine erweiterte Suche und kann nicht editiert werden." advSearchError_notFound = "Die angeforderte Suche wurde nicht gefunden." +ajax_load_interrupted = "Ladevorgang abgebrochen" ajaxview_label_information = "Information" ajaxview_label_tools = "Werkzeuge" All = "Alles" @@ -233,6 +235,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Möchten Sie die ausge Contents = "Inhalte" Contributing Source = "Originalquelle" Contributors = "Weitere Verfasser" +Coordinates = "Koordinaten" Copies = "Exemplare" Copy = "Exemplar" Copyright = "Copyright" @@ -363,6 +366,8 @@ external_auth_heading = "Zugriff auf lizenzpflichtige Inhalte" external_auth_login_message = "Melden Sie sich an, um auf lizenzpflichtige Inhalte zuzugreifen" external_auth_unauthorized = "Sie haben keinen Zugriff auf lizenzpflichtige Inhalte" external_auth_unauthorized_desc = "Ihr aktuelles Login erlaubt keinen Zugriff auf lizenzpflichtige Inhalte. Bitte melden Sie sich ab und verwenden Sie eine andere Art der Anmeldung." +facet_list_empty = "Keine Werte verfügbar" +facet_list_for = "Werte für %%field%%" FAQs = "Häufig gestellte Fragen" fav_delete = "Ausgewählte Favoriten löschen" fav_delete_deleting = "Ihre ausgewählten Favoriten werden gelöscht." @@ -380,6 +385,8 @@ fav_list_delete_fail = "Leider ist ein Fehler aufgetreten. Ihre Liste wurde nich Favorites = "Favoriten" Fee = "Gebühr" Feedback = "Feedback" +feedback_email = "E-Mail" +feedback_login_required = "Bitte loggen Sie sich zuerst ein." feedback_name = "Name" Field of activity = "Tätigkeitsbereich" File Description = "Dateibeschreibung" @@ -391,6 +398,7 @@ Find More = "Weitere Suchoptionen" Find New Items = "Suche Neuerscheinungen" Finding Aid = "Findmittel" Fine = "Gebührengrund" +Fine Date = "Gebührenpflichtiges Verzugsdatum" fine_limit_patron = "Sie haben den Grenzwert für Mahnungen erreicht. Sie können keine Verlängerungen mehr vornehmen" Fines = "Gebühren" First = "Erste" @@ -410,6 +418,7 @@ Geographic Search = "Geografische Suche" Geographic Terms = "Geografische Kategorien" Geography = "Geographie" Get full text = "Volltext" +Get more information = "Weitere Angaben" Get RSS Feed = "RSS-Feed abonnieren" Globe = "Globus" Go = "ausführen" @@ -446,6 +455,7 @@ history_saved_searches = "Ihre gespeicherten Suchanfragen" history_search = "Suche" history_time = "Zeit" hold_available = "Abholbereit" +hold_available_until = "Zur Abholung bereit bis am %%date%%" hold_cancel = "Bestellung annullieren" hold_cancel_all = "Alle Bestellungen annullieren" hold_cancel_fail = "Ihre Bestellung konnte nicht annulliert werden. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe" @@ -584,6 +594,7 @@ Library Catalog Search = "Bibliothekskatalogsuche" Library Catalog Search Result = "Suchergebnis im Bibliothekskatalog" Library Catalog Username = "Benutzername Bibliothekskatalog" Library Web Search = "Bibiothek Internetsuche" +library_card_edit_password_placeholder = "Neues Passwort" lightbox_error = "Fehler: Laden des Popup-Fensters fehlgeschlagen" Limit To = "Eingrenzen" List = "Liste" @@ -825,7 +836,7 @@ Refine Results = "Treffer weiter einschränken" Region = "Region" relais_available = "Das Medium ist per Fernleihe verfügbar. Möchten Sie das Exemplar anfordern?" relais_checking = "Ãœberprüfe Verfügbarkeit..." -relais_error_html = "Bei der Bestellung ist ein Problem aufgetreten. Klicken Sie <a href="%%url%%" target='new'>hier</a> um das Bestellformular für die Fernleihe aufzurufen.</a>" +relais_error_html = "Bei der Bestellung ist ein Problem aufgetreten. Klicken Sie <a href="%%url%%" target='new'>hier</a> um das Bestellformular für die Fernleihe aufzurufen." relais_request = "Bestellung per Fernleihe" relais_requesting = "Anfrage..." relais_search = "Suche für die Fernleihe" @@ -843,9 +854,11 @@ renew_error = "Die Ausleihfrist(en) konnten nicht verlängert werden - Bitte kon renew_fail = "Die Ausleihfrist konnte nicht verlängert werden" renew_item = "Ausleihfrist verlängern" renew_item_due = "Rückgabe innerhalb von 24 Stunden fällig" +renew_item_due_tooltip = "Bald fällige Ausleihen" renew_item_limit = "Maximale Anzahl Verlängerungen für diese Ausleihe erreicht" renew_item_no = "Diese Ausleihfrist kann nicht verlängert werden" renew_item_overdue = "Rückgabe überfällig" +renew_item_overdue_tooltip = "Ãœberfällige Ausleihen" renew_item_requested = "Dieses Medium wurde von einem anderen Benutzer vorgemerkt" renew_select_box = "Ausleihfrist verlängern" renew_selected = "Fristverlängerung der ausgewählten Ausleihen" @@ -894,6 +907,7 @@ search_match = "Suchbedingung" search_NOT = "OHNE die Wörter" search_OR = "Mit IRGENDEINEM der Wörter" search_save_success = "Suche erfolgreich abgespeichert." +search_terms = "Suchbegriffe" search_unsave_success = "Gespeicherte Suche erfolgreich gelöscht." seconds_abbrev = "s" see all = "Alle anzeigen" @@ -1078,6 +1092,7 @@ Video = "Video" Video Clips = "Videoclips" Videos = "Videos" View Book Bag = "Zwischenablage ansehen" +View Complete Issue = "Vollständige Ausgabe ansehen" View Full Collection = "Vollständiger Bestand ansehen" View Full Record = "Vollständigen Datensatz ansehen" View in EDS = "In EDS ansehen" diff --git a/languages/el.ini b/languages/el.ini index 4171aa9048b294285a5ac4bbebb8cd2fffe7ac38..087e67463c455aec7c1f4aeee25619fca100ba32 100644 --- a/languages/el.ini +++ b/languages/el.ini @@ -8,6 +8,7 @@ access_denied = "Δεν επιτÏÎπεται η Ï€Ïόσβαση." Accession Number = "ΑÏιθμός ΚαταχώÏησης" Account = "ΛογαÏιασμός" account_block_options_missing = "ΜεÏικÎÏ‚ επιλογÎÏ‚ δεν εμφανίζονται λόγω πεÏιοÏισμών στον λογαÏιασμό σας. ΛεπτομÎÏειες: %%details%%" +account_has_alerts = "ΥπάÏχουν ειδοποιήσεις στον λογαÏιασμό σας" Add a Library Card = "Î Ïοσθήκη κάÏτας βιβλιοθήκης" Add a Note = "Î Ïοσθήκη σημείωσης" Add Tag = "Î Ïοσθήκη ετικÎτας" @@ -47,6 +48,7 @@ Advanced Search = "ΣÏνθετη αναζήτηση" advSearchError_noRights = "Δεν μποÏείτε να Ï„Ïοποποιήσετε την αναζήτηση (Ï…Ï€ÎÏβαση χÏόνου αναμονής;)" advSearchError_notAdvanced = "Η αναζήτηση που Ï€Ïοσπαθείτε να Ï„Ïοποποιήσετε δεν είναι σÏνθετη" advSearchError_notFound = "Δεν βÏÎθηκαν αποτελÎσματα για την αναζήτησή σας" +ajax_load_interrupted = "Η φόÏτωση διακόπηκε" ajaxview_label_information = "ΠληÏοφοÏίες" ajaxview_label_tools = "ΕÏγαλεία" All = "Όλα" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "ΘÎλετε να ακ Contents = "ΠεÏιεχόμενα" Contributing Source = "Πηγή συνεισφοÏάς" Contributors = "ΣυνεισφοÏÎÏ‚" +Coordinates = "ΣυντεταγμÎνες" Copies = "ΑντίγÏαφα" Copy = "ΑντίγÏαφο" Copyright = "Copyright" @@ -364,6 +367,8 @@ external_auth_heading = "Î Ïόσβαση σε αδειοδοτημÎνο υλι external_auth_login_message = "Συνδεθείτε για να Îχετε Ï€Ïόσβαση σε αδειοδοτημÎνο υλικό" external_auth_unauthorized = "Δεν Îχετε δικαίωμα Ï€Ïόσβασης σε αδειοδοτημÎνο υλικό" external_auth_unauthorized_desc = "Ο Ï„ÏÎχων λογαÏιασμός δεν Îχει δικαίωμα Ï€Ïόσβασης σε αδειοδοτημÎνο υλικό. Αποσυνδεθείτε και συνδεθείτε με τον κατάλληλο λογαÏιασμό." +facet_list_empty = "Δεν βÏÎθηκαν δεδομÎνα" +facet_list_for = "Λίστα φίλτÏων για %%field%%" FAQs = "Ρωτήστε μας" fav_delete = "ΔιαγÏαφή επιλεγμÎνων αγαπημÎνων" fav_delete_deleting = "ΔιαγÏαφή των αγαπημÎνων σας" @@ -381,6 +386,8 @@ fav_list_delete_fail = "ΠαÏουσιάστηκε σφάλμα. Η λίστα Favorites = "ΑγαπημÎνα" Fee = "ΧÏÎωση" Feedback = "Σχόλιά" +feedback_email = "ΗλεκτÏονικό ταχυδÏομείο" +feedback_login_required = "Î ÏÎπει Ï€Ïώτα να συνδεθείτε." feedback_name = "Όνομα" Field of activity = "Πεδίο δÏαστηÏιότητας" File Description = "ΠεÏιγÏαφή αÏχείου" @@ -392,6 +399,7 @@ Find More = "Î’Ïείτε πεÏισσότεÏα" Find New Items = "Î’Ïείτε νÎα τεκμήÏια" Finding Aid = "Βοήθεια αναζήτησης" Fine = "Î Ïόστιμο" +Fine Date = "ΗμεÏομηνία Î Ïοστίμου" fine_limit_patron = "Δεν μποÏείτε να κάνεντε ανανÎωση. Έχετε υπεÏβεί το ÏŒÏιο Ï€Ïοστίμων" Fines = "Î Ïόστιμα" First = "Î Ïώτη" @@ -411,6 +419,7 @@ Geographic Search = "ΓεωγÏαφική αναζήτηση" Geographic Terms = "ΓεωγÏαφικοί ÏŒÏοι" Geography = "ΓεωγÏαφία" Get full text = "Λήψη πλήÏους κειμÎνου" +Get more information = "Λάβετε πεÏισσότεÏες πληÏοφοÏίες" Get RSS Feed = "Λήψη RSS" Globe = "Εμφάνιση ΥδÏογείου" Go = "ΈναÏξη" @@ -447,6 +456,7 @@ history_saved_searches = "ΑποθηκευμÎνες Αναζητήσεις Ισ history_search = "Αναζήτηση ΙστοÏικοÏ" history_time = "ÎÏα ΙστοÏικοÏ" hold_available = "ΔιαθÎσιμο" +hold_available_until = "ΔιαθÎσιμο για παÏαλαβή μÎχÏι %%date%%" hold_cancel = "ΑκÏÏωση κÏάτησης" hold_cancel_all = "ΑκÏÏωση όλων των κÏατήσεων" hold_cancel_fail = "Το αίτημά σας δεν ακυÏώθηκε. Απευθυνθείτε στην εξυπηÏÎτηση για βοήθεια" @@ -510,6 +520,7 @@ ill_request_processed = "ΕπεξεÏγασμÎνο" ill_request_profile_html = "Για πληÏοφοÏίες σχετικά με τον διαδανεισμό, συνδεθείτε με τον <a href="%%url%%">λογαÏιασμό</a> της Βιβλιοθήκης σας." ill_request_submit_text = "Υποβολή αιτήματος" Illustrated = "ΕικονογÏαφημÎνο" +ils_account_create_error = "Ο λογαÏιασμός σας δεν καταχωÏήθηκε στο σÏστημα διαχείÏισης βιβλιοθήκης. Αν το Ï€Ïόβλημα παÏαμÎνει, απευθυνθείτε στη βιβλιοθήκη σας." ils_action_unavailable = "Η λειτουÏγία που επιλÎξατε δεν είναι διαθÎσιμη για τη συγκεκÏιμÎνη κάÏτα βιβλιοθήκης" ils_connection_failed = "Ο κατάλογος της βιβλιοθήκης βÏίσκεται σε κατάσταση συντήÏησης." ils_offline_holdings_message = "Η κατάσταση των τεκμηÏίων δεν είναι διαθÎσιμη αυτή τη στιγμή. ΖητοÏμε συγγνώμη για το Ï€Ïόβλημα. Επικοινωνήστε μαζί μας αν χÏειάζεστε βοήθεια:" @@ -584,6 +595,7 @@ Library Catalog Search = "Αναζήτηση στον κατάλογο της β Library Catalog Search Result = "ΑποτÎλεσμα καταλόγου βιβλιοθήκης" Library Catalog Username = "Όνομα ΧÏήστη καταλόγου βιβλιοθήκης" Library Web Search = "Αναζήτηση ιστοσελίδων βιβλιοθήκης" +library_card_edit_password_placeholder = "ÎÎος κωδικός" lightbox_error = "Σφάλμα. Αδυναμία φόÏτωσης αναδυόμενου παÏαθÏÏου" Limit To = "ΠεÏιοÏισμός σε" List = "Λίστα" @@ -843,9 +855,11 @@ renew_error = "Δεν είναι δυνατή η ανανÎωση του τεκ renew_fail = "Η ανανÎωση του τεκμηÏίου απÎτυχε" renew_item = "ΑνανÎωση τεκμηÏίου" renew_item_due = "Το τεκμήÏιο θα Ï€ÏÎπει να επιστÏαφεί μÎσα στο επόμενο 24ωÏο" +renew_item_due_tooltip = "ΤεκμήÏια για άμεση επιστÏοφή" renew_item_limit = "Το τεκμήÏιο αυτό δεν μποÏεί να ανανεωθεί. Έχετε υπεÏβεί τον αÏιθμό ανανεώσεων" renew_item_no = "Το τεκμήÏιο αυτό δεν μποÏεί να ανανεωθεί" renew_item_overdue = "Το τεκμήÏιο είναι εκπÏόθεσμο" +renew_item_overdue_tooltip = "ΕκπÏόθεσμα τεκμήÏια" renew_item_requested = "Το τεκμήÏιο αυτό Îχει ζητηθεί από άλλο χÏήστη" renew_select_box = "ΑνανÎωση τεκμηÏίου" renew_selected = "ΑνανÎωση επιλεγμÎνων τεκμηÏίων" @@ -894,6 +908,7 @@ search_match = "Îα πεÏιλαμβάνονται" search_NOT = "κανÎνας" search_OR = "οποιοσδήποτε" search_save_success = "Η αναζήτηση αποθηκεÏτηκε επιτυχώς." +search_terms = "ÎŒÏοι αναζήτησης" search_unsave_success = "Η αποθηκευμÎνη αναζήτηση διαγÏάφηκε επιτυχώς." seconds_abbrev = "δλ" see all = "Î Ïοβολή όλων" @@ -1078,6 +1093,7 @@ Video = "Βίντεο" Video Clips = "Βιντεοκλιπ" Videos = "Βίντεο" View Book Bag = "Î Ïοβολή καλαθιοÏ" +View Complete Issue = "Δείτε την πλήÏη Îκδοση" View Full Collection = "Εμφάνιση ολόκληÏης της συλλογής" View Full Record = "Εμφάνιση ολόκληÏης της εγγÏαφής" View in EDS = "Î Ïοβολή σε EDS" diff --git a/languages/en.ini b/languages/en.ini index ef5698ecd00740b4f3511bc91ca309e21abf042a..a0efcc79c4a9bc62e06ae0b27532bbaf95dffc96 100644 --- a/languages/en.ini +++ b/languages/en.ini @@ -7,6 +7,7 @@ access_denied = "Access denied." Accession Number = "Accession Number" Account = "Account" account_block_options_missing = "Some choices have been removed due to a block on your account. Details: %%details%%" +account_has_alerts = "Your account has alerts" Add a Library Card = "Add a Library Card" Add a Note = "Add a Note" Add Tag = "Add Tag" @@ -46,6 +47,7 @@ Advanced Search = "Advanced Search" advSearchError_noRights = "I'm sorry, but you don't have permission to edit that search. Perhaps your browser session has expired?" advSearchError_notAdvanced = "The search you have requested to edit is not an advanced search." advSearchError_notFound = "The search you have requested was not found." +ajax_load_interrupted = "Loading interrupted" ajaxview_label_information = "Information" ajaxview_label_tools = "Tools" All = "All" @@ -364,6 +366,8 @@ external_auth_heading = "Access to licensed material" external_auth_login_message = "Login to access licensed material" external_auth_unauthorized = "You are not authorized to access licensed material" external_auth_unauthorized_desc = "Your login method does not provide access to licensed material. Please log out and then log in using another method." +facet_list_empty = "No data available" +facet_list_for = "Facet list for %%field%%" FAQs = "FAQs" fav_delete = "Delete Selected Favorites" fav_delete_deleting = "Your favorite(s) are being deleted." @@ -381,6 +385,8 @@ fav_list_delete_fail = "Sorry, an error has occurred. Your list was not deleted. Favorites = "Saved Items" Fee = "Fee" Feedback = "Feedback" +feedback_email = "Email" +feedback_login_required = "You must be logged in first." feedback_name = "Name" Field of activity = "Field of activity" File Description = "File Description" @@ -392,6 +398,7 @@ Find More = "Find More" Find New Items = "Find New Items" Finding Aid = "Finding Aid" Fine = "Fine" +Fine Date = "Fine Date" fine_limit_patron = "You have reached your fines limit and cannot renew items" Fines = "Fines" First = "First" @@ -411,6 +418,7 @@ Geographic Search = "Geographic Search" Geographic Terms = "Geographic Terms" Geography = "Geography" Get full text = "Get full text" +Get more information = "Get more information" Get RSS Feed = "Get RSS Feed" Globe = "Globe" Go = "Go" @@ -447,6 +455,7 @@ history_saved_searches = "Saved Searches" history_search = "Search" history_time = "Time" hold_available = "Available for Pickup" +hold_available_until = "Available for Pickup Until %%date%%" hold_cancel = "Cancel Hold" hold_cancel_all = "Cancel All Holds" hold_cancel_fail = "Your request was not canceled. Please contact the circulation desk for further assistance" @@ -585,6 +594,7 @@ Library Catalog Search = "Library Catalog Search" Library Catalog Search Result = "Library Catalog Search Result" Library Catalog Username = "Library Catalog Username" Library Web Search = "Library Web Search" +library_card_edit_password_placeholder = "New Password" lightbox_error = "Error: Cannot Load Popup Box" Limit To = "Limit To" List = "List" @@ -827,7 +837,7 @@ Refine Results = "Refine Results" Region = "Region" relais_available = "This item is available through Interlibrary Loan. Would you like to request it?" relais_checking = "Checking availability..." -relais_error_html = "There was a problem with this request. Click <a href="%%url%%" target='new'>here</a> to request this item using the Interlibrary Loan website.</a>" +relais_error_html = "There was a problem with this request. Please request this item using the <a href="%%url%%" target='new'>Interlibrary Loan website</a>." relais_request = "Interlibrary Loan Request" relais_requesting = "Requesting..." relais_search = "Search Interlibrary Loan" @@ -845,9 +855,11 @@ renew_error = "We were unable to renew your item(s) - Please contact a member of renew_fail = "This item could not be renewed" renew_item = "Renew Item" renew_item_due = "Item due within the next 24 hours" +renew_item_due_tooltip = "Items due soon" renew_item_limit = "This item has reached its renewal limit" renew_item_no = "This item cannot be renewed" renew_item_overdue = "Item Overdue" +renew_item_overdue_tooltip = "Items overdue" renew_item_requested = "This item has been requested by another user" renew_select_box = "Renew Item" renew_selected = "Renew Selected Items" @@ -896,6 +908,7 @@ search_match = "Match" search_NOT = "NO Terms" search_OR = "ANY Terms" search_save_success = "Search saved successfully." +search_terms = "Search terms" search_unsave_success = "Saved search removed successfully." seconds_abbrev = "s" see all = "see all" @@ -1080,6 +1093,7 @@ Video = "Video" Video Clips = "Video Clips" Videos = "Videos" View Book Bag = "View Book Bag" +View Complete Issue = "View Complete Issue" View Full Collection = "View Full Collection" View Full Record = "View Full Record" View in EDS = "View in EDS" diff --git a/languages/es.ini b/languages/es.ini index 0f2309e4c1c7cb5d1abf80e3e84d87f534a45a20..9b5c9c091ebd7c24c9da3270f60924751a405604 100644 --- a/languages/es.ini +++ b/languages/es.ini @@ -8,6 +8,7 @@ access_denied = "Acceso Denegado" Accession Number = "Número de Acceso" Account = "Cuenta" account_block_options_missing = "Algunas opciones se han eliminado debido a un bloqueo en su cuenta. Detalles: %%details%%" +account_has_alerts = "Tu cuenta tiene alertas" Add a Library Card = "Agregar una Tarjeta de la Biblioteca" Add a Note = "Agregar Nota" Add Tag = "Agregar Etiqueta" @@ -47,6 +48,7 @@ Advanced Search = "Búsqueda Avanzada" advSearchError_noRights = "Lo sentimos, no tiene permisos para editar la búsqueda. Tal vez ha expirado la sesión en su navegador." advSearchError_notAdvanced = "La búsqueda solicitada para editar no es Avanzada." advSearchError_notFound = "No se ha encontrado la búsqueda solicitada." +ajax_load_interrupted = "Carga interrumpida" ajaxview_label_information = "Información" ajaxview_label_tools = "Herramientas" All = "Todo" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "¿Desea cancelar sus s Contents = "Contenido" Contributing Source = "Fuente de Contibución" Contributors = "Colaboradores" +Coordinates = "Coordenadas" Copies = "Copias" Copy = "Copia" Copyright = "Derechos de autor" @@ -364,6 +367,8 @@ external_auth_heading = "Acceso a material licenciado" external_auth_login_message = "Iniciar sesión para acceder a material licenciado" external_auth_unauthorized = "No está autorizado para acceder a material licenciado" external_auth_unauthorized_desc = "Su método de acceso no proporciona acceso a material licenciado. Por favor, cierre la sesión y luego inicie utilizando otro método" +facet_list_empty = "Datos no disponibles" +facet_list_for = "Lista de facetas para %%field%%" FAQs = "Preguntas Frecuentes" fav_delete = "Borrar Favoritos Seleccionados" fav_delete_deleting = "Sus favoritos están siendo eliminados." @@ -381,6 +386,8 @@ fav_list_delete_fail = "Lo sentimos, un error ha ocurrido. Su lista no ha sido b Favorites = "Favoritos" Fee = "Cuota" Feedback = "Comentarios" +feedback_email = "Correo Electrónico" +feedback_login_required = "Primero debe ingresar al sistema." feedback_name = "Nombre" Field of activity = "Campo de actividad" File Description = "Descripción del Archivo" @@ -392,6 +399,7 @@ Find More = "Buscar Más" Find New Items = "Buscar Nuevos Ejemplares" Finding Aid = "Encontrar Ayuda" Fine = "Multa" +Fine Date = "Fecha de Multa" fine_limit_patron = "Ha llegado al lÃmite de multas, no puede renovar" Fines = "Multas" First = "Primero" @@ -411,6 +419,7 @@ Geographic Search = "Búsqueda Geográfica" Geographic Terms = "Términos Geográficos" Geography = "GeografÃa" Get full text = "Enlace del recurso" +Get more information = "Obtener mas informacion" Get RSS Feed = "RSS" Globe = "Global" Go = "ir" @@ -447,6 +456,7 @@ history_saved_searches = "Sus Búsquedas Guardadas" history_search = "Buscar" history_time = "Tiempo" hold_available = "Disponible para llevar" +hold_available_until = "Disponible para recoger hasta %%date%%" hold_cancel = "Cancelar reserva" hold_cancel_all = "Cancelar todas las reservas" hold_cancel_fail = "Su solicitud no ha sido cancelada, por favor contactar con el mostrador de circulación para más ayuda" @@ -510,6 +520,7 @@ ill_request_processed = "Procesado" ill_request_profile_html = "Para información de solicitud de préstamo interbibliotecario, por favor establecer su <a href="%%url%%">Perfil del Catálogo de la biblioteca</a>" ill_request_submit_text = "Lugar de Solicitud" Illustrated = "Ilustrado" +ils_account_create_error = "No se pudo crear su cuenta en nuestro sistema de administración de bibliotecas. Si el problema persiste, comunÃquese con su biblioteca"." ils_action_unavailable = "La función solicitada no está disponible con la tarjeta de biblioteca activa." ils_connection_failed = "Nuestro Sistema de Biblioteca se encuentra en mantenimiento." ils_offline_holdings_message = "En este momento no hay información de existencias y disponibilidad de copias. Por favor acepte nuestras disculpas por los inconvenientes causados, contáctenos para una mayor información." @@ -584,6 +595,7 @@ Library Catalog Search = "Búsqueda en el catálogo" Library Catalog Search Result = "Resultados de Búsqueda del Catálogo" Library Catalog Username = "Nombre de usuario del Catálog" Library Web Search = "Búsqueda en internet de la Biblioteca" +library_card_edit_password_placeholder = "Nueva Contraseña" lightbox_error = "Error: No se puede cargar el cuadro de diálogo emergente" Limit To = "Limitar" List = "Lista" @@ -843,9 +855,11 @@ renew_error = "No podemos renovar los elementos – Contactar con un miembro del renew_fail = "Este elemento no puede ser renovado" renew_item = "Renovar elemento" renew_item_due = "Vence en 24 horas" +renew_item_due_tooltip = "Items por vencer pronto" renew_item_limit = "Ha alcanzado el máximo de renovaciones para este elemento" renew_item_no = "Este elemento no puede ser renovado" renew_item_overdue = "Vencimientos" +renew_item_overdue_tooltip = "Items vencidos" renew_item_requested = "Este elemento ha sido solicitado por otro usuario" renew_select_box = "Renovar elemento" renew_selected = "Renovar elementos seleccionados" @@ -894,6 +908,7 @@ search_match = "Coincide" search_NOT = "Sin términos" search_OR = "Cualquier término" search_save_success = "Búsqueda guardada exitosamente" +search_terms = "Términos de búsqueda" search_unsave_success = "Búsqueda guardada ha sido eliminada con éxito" seconds_abbrev = "s" see all = "ver todos" @@ -1078,6 +1093,7 @@ Video = "Video" Video Clips = "Video Clips" Videos = "Videos" View Book Bag = "Ver Mochila" +View Complete Issue = "Ver Número Completo" View Full Collection = "Ver colección completa" View Full Record = "Ver registro completo" View in EDS = "Vista en EDS" diff --git a/languages/eu.ini b/languages/eu.ini index 629f2fab457fb0f72961d21412fbb656e99a5775..c74c5841c1b2c46f22e8892542b2e4e8885a5e23 100644 --- a/languages/eu.ini +++ b/languages/eu.ini @@ -1001,6 +1001,8 @@ fav_list_delete_fail = "Errorea gertatu da. Ez dugu zure zerrenda ezabatu." Favorites = "Gogokoenak" Fee = "Kuota" Feedback = "Feedback" +feedback_email = "Posta elektronikoa" +feedback_login_required = "Lehenik saioa ireki behar duzu." feedback_name = "Feedback-Izena" Field of activity = "Jarduera-eremua" File Description = "Fitxategi deskribapena" @@ -1204,6 +1206,7 @@ Library Catalog Search = "Bilatu Liburutegiko Katalogoan" Library Catalog Search Result = "Katalogoan egindako bilaketaren emaitzak" Library Catalog Username = "Erabiltzailea" Library Web Search = "Liburutegiaren web bilaketa" +library_card_edit_password_placeholder = "Pasahitza berria" lightbox_error = "Errorea: ezin da kargatu" Limit To = "Bilaketa zehaztu" List = "Zerrenda" diff --git a/languages/fi.ini b/languages/fi.ini index 84e21ab0b20d264878a2ba87c9e0c9db2d9975b3..20c1fcfd8ab0cba1c6b64b562fdc14c3363bc031 100644 --- a/languages/fi.ini +++ b/languages/fi.ini @@ -6,6 +6,7 @@ access_denied = "Pääsy estetty." Accession Number = "Hankintanumero" Account = "Tili" account_block_options_missing = "Joitakin toimintoja ei näytetä, koska olet lainaus- tai varauskiellossa. Lisätiedot: %%details%%" +account_has_alerts = "Tililläsi on huomioitavaa" Add a Library Card = "Lisää kirjastokortti" Add a Note = "Lisää merkintä" Add Tag = "Lisää tagi" @@ -45,6 +46,7 @@ Advanced Search = "Tarkennettu haku" advSearchError_noRights = "Haun muokkaus epäonnistui. Epäonnistuminen voi johtua vanhentuneesta selainistunnosta." advSearchError_notAdvanced = "Muokkaamasi haku ei ole tarkennettu haku." advSearchError_notFound = "Hakua ei löydy." +ajax_load_interrupted = "Lataus keskeytyi" ajaxview_label_information = "Tietoa" ajaxview_label_tools = "Työkalut" All = "Kaikki" @@ -232,6 +234,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Haluatko perua valitse Contents = "Sisältö" Contributing Source = "Osallistuva lähde" Contributors = "Muut tekijät" +Coordinates = "Koordinaatit" Copies = "Niteet" Copy = "Nide" Copyright = "Copyright" @@ -368,6 +371,8 @@ external_auth_heading = "Pääsy lisensioituun aineistoon" external_auth_login_message = "Kirjaudu sisään päästäksesi lisensioituun aineistoon" external_auth_unauthorized = "Sinulla ei ole käyttöoikeutta lisensioituun aineistoon" external_auth_unauthorized_desc = "Käyttämälläsi kirjautumistavalla ei ole pääsyä lisensioituun aineistoon. Kirjaudu ensin ulos ja käytä sitten toista kirjautumistapaa." +facet_list_empty = "Ei tietoja" +facet_list_for = "Fasettilista: %%field%%" FAQs = "UKK:t" fav_delete = "Poista valitut suosikit" fav_delete_deleting = "Suosikkejasi poistetaan" @@ -385,6 +390,8 @@ fav_list_delete_fail = "Tapahtui virhe. Listaa ei poistettu." Favorites = "Suosikit" Fee = "Maksu" Feedback = "Palaute" +feedback_email = "Sähköposti" +feedback_login_required = "Kirjaudu sisään ensin." feedback_name = "Nimi" Field of activity = "Toimiala" File Description = "Tiedoston kuvaus" @@ -396,6 +403,7 @@ Find More = "Hae lisää" Find New Items = "Uutuusluettelo" Finding Aid = "Hakemisto" Fine = "Maksu" +Fine Date = "Kirjauspäivämäärä" fine_limit_patron = "Lainojen uusiminen ei onnistu, koska maksamattomia maksuja on liikaa" Fines = "Maksut" First = "Ensimmäinen" @@ -415,6 +423,7 @@ Geographic Search = "Maantieteellinen haku" Geographic Terms = "Maantieteelliset termit" Geography = "Maantieteellinen" Get full text = "Hae kokoteksti" +Get more information = "Lisätietoa" Get RSS Feed = "RSS-syöte" Globe = "Karttapallo" Go = "Siirry" @@ -451,6 +460,7 @@ history_saved_searches = "Tallennetut haut" history_search = "Haku" history_time = "Aika" hold_available = "Noudettavissa" +hold_available_until = "Noudettavissa - noudettava viimeistään %%date%%" hold_cancel = "Peru varaus" hold_cancel_all = "Peru kaikki varaukset" hold_cancel_fail = "Varaustasi ei peruttu. Ota yhteyttä kirjaston asiakaspalveluun." @@ -508,12 +518,13 @@ ill_request_pick_up_library = "Noutokirjasto" ill_request_pick_up_location = "Noutopaikka" ill_request_place_fail_missing = "Tilaus epäonnistui puuttuvien tietojen vuoksi. Ota yhteyttä kirjaston asiakaspalveluun." ill_request_place_success = "Kaukolainatilaus onnistui" -ill_request_place_success_html = "Kaukolainatilaus onnistui <a href="%%url%%">Kaukolainatilaukset</a>." +ill_request_place_success_html = "Kaukolainatilaus onnistui. <a href="%%url%%">Kaukolainatilaukset</a>." ill_request_place_text = "Tee kaukolainatilaus" ill_request_processed = "Käsitelty" ill_request_profile_html = "Kirjaudu <a href="%%url%%">kirjastokortilla</a> nähdäksesi kaukolainatilaukset." ill_request_submit_text = "Tee kaukolainatilaus" Illustrated = "Kuvitus" +ils_account_create_error = "Tiliä ei voitu luoda kirjastojärjestelmään. Jos ongelma jatkuu, ota yhteyttä kirjastoon.Your account could not be created in our library management system." ils_action_unavailable = "Toiminto ei ole saatavissa käytössä olevalla kirjastokortilla." ils_connection_failed = "Kirjastojärjestelmään ei saatu yhteyttä. Tietoja, jotka liittyvät tiliisi kirjastossa, ei voida näyttää. Jos ongelma jatkuu, ota yhteyttä kirjastoon." ils_offline_holdings_message = "Saatavuustiedot eivät ole juuri nyt käytettävissä. Pahoittelemme tästä aiheutunutta vaivaa. Voitte ottaa yhteyttä:" @@ -588,6 +599,7 @@ Library Catalog Search = "Haku kirjastoluettelosta" Library Catalog Search Result = "Hakutulokset" Library Catalog Username = "Kirjastokortin tunnus" Library Web Search = "Web-haku" +library_card_edit_password_placeholder = "Uusi salasana" lightbox_error = "Virhe: Ponnahdusikkunan lataaminen epäonnistui." Limit To = "Rajaukset" List = "Lista" @@ -827,6 +839,14 @@ recovery_user_not_found = "Tiliäsi ei löytynyt" rectangle_center_message = "Valitun alueen keskikohta" Refine Results = "Tarkenna hakua" Region = "Alue" +relais_available = "Aineisto on saatavissa kaukolainana. Haluatko tehdä kaukolainapyynnön?" +relais_checking = "Tarkistetaan saatavuutta..." +relais_error_html = "Pyyntö epäonnistui. Tee pyyntö <a href="%%url%%" target='new'>kaukolainauspalvelun sivuilla.</a>" +relais_request = "Kaukopalvelupyyntö" +relais_requesting = "Pyyntöä lähetetään..." +relais_search = "Kaukopalveluhaku" +relais_success_label = "Vahvistus:" +relais_success_message = "Pyyntö tehty tunnuksella #%%id%%. Saat vahvistuksen sähköpostilla." Related Author = "Liittyvä tekijä" Related Items = "Liittyvät tietueet" Related Subjects = "Liittyvät aiheet" @@ -839,9 +859,11 @@ renew_error = "Lainojasi ei voitu uusia. Ota yhteyttä kirjaston asiakaspalveluu renew_fail = "Lainaa ei voitu uusia" renew_item = "Uusi laina" renew_item_due = "Laina-aikaa jäljellä alle vuorokausi" +renew_item_due_tooltip = "Laina-aika päättyy pian" renew_item_limit = "Tämän lainan uusimiskerrat ovat tulleet täyteen" renew_item_no = "Tätä lainaa ei voida uusia" renew_item_overdue = "Laina on myöhässä" +renew_item_overdue_tooltip = "Lainoja myöhässä" renew_item_requested = "Varattu toiselle asiakkaalle" renew_select_box = "Uusi laina" renew_selected = "Uusi valitut lainat" @@ -890,6 +912,7 @@ search_match = "Hae" search_NOT = "Ehtoihin sisältymättömät (NOT)" search_OR = "Millä tahansa ehdoista (OR)" search_save_success = "Haku tallennettu." +search_terms = "Hakuehdot" search_unsave_success = "Haku poistettu." seconds_abbrev = "s" see all = "näytä kaikki" @@ -976,7 +999,7 @@ storage_retrieval_request_invalid_pickup = "Valittu noutopaikka on virheellinen. storage_retrieval_request_issue = "Päiväys" storage_retrieval_request_place_fail_missing = "Tilaus epäonnistui puuttuvien tietojen vuoksi. Ota yhteyttä kirjaston asiakaspalveluun." storage_retrieval_request_place_success = "Varastotilaus onnistui" -storage_retrieval_request_place_success_html = "Varastotilaus onnistui <a href="%%url%%">Varastotilaukset</a>." +storage_retrieval_request_place_success_html = "Varastotilaus onnistui. <a href="%%url%%">Varastotilaukset</a>." storage_retrieval_request_place_text = "Tee varastotilaus" storage_retrieval_request_processed = "Käsitelty" storage_retrieval_request_profile_html = "Kirjaudu <a href="%%url%%">kirjastokortilla</a> nähdäksesi varastotilaukset." @@ -1074,6 +1097,7 @@ Video = "Video" Video Clips = "Videoleikkeet" Videos = "Videot" View Book Bag = "Näytä kirjakori" +View Complete Issue = "Näytä koko numero" View Full Collection = "Näytä koko kokoelma" View Full Record = "Näytä koko tietue" View in EDS = "Näytä EDS:ssä" diff --git a/languages/fr.ini b/languages/fr.ini index 548303f33b70dfac06dc49c3bfba17f094fa557a..009ad3473ae61ceb5048fec03955949e382c71b8 100644 --- a/languages/fr.ini +++ b/languages/fr.ini @@ -7,6 +7,7 @@ access_denied = "Accès non autorisé." Accession Number = "Numéro d'inventaire" Account = "Compte lecteur" account_block_options_missing = "Certains choix ont été retirés en raison d'un blocage sur votre compte. Détails : %%details%%" +account_has_alerts = "Il y a des alertes sur votre compte" Add a Library Card = "Ajouter une carte de bibliothèque" Add a Note = "Ajouter une observation" Add Tag = "Ajouter un tag" @@ -46,6 +47,7 @@ Advanced Search = "Recherche avancée" advSearchError_noRights = "Désolé, mais vous n'avez pas le droit de changer cette recherche. Peut-être que la session n'est plus valable ?" advSearchError_notAdvanced = "La recherche choisie ne peut pas être éditée." advSearchError_notFound = "La recherche demandée n'existe pas." +ajax_load_interrupted = "Chargement interrompu" ajaxview_label_information = "Information" ajaxview_label_tools = "Outils" All = "Tout" @@ -233,6 +235,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Souhaitez-vous annuler Contents = "Contenu" Contributing Source = "Sources" Contributors = "autres auteurs" +Coordinates = "Coordonnées" Copies = "Exemplaires" Copy = "Exemplaire" Copyright = "Copyright" @@ -363,6 +366,8 @@ external_auth_heading = "Accès aux contenus qui font l'objet d'une licence" external_auth_login_message = "Connectez-vous pour accéder aux contenus qui font l'objet d'une licence" external_auth_unauthorized = "Vous n'êtes pas autorisé à accéder aux contenus qui font l'objet d'une licence" external_auth_unauthorized_desc = "Le mode de connexion que vous avez utilisé ne donne pas accès aux contenus qui font l'objet d'une licence. Merci de vous déconnecter et d'utiliser une autre méthode d'authentification." +facet_list_empty = "Pas de valeurs disponibles" +facet_list_for = "Liste des valeurs pour %%field%%" FAQs = "FAQ" fav_delete = "Supprimer les favoris sélectionnés" fav_delete_deleting = "Vos favoris sont supprimés." @@ -380,6 +385,8 @@ fav_list_delete_fail = "Hélas une erreur est survenue. Votre liste n'a pas ét Favorites = "Favoris" Fee = "Frais" Feedback = "Remarques" +feedback_email = "Courriel" +feedback_login_required = "Il faut se connecter d'abord." feedback_name = "Nom" Field of activity = "Domaine d'activité" File Description = "Description du fichier" @@ -391,6 +398,7 @@ Find More = "Autres modes de recherche" Find New Items = "Chercher des nouveautés" Finding Aid = "Aide pour la recherche" Fine = "Amendes" +Fine Date = "Date pour le paiement de l'amende" fine_limit_patron = "Vous avez atteint la limite des amendes et ne pouvez plus renouveler d'emprunt." Fines = "Amendes" First = "Premier" @@ -410,6 +418,7 @@ Geographic Search = "Recherche géographique" Geographic Terms = "Termes géographiques" Geography = "Géographie" Get full text = "Accéder au texte intégral" +Get more information = "Plus d'information" Get RSS Feed = "S'abonner aux flux RSS" Globe = "Globe" Go = "Go" @@ -446,6 +455,7 @@ history_saved_searches = "Recherches sauvegardées" history_search = "Recherche" history_time = "Date" hold_available = "Disponible pour le retrait" +hold_available_until = "Disponible pour le retrait jusqu'au %%date%%" hold_cancel = "Annuler la réservation" hold_cancel_all = "Annuler toutes les réservations" hold_cancel_fail = "Votre réservation n'a pas été annulée. Veuillez contacter la bibliothèque pour plus d'informations." @@ -509,6 +519,7 @@ ill_request_processed = "Traité" ill_request_profile_html = "Pour les informations sur les demandes de prêt entre bibliothèques, merci de créer un <a href="%%url%%">profil dans le catalogue de la bibliothèque</a>." ill_request_submit_text = "Faire une demande" Illustrated = "Illustré" +ils_account_create_error = "Votre compte n'a pas pu être créé dans notre système de gestion de bibliothèque. Si le problème persiste, veuillez contacter votre bibliothèque." ils_action_unavailable = "La fonctionnalité demandée n'est pas disponible avec la carte de bibliothèque utilisée." ils_connection_failed = "Notre système de gestion de bibliothèque est en cours de maintenance." ils_offline_holdings_message = "Les réservations et la disponibilité des documents sont momentanément indisponibles. Veuillez nous excuser pour la gêne occasionnée et nous contacter pour toute assistance :" @@ -583,6 +594,7 @@ Library Catalog Search = "Recherche dans le catalogue de la bibliothèque" Library Catalog Search Result = "Résultat de la recherche dans le catalogue de la bibliothèque" Library Catalog Username = "Nom d'utilisateur du catalogue de la bibliothèque" Library Web Search = "Recherche sur le site de la bibliothèque" +library_card_edit_password_placeholder = "Nouveau mot de passe" lightbox_error = "Erreur: impossible d'ouvrir la pop-up" Limit To = "Limiter à " List = "Liste" @@ -842,9 +854,11 @@ renew_error = "Nous n'avons pas pu prolonger ce(s) prêt(s). Veuillez contacter renew_fail = "Ce prêt n'a pu être prolongé" renew_item = "Prolonger un prêt" renew_item_due = "Documents à rendre dans les 24 heures" +renew_item_due_tooltip = "Emprunts à échéance proche" renew_item_limit = "Pour ce document le nombre maximal de prolongations de prêt est atteint" renew_item_no = "Le prêt de ce document ne peut être prolongé" renew_item_overdue = "Document en retard" +renew_item_overdue_tooltip = "Emprunts en retard" renew_item_requested = "Ce document a été réservé par un autre usager" renew_select_box = "Prolonger le prêt de ce document" renew_selected = "Prolonger le prêt des documents sélectionnés" @@ -893,6 +907,7 @@ search_match = "Correspondances" search_NOT = "Aucun terme" search_OR = "Un des termes" search_save_success = "Recherche enregistrée avec succès." +search_terms = "Termes de la recherche" search_unsave_success = "Recherche supprimée avec succès." seconds_abbrev = "s" see all = "voir tous les " @@ -1077,6 +1092,7 @@ Video = "Vidéo" Video Clips = "vidéo-clips" Videos = "Vidéos" View Book Bag = "Consulter le panier" +View Complete Issue = "Voir le numéro complet" View Full Collection = "Voir la collection complète" View Full Record = "Voir la notice complète" View in EDS = "Voir dans EDS" diff --git a/languages/ga.ini b/languages/ga.ini index 1d9c9d4f863f80999c68c6d39f135c4d1cccb4c2..b32de6baef0e42aa563d1f43f8bf2bdba21e87e2 100644 --- a/languages/ga.ini +++ b/languages/ga.ini @@ -240,6 +240,8 @@ fav_list_delete_cancel = "NÃor scriosadh an liosta seo." fav_list_delete_fail = "Ãr leithscéal, ach tharla earráid. NÃor scriosadh do liosta." Favorites = "Ceanáin" Fee = "Táille" +feedback_email = "RÃomhphost" +feedback_login_required = "Nà mór a bheith logáilte amach i gcónaÃ." Find = "Aimsigh" Find More = "Aimsigh Tuilleadh" Find New Items = "Aimsigh MÃreanna Nua" diff --git a/languages/gl.ini b/languages/gl.ini index 3d49a0d670069da18c0a95024b26fca2333d6c17..71e1d63dbe72ce91ff56fb3b10396beff6f066f7 100644 --- a/languages/gl.ini +++ b/languages/gl.ini @@ -345,6 +345,7 @@ fav_list_delete_fail = "SentÃmolo, ocorreu un erro . A súa lista non foi borra Favorites = "Favoritos" Fee = "Cota" Feedback = "Comentarios" +feedback_email = "Correo Electrónico" feedback_name = "Nome" File Description = "Descrición do Arquivo" Filter = "Filtro" @@ -536,6 +537,7 @@ Library Catalog Search = "Procura no catálogo" Library Catalog Search Result = "Resultados de Procura do Catálogo" Library Catalog Username = "Nome de usuario do Catálogo" Library Web Search = "Procura na internet da Biblioteca" +library_card_edit_password_placeholder = "Nova contrasinal" lightbox_error = "Erro: Non se pode cargar o cadro de diálogo emerxente" Limit To = "Limitar" List = "Lista" diff --git a/languages/he.ini b/languages/he.ini index 436df6167a72434c261d85fab2b60b5af71e4580..748e7f101eb1721b1d042325c25cf2c84befdbc8 100644 --- a/languages/he.ini +++ b/languages/he.ini @@ -275,6 +275,8 @@ fav_list_delete_cancel = "רשימה זו ×œ× × ×ž×—×§" fav_list_delete_fail = "מצטערי×. ×רעה שגי××”. הרשימה שלך ×œ× × ×ž×—×§×”." Favorites = "מועדפי×" Fee = "דמי שימוש" +feedback_email = "דו×ל" +feedback_login_required = "צריך להיות מחובר מר×ש" filter_wildcard = "כל ×חד" Find = "מצ×" Find More = "×ž×¦× ×¢×•×“" diff --git a/languages/it.ini b/languages/it.ini index 858d5aa36e24a4dade22f0f2964707b0167602b5..8b96bd23310375fb14d06eb8e457409c16eb02b5 100644 --- a/languages/it.ini +++ b/languages/it.ini @@ -380,6 +380,7 @@ fav_list_delete_fail = "Ops, si è verificato un errore. La tua lista non è sta Favorites = "Elementi salvati" Fee = "Tariffa" Feedback = "Feedback" +feedback_email = "Email" feedback_name = "Nome" Field of activity = "Campo di attività " File Description = "Descrizione del file" @@ -583,6 +584,7 @@ Library Catalog Search = "Cerca nel catalogo di biblioteca" Library Catalog Search Result = "Risultati della ricerca del catalogo della biblioteca" Library Catalog Username = "Username del catologo della biblioteca" Library Web Search = "Library Web Search" +library_card_edit_password_placeholder = "Nuova Password" lightbox_error = "Errore: i Popup non funzionano" Limit To = "Limita a" List = "Lista" @@ -824,7 +826,7 @@ Refine Results = "Raffina i risultati" Region = "Regione" relais_available = "Questa copia è disponibile attraverso il servizio ILL. Vuoi richiederla?" relais_checking = "Sto controllando la disponibilità ..." -relais_error_html = "C'è un problam con questa richiesta. Clicca <a href="%%url%%" target='new'>qui</a> per richiedere questa copia usando il sito dell'ILL.</a>" +relais_error_html = "C'è un problam con questa richiesta. Clicca <a href="%%url%%" target='new'>qui</a> per richiedere questa copia usando il sito dell'ILL." relais_request = "Richiesta di prestito ILL" relais_requesting = "In richiesta ..." relais_search = "Cerca attraverso l'ILL" diff --git a/languages/ja.ini b/languages/ja.ini index 2d0c1c622ab4a2b7401ea45fb3d7591681ef99d2..1040e5fa9d72960c477879172a3db356c465277d 100644 --- a/languages/ja.ini +++ b/languages/ja.ini @@ -8,6 +8,7 @@ access_denied = "アクセスã§ãã¾ã›ã‚“。" Accession Number = "å—入番å·" Account = "アカウント" account_block_options_missing = "一部ã®é¸æŠžè‚¢ã¯å‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™ã€‚ 詳細: %%details%%" +account_has_alerts = "通知ãŒã‚ã‚Šã¾ã™" Add a Library Card = "図書館カードã®è¿½åŠ " Add a Note = "æ³¨è¨˜è¿½åŠ " Add Tag = "ã‚¿ã‚°è¿½åŠ " @@ -47,6 +48,7 @@ Advanced Search = "詳細検索" advSearchError_noRights = "ã“ã®æ¤œç´¢ã‚’編集ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。セッションãŒåˆ‡ã‚Œã¦ã„ã¾ã›ã‚“ã‹ã€‚" advSearchError_notAdvanced = "編集指定ã—ãŸæ¤œç´¢ã¯è©³ç´°æ¤œç´¢ã§ã¯ã‚ã‚Šã¾ã›ã‚“。" advSearchError_notFound = "指定ã—ãŸæ¤œç´¢ã¯ã‚ã‚Šã¾ã›ã‚“。" +ajax_load_interrupted = "ãƒãƒ¼ãƒ‰ãŒä¸æ–ã•ã‚Œã¾ã—ãŸ" ajaxview_label_information = "æƒ…å ±" ajaxview_label_tools = "ツール" All = "ã™ã¹ã¦" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "é¸æŠžã—ãŸæ‰€è”µæ¤œ Contents = "コンテンツ" Contributing Source = "è²¢çŒ®è€…æƒ…å ±æº" Contributors = "貢献者" +Coordinates = "座標" Copies = "部数" Copy = "所蔵" Copyright = "著作権" @@ -364,6 +367,8 @@ external_auth_heading = "ライセンス資料ã«ã‚¢ã‚¯ã‚»ã‚¹" external_auth_login_message = "ãƒã‚°ã‚¤ãƒ³ã—ã¦ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è³‡æ–™ã«ã‚¢ã‚¯ã‚»ã‚¹" external_auth_unauthorized = "ライセンス資料ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“" external_auth_unauthorized_desc = "ã“ã®ãƒã‚°ã‚¤ãƒ³æ–¹æ³•ã§ã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è³‡æ–™ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¦åˆ¥ã®æ–¹æ³•ã§å†åº¦ãƒã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„。" +facet_list_empty = "該当データãŒã‚ã‚Šã¾ã›ã‚“" +facet_list_for = "%%field%%ã®ãƒ•ã‚¡ã‚»ãƒƒãƒˆãƒªã‚¹ãƒˆ" FAQs = "FAQ" fav_delete = "é¸æŠžã—ãŸãŠæ°—ã«å…¥ã‚Šã‚’削除" fav_delete_deleting = "é¸æŠžã—ãŸãŠæ°—ã«å…¥ã‚Šã‚’削除ä¸ã§ã™ã€‚" @@ -381,6 +386,8 @@ fav_list_delete_fail = "エラーãŒç™ºç”Ÿã—ãŸã®ã§ã€ãƒªã‚¹ãƒˆã‚’削除㧠Favorites = "ãŠæ°—ã«å…¥ã‚Š" Fee = "料金" Feedback = "ã”æ„見" +feedback_email = "メール" +feedback_login_required = "ã“ã®æ“作ã«ã¯ãƒã‚°ã‚¤ãƒ³ãŒå¿…è¦ã§ã™" feedback_name = "ãŠåå‰" Field of activity = "アクテイビティã®ãƒ•ã‚¤ãƒ¼ãƒ«ãƒ‰" File Description = "ファイル記述" @@ -392,6 +399,7 @@ Find More = "ãã®ä»–ã®æ¤œç´¢" Find New Items = "æ–°ç€è³‡æ–™ã®æ¤œç´¢" Finding Aid = "検索ツール" Fine = "延滞金" +Fine Date = "延滞金発生日" fine_limit_patron = "延滞金é™åº¦é¡ã«é”ã—ã¾ã—ãŸã€‚資料ã®æ›´æ–°ã¯ã§ãã¾ã›ã‚“。" Fines = "延滞金" First = "最åˆ" @@ -411,6 +419,7 @@ Geographic Search = "GIS検索" Geographic Terms = "地ç†é …ç›®" Geography = "地ç†åŒºåˆ†" Get full text = "全文ã®å…¥æ‰‹" +Get more information = "より詳ã—ã„æƒ…å ±ã‚’å–å¾—ã™ã‚‹" Get RSS Feed = "RSSフィード" Globe = "地çƒå„€" Go = "実行" @@ -447,6 +456,7 @@ history_saved_searches = "ä¿å˜æ¸ˆã®æ¤œç´¢" history_search = "検索" history_time = "日時" hold_available = "予約å¯èƒ½" +hold_available_until = "%%date%%ã¾ã§ãŠå–ã‚Šç½®ãã—ã¾ã™" hold_cancel = "予約å–消" hold_cancel_all = "ã™ã¹ã¦ã®äºˆç´„å–消" hold_cancel_fail = "予約ã®å–消ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚閲覧係ã«ã”連絡ãã ã•ã„。" @@ -510,6 +520,7 @@ ill_request_processed = "処ç†ä¸" ill_request_profile_html = "ILLリクエストを行ã†ã«ã¯ã€<a href="%%url%%">図書館目録プãƒãƒ•ã‚£ãƒ¼ãƒ«</a>を作æˆã—ã¦ãã ã•ã„。" ill_request_submit_text = "リクエストã®ä¾é ¼" Illustrated = "図表" +ils_account_create_error = "アカウントを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚å•é¡ŒãŒå†ç¾ã™ã‚‹å ´åˆã¯ã€å›³æ›¸é¤¨ã«ã”連絡ãã ã•ã„。" ils_action_unavailable = "ã”希望ã®æ©Ÿèƒ½ã¯ã“ã®å›³æ›¸é¤¨ã‚«ãƒ¼ãƒ‰ã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。" ils_connection_failed = "ç¾åœ¨ã€å›³æ›¸é¤¨ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ ã¯ä¿å®ˆä½œæ¥ä¸ã§ã™ã€‚" ils_offline_holdings_message = "ç¾åœ¨ã€äºˆç´„ã¨è²¸å‡ºæƒ…å ±ã®é–²è¦§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。ã”ä¸ä¾¿ã‚’ãŠã‹ã‘ã—大変申ã—訳ã‚ã‚Šã¾ã›ã‚“。詳細ã¯æ‹…当ã«ã”連絡ãã ã•ã„:" @@ -584,6 +595,7 @@ Library Catalog Search = "図書館目録検索" Library Catalog Search Result = "図書館目録システムã®æ¤œç´¢çµæžœ" Library Catalog Username = "ユーザå" Library Web Search = "図書館ã®Web検索" +library_card_edit_password_placeholder = "新パスワード" lightbox_error = "エラー: ãƒãƒƒãƒ—アップボックスをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“" Limit To = "絞込ã¿" List = "リスト" @@ -843,9 +855,11 @@ renew_error = "æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚閲覧係ã«ã”連絡ãã ã• renew_fail = "æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸ" renew_item = "貸出更新" renew_item_due = "è¿”å´æœŸé™å‰æ—¥" +renew_item_due_tooltip = "è¿”å´æ—¥ãŒè¿‘ã„アイテム" renew_item_limit = "貸出更新ã®åˆ¶é™å›žæ•°ã‚’超ãˆã¾ã—ãŸ" renew_item_no = "ã“ã®è³‡æ–™ã¯æ›´æ–°ã§ãã¾ã›ã‚“" renew_item_overdue = "貸出期é™è¶…éŽ" +renew_item_overdue_tooltip = "è¿”å´æ—¥ã‚’éŽãŽãŸã‚¢ã‚¤ãƒ†ãƒ " renew_item_requested = "ã“ã®è³‡æ–™ã¯ä»–ã®åˆ©ç”¨è€…ã«äºˆç´„ã•ã‚Œã¦ã„ã¾ã™" renew_select_box = "貸出更新" renew_selected = "é¸æŠžè³‡æ–™ã‚’貸出更新" @@ -894,6 +908,7 @@ search_match = "è«–ç†æ¼”ç®—" search_NOT = "å¦å®šï¼ˆNOT)" search_OR = "è«–ç†å’Œï¼ˆOR)" search_save_success = "検索å¼ã‚’ä¿å˜ã—ã¾ã—ãŸã€‚" +search_terms = "æ¤œç´¢é …ç›®" search_unsave_success = "検索å¼ã‚’削除ã—ã¾ã—ãŸã€‚" seconds_abbrev = "秒" see all = "ã™ã¹ã¦è¦‹ã‚‹" @@ -1078,6 +1093,7 @@ Video = "ビデオ" Video Clips = "ビデオクリップ" Videos = "ビデオ" View Book Bag = "図書ãƒãƒƒã‚°ã‚’見る" +View Complete Issue = "å…¨å·ã‚’閲覧" View Full Collection = "全コレクションを閲覧" View Full Record = "全レコードを閲覧" View in EDS = "EDSã§ã®è¡¨ç¤º" diff --git a/languages/native.ini b/languages/native.ini index 1d9a3aa3acb87e6f661fccf8aa2f1b29731a8f3c..7c2f62e7fb51b567516ae98ba7a381e974dee132 100644 --- a/languages/native.ini +++ b/languages/native.ini @@ -27,4 +27,5 @@ Slovene = "slovenÅ¡Äina" Spanish = "Español" Swedish = "Svenska" Turkish = "Türkçe" +Vietnamese = "Tiếng Việt" Welsh = "Cymraeg" diff --git a/languages/nl.ini b/languages/nl.ini index e84ba354b51308d3cefac9379f365ce98aeb6f5f..ed3286e4f0ac82a5628fe2038d9b838f927c4d4a 100644 --- a/languages/nl.ini +++ b/languages/nl.ini @@ -8,6 +8,7 @@ access_denied = "Toegang geweigerd" Accession Number = "Archiefnummer" Account = "Account" account_block_options_missing = "Sommige keuzes werden verwijderd vanwege een blokkering op je account. Meer info: %%details%%" +account_has_alerts = "Je hebt notificaties" Add a Library Card = "Voeg een bibliotheekkaart toe" Add a Note = "Voeg aantekening toe" Add Tag = "Voeg label toe" @@ -47,6 +48,7 @@ Advanced Search = "Uitgebreid zoeken" advSearchError_noRights = "Helaas, je hebt geen toestemming om die zoekopdracht te veranderen. Misschien is jouw browser sessie afgelopen?" advSearchError_notAdvanced = "De zoekopdracht die je wil aanpassen is geen uitgebreide zoekopdracht." advSearchError_notFound = "De zoekopdracht die je vraagt, werd niet gevonden." +ajax_load_interrupted = "Laden werd onderbroken" ajaxview_label_information = "Informatie" ajaxview_label_tools = "Tools" All = "Alle" @@ -234,6 +236,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Wil je zeker jouw gese Contents = "Inhoud" Contributing Source = "Meewerkende bron" Contributors = "Medewerkers" +Coordinates = "Coördinaten" Copies = "Kopieën" Copy = "Kopie" Copyright = "Auteursrecht" @@ -364,6 +367,8 @@ external_auth_heading = "Toegang tot gelicentieerd materiaal" external_auth_login_message = "Log in om toegang te krijgen tot gelicentieerd materiaal" external_auth_unauthorized = "Je bent niet bevoegd om toegang te krijgen tot gelicentieerd materiaal" external_auth_unauthorized_desc = "Jouw manier van inloggen geeft geen toegang tot gelicentieerd materiaal. Log a.u.b. uit en log dan weer in op een andere manier." +facet_list_empty = "Geen gegevens beschikbaar" +facet_list_for = "Gefilterde lijst voor %%field%%" FAQs = "FAQs" fav_delete = "Geselecteerde favorieten wissen" fav_delete_deleting = "Jouw favoriet(en) wordt/worden gewist." @@ -381,6 +386,8 @@ fav_list_delete_fail = "Sorry, er is een fout opgetreden. Jouw lijst werd niet g Favorites = "Favorieten" Fee = "Bijdrage" Feedback = "Feedback" +feedback_email = "Email" +feedback_login_required = "Je moet eerst inloggen." feedback_name = "Naam" Field of activity = "Werkterrein" File Description = "Bestandsbeschrijving" @@ -392,6 +399,7 @@ Find More = "Vind meer" Find New Items = "Zoek nieuwe items" Finding Aid = "Zoek hulp" Fine = "Boete" +Fine Date = "Datum boete" fine_limit_patron = "Je hebt jouw boete limieten overschreden en kunt geen items vernieuwen" Fines = "Boetes" First = "Eerst(e)" @@ -411,6 +419,7 @@ Geographic Search = "Geografische zoekopdracht" Geographic Terms = "Geografische termen" Geography = "Geografie" Get full text = "Volledige tekst" +Get more information = "Meer informatie" Get RSS Feed = "Abonneren op RSS-datastromen" Globe = "Wereldbol" Go = "Ga" @@ -447,6 +456,7 @@ history_saved_searches = "Jouw recent opgeslagen zoekopdrachten" history_search = "Zoekopdracht" history_time = "Tijdstip" hold_available = "Klaar om te worden opgehaald" +hold_available_until = "Voor jou beschikbaar tot %date%" hold_cancel = "Annuleer reservatie" hold_cancel_all = "Annuleer alle reservaties" hold_cancel_fail = "Jouw verzoek werd niet geannuleerd. Contacteer Circulatie voor meer informatie." @@ -510,6 +520,7 @@ ill_request_processed = "Verwerkt" ill_request_profile_html = "Voor meer info over IBL-aanvragen, meld je eerst aan." ill_request_submit_text = "Plaats aanvraag" Illustrated = "Geïllustreerd" +ils_account_create_error = "Je account kon niet worden aangemaakt in ons bibliotheek management systeem. Als dit probleem zich blijft voordoen, contacteer dan je bibliotheek." ils_action_unavailable = "De gevraagde opdracht is niet mogelijk met deze bibliotheekkaart." ils_connection_failed = "Ons bibliotheek beheerssysteem is momenteel in onderhoud." ils_offline_holdings_message = "Reserveringen en beschikbaarheid van items momenteel niet beschikbaar. Met onze excuses. Contacteer ons voor hulp:" @@ -584,6 +595,7 @@ Library Catalog Search = "Zoekopdracht catalogus" Library Catalog Search Result = "Zoekresultaat van de catalogus" Library Catalog Username = "Gebruikersnaam voor catalogus" Library Web Search = "Doorzoek de website van de bibliotheek" +library_card_edit_password_placeholder = "Nieuw wachtwoord" lightbox_error = "Foutmelding: Pop-upvenster kan niet worden geladen" Limit To = "Beperken tot" List = "Lijst" @@ -843,9 +855,11 @@ renew_error = "We kunnen jouw artikel(en) niet vernieuwen - Contacteer alsjeblie renew_fail = "Dit artikel kon niet worden verlengd" renew_item = "Verleng dit artikel" renew_item_due = "Dit artikel moet binnen de 24 uur worden ingeleverd" +renew_item_due_tooltip = "Deze items moeten binnenkort ingeleverd worden" renew_item_limit = "Dit artikel kan niet langer worden verlengd" renew_item_no = "Dit artikel kan niet worden verlengd" renew_item_overdue = "Dit artikel is over tijd" +renew_item_overdue_tooltip = "Deze items zijn te laat" renew_item_requested = "Dit artikel is aangevraagd door een andere gebruiker" renew_select_box = "Verlengen" renew_selected = "Verleng geselecteerde artikelen" @@ -894,6 +908,7 @@ search_match = "Overeenkomst" search_NOT = "GEEN Termen" search_OR = "ANY Terms" search_save_success = "Zoekopdracht succesvol bewaard" +search_terms = "Zoektermen" search_unsave_success = "Bewaarde zoekopdracht succesvol verwijderd" seconds_abbrev = "s" see all = "Bekijk alles" @@ -1078,6 +1093,7 @@ Video = "Video" Video Clips = "Videoclips" Videos = "Video's" View Book Bag = "Bekijk boekentas" +View Complete Issue = "Bekijk het volledige nummer" View Full Collection = "Bekijk volledige collectie" View Full Record = "Bekijk volledig record" View in EDS = "Bekijk in EDS" diff --git a/languages/pl.ini b/languages/pl.ini index 05345b1da770c5bfb7365656a66dcd07103b01d6..9e70c252a1e9cea7ce07e406e965241d3e3a26b8 100644 --- a/languages/pl.ini +++ b/languages/pl.ini @@ -69,6 +69,7 @@ access_denied = "DostÄ™p niedozwolony." Accession Number = "Numer dostÄ™pu" Account = "Konto czytelnika" account_block_options_missing = "Z powodu zablokowania twojego konta niektóre opcje zostaÅ‚y usuniÄ™te. Szczegółowo: %%details%%" +account_has_alerts = "Twoje konto zawiera ostrzeżenia" Add a Library Card = "DoÅ‚Ä…cz kartÄ™ bibliotecznÄ…" Add a Note = "Dodaj adnotacjÄ™" Add Tag = "Dodaj etykietÄ™" @@ -108,6 +109,7 @@ Advanced Search = "Wyszukiwanie zaawansowane" advSearchError_noRights = "Nie możesz zmienić wyszukiwania, skoÅ„czyÅ‚a siÄ™ sesja." advSearchError_notAdvanced = "Nie możesz edytować wyszukiwania. Nie używasz wyszukiwania zaawansowanego." advSearchError_notFound = "Nie znaleziono żądanego wyszukiwania." +ajax_load_interrupted = "Åadowanie zostaÅ‚o przerwane" ajaxview_label_information = "Informacja" ajaxview_label_tools = "NarzÄ™dzia" All = "wszystko" @@ -295,6 +297,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Czy chcesz usunąć za Contents = "Treść" Contributing Source = "ŹródÅ‚o przyczyniajÄ…ce" Contributors = "Kolejni autorzy" +Coordinates = "WspółrzÄ™dne" Copies = "Egzemplarze" Copy = "Egzemplarz" Copyright = "Prawo autorskie" @@ -425,6 +428,8 @@ external_auth_heading = "Logowanie do peÅ‚nego dostÄ™pu" external_auth_login_message = "Zaloguj siÄ™, aby mieć dostÄ™p do e-zasobów licencjonowanych." external_auth_unauthorized = "Nie masz dostÄ™pu do e-zasobów licencjonowanych." external_auth_unauthorized_desc = "Twoja metoda logowania nie zapewnia dostÄ™pu do e-zasobów licencjonowanych. Wyloguj siÄ™, a nastÄ™pnie zaloguj siÄ™ przy użyciu innej metody." +facet_list_empty = "Brak danych" +facet_list_for = "Lista faset dla %%field%%" FAQs = "CzÄ™sto zadawane pytania" fav_delete = "UsuÅ„ zaznaczone ulubione książki" fav_delete_deleting = "UsuniÄ™cie zaznaczonych książek w trakcie." @@ -442,6 +447,8 @@ fav_list_delete_fail = "BÅ‚Ä…d: Nie udaÅ‚o siÄ™ usunąć listy." Favorites = "Ulubione książki" Fee = "OpÅ‚ata" Feedback = "Feedback" +feedback_email = "Email" +feedback_login_required = "Najpierw siÄ™ zaloguj." feedback_name = "Nazwisko" Field of activity = "Zakres dziaÅ‚alnoÅ›ci" File Description = "Opis pliku" @@ -453,6 +460,7 @@ Find More = "Dalsze opcje" Find New Items = "Szukaj nowych nabytków" Finding Aid = "Pomoc" Fine = "Powód opÅ‚aty" +Fine Date = "Data opÅ‚aty" fine_limit_patron = "OsiÄ…gnÄ…Å‚eÅ› limit opÅ‚at. Nie możesz prolongować tej książki." Fines = "OpÅ‚aty" First = "Pierwsza" @@ -472,6 +480,7 @@ Geographic Search = "Wyszukiwanie geograficzne" Geographic Terms = "HasÅ‚a geograficzne" Geography = "Geografia" Get full text = "Dokumenty peÅ‚notekstowe" +Get more information = "WiÄ™cej informacji" Get RSS Feed = "Abonuj RSS" Globe = "Globus" Go = "Wykonaj" @@ -508,6 +517,7 @@ history_saved_searches = "Historia wyszukiwania" history_search = "Wyszukiwanie" history_time = "Czas" hold_available = "do odebrania" +hold_available_until = "Do odebrania do %%date%%" hold_cancel = "Anuluj zamówienia i rezerwacje" hold_cancel_all = "Anuluj wszystkie" hold_cancel_fail = "Nie udaÅ‚o siÄ™ anulować zamówienia lub rezerwacji - skontaktuj siÄ™ z bibliotekÄ…." @@ -571,6 +581,7 @@ ill_request_processed = "Przetworzony" ill_request_profile_html = "Aby otrzymać informacje o zamówieniu miÄ™dzybibliotecznym, utwórz <a href="%%url%%">konto czytelnika</a>." ill_request_submit_text = "Zamów" Illustrated = "Ilustracje" +ils_account_create_error = "WystÄ…piÅ‚ bÅ‚Ä…d przy utworzeniu twojego konta. JeÅ›li problem bÄ™dzie siÄ™ powtarzaÅ‚, skontaktuj siÄ™ z bibliotekÄ…." ils_action_unavailable = "Żądana funkcja nie jest dostÄ™pna dla twojej karty czytelnika." ils_connection_failed = "Niestety! Z powodu przeglÄ…du technicznego system jest niedostÄ™pny." ils_offline_holdings_message = "Niestety! Status dostÄ™pu obecnie nie stoi do dyspozycji - skontaktuj siÄ™ z bibliotekÄ…." @@ -645,6 +656,7 @@ Library Catalog Search = "Wyszukiwanie" Library Catalog Search Result = "Rezultaty" Library Catalog Username = "Nazwa użytkownika" Library Web Search = "Wyszukiwanie w internecie" +library_card_edit_password_placeholder = "Nowe hasÅ‚o" lightbox_error = "BÅ‚Ä…d: Nie udaÅ‚o siÄ™ zaÅ‚adować okienka pop-up." Limit To = "Ogranicz do" List = "Lista" @@ -886,7 +898,7 @@ Refine Results = "Redukuj rezultaty" Region = "Region" relais_available = "Ta książka jest dostÄ™pna przez wypożyczenie miÄ™dzybiblioteczne. Chcesz zamówić?" relais_checking = "Sprawdzamy dostÄ™pność..." -relais_error_html = "WystÄ…piÅ‚ problem przy zamówieniu. Kliknij <a href="%%url%%" target='new'>here</a> aby zamówić tÄ… książke za pomocÄ… wypożyczalni miÄ™dzybibliotecznej.</a>" +relais_error_html = "WystÄ…piÅ‚ problem przy zamówieniu. Kliknij <a href="%%url%%" target='new'>here</a> aby zamówić tÄ… książke za pomocÄ… wypożyczalni miÄ™dzybibliotecznej." relais_request = "Zamówienie wypożyczenia miÄ™dzybibliotecznego" relais_requesting = "Zamawiamy..." relais_search = "Wyszukaj wypożyczenie miÄ™dzybiblioteczne" @@ -904,9 +916,11 @@ renew_error = "Prolongowanie niemożliwe - skontaktuj siÄ™ z bibliotekÄ…." renew_fail = "Prolongowanie niemożliwe" renew_item = "Prolonguj termin zwrotu" renew_item_due = "Prosimy o zwrot w ciÄ…gu 24 godzin." +renew_item_due_tooltip = "Termin zwrotu siÄ™ zbliża" renew_item_limit = "Maksymalna ilość prolongat osiÄ…gniÄ™ta." renew_item_no = "Prolongowanie niemożliwe" renew_item_overdue = "Termin zwrotu przekroczony. Prolongowanie niemożliwe." +renew_item_overdue_tooltip = "Termin zwrotu przekroczony" renew_item_requested = "Książka zostaÅ‚a zamówiona przez innego czytelnika." renew_select_box = "Prolonguj termin zwrotu" renew_selected = "Prolonguj zaznaczone książki" @@ -955,6 +969,7 @@ search_match = "Zbieżność" search_NOT = "BEZ słów" search_OR = "z JAKIMKOLWIEK ze słów" search_save_success = "Wyszukiwanie zostaÅ‚o zapisane." +search_terms = "HasÅ‚a" search_unsave_success = "Wyszukiwanie zostaÅ‚o usuniÄ™te." seconds_abbrev = "s" see all = "Zobacz wszystkie" @@ -1139,6 +1154,7 @@ Video = "Wideo" Video Clips = "Wideoclips" Videos = "Wideo" View Book Bag = "Zobacz listÄ™ podrÄ™cznÄ…" +View Complete Issue = "Obejrz caÅ‚e wydanie" View Full Collection = "Zobacz caÅ‚Ä… kolekcjÄ™" View Full Record = "Zobacz caÅ‚y zapis" View in EDS = "Zobacz w EDS" diff --git a/languages/pt-br.ini b/languages/pt-br.ini index bb5331ce7d1a08499d72edee48ca94541bcdf719..6de0bb8856c9cd4e7102f2b410275926753b54ef 100644 --- a/languages/pt-br.ini +++ b/languages/pt-br.ini @@ -7,6 +7,7 @@ access_denied = "Access não permitido." Accession Number = "Número de chamada" Account = "Conta" account_block_options_missing = "Algumas opções foram removidas devido a problemas na sua conta. Detalhes: %%details%%" +account_has_alerts = "Sua conta tem alertas" Add a Library Card = "Adicionar Cartão de Biblioteca" Add a Note = "Adicionar uma nota" Add Tag = "Adicionar Tag" @@ -46,6 +47,7 @@ Advanced Search = "Busca Avançada" advSearchError_noRights = "Desculpe, você não tem permissão para editar a busca. Talvez a sua sessão tenha expirado?" advSearchError_notAdvanced = "A busca que solicitou a edição não é uma busca avançada." advSearchError_notFound = "A busca que solicitou não foi encontrada." +ajax_load_interrupted = "Carregamento interrompido" ajaxview_label_information = "Informação" ajaxview_label_tools = "Ferramentas" All = "Todos" @@ -233,6 +235,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Deseja cancelar as req Contents = "Conteúdos" Contributing Source = "Fonte contribuidora" Contributors = "Colaboradores" +Coordinates = "Coordenadas" Copies = "Cópias" Copy = "Cópia" Copyright = "Copyright" @@ -363,6 +366,8 @@ external_auth_heading = "Acesso a material licenciado" external_auth_login_message = "Faça login para acessar material licenciado" external_auth_unauthorized = "Você não está autorizado a acessar material licenciado" external_auth_unauthorized_desc = "Sua forma de login não oferta acesso a material licenciado. Por favor, faça logoff e se logue novamente de outra forma." +facet_list_empty = "Não há dados disponÃveis" +facet_list_for = "Lista de facetas para %%field%%" FAQs = "FAQs" fav_delete = "Apagar os Favoritos selecionados" fav_delete_deleting = "Os Favoritos selecionados serão apagados." @@ -380,6 +385,8 @@ fav_list_delete_fail = "Desculpe, ocorreu um erro. Lista não eliminada." Favorites = "Itens Guardados" Fee = "Multas" Feedback = "Comentário" +feedback_email = "Email" +feedback_login_required = "Você deve entrar na sua conta antes." feedback_name = "Nome" Field of activity = "Campo de atividade" File Description = "Descrição de arquivo" @@ -391,6 +398,7 @@ Find More = "Encontrar Mais" Find New Items = "Encontrar novos itens" Finding Aid = "Obter ajuda" Fine = "Multa" +Fine Date = "Data da multa" fine_limit_patron = "Não lhe é permitido renovar o empréstimo por ter atingido o limite de penalizações" Fines = "Multas" First = "Primeiro" @@ -410,6 +418,7 @@ Geographic Search = "Busca Geográfica" Geographic Terms = "Termos Geográficos" Geography = "Geografia" Get full text = "Obter o texto integral" +Get more information = "Obtenha mais informações" Get RSS Feed = "Obter Feed RSS" Globe = "Globo" Go = "Ir" @@ -446,6 +455,7 @@ history_saved_searches = "Buscas Guardadas" history_search = "Busca" history_time = "Hora" hold_available = "DisponÃvel para levantamento" +hold_available_until = "DisponÃvel para retirada até %%date%%" hold_cancel = "Cancelar a reserva" hold_cancel_all = "Cancelar todas as reservas" hold_cancel_fail = "A sua reserva não foi cancelada; por favor, contate o Balcão de Atendimento para ajuda adicional" @@ -509,6 +519,7 @@ ill_request_processed = "Processado" ill_request_profile_html = "Para informação sobre Pedido de Débito Interbiblioteca, por favor estabeleça seu <a href="%%url%%">Perfil no Catálogo da Biblioteca</a>." ill_request_submit_text = "Colocar Pedido" Illustrated = "Ilustrado" +ils_account_create_error = "Sua conta não pôde ser criada em nosso sistema de gestão de bibliotecas. Se o problema persistir, entre em contato com sua biblioteca." ils_action_unavailable = "A função requerida não está disponÃvel com o cartão de biblioteca ativo." ils_connection_failed = "O sistema está em manutenção." ils_offline_holdings_message = "A informação da disponibilidade do(s) exemplar(es) não está disponÃvel de momento; por favor, aceite as nossas desculpas por qualquer inconveniente que isso possa causar e contate-nos para obter ajuda:" @@ -583,6 +594,7 @@ Library Catalog Search = "Busca no Catálogo da Biblioteca" Library Catalog Search Result = "Resultado da busca no Catálogo da Biblioteca" Library Catalog Username = "Login do Usuário no Catálogo da Biblioteca" Library Web Search = "Buscar na Web da Biblioteca" +library_card_edit_password_placeholder = "Nova Senha" lightbox_error = "Erro: janela de pop-ups bloqueada" Limit To = "Limitar a" List = "Lista" @@ -824,7 +836,7 @@ Refine Results = "Refinar Resultados" Region = "Região" relais_available = "Este item está disponÃvel por meio do empréstimo entre bibliotecas. Gostaria de requisitá-lo?" relais_checking = "Verificando disponibilidade..." -relais_error_html = "Houve um problema com seu pedido. Clique em <a href="%%url%%" target='new'>here</a> para pedir esse item usando o site de empréstimo entre bibliotecas.</a>" +relais_error_html = "Houve um problema com seu pedido. Clique em <a href="%%url%%" target='new'>here</a> para pedir esse item usando o site de empréstimo entre bibliotecas." relais_request = "Pedido de Empréstimo entre Bibliotecas" relais_requesting = "Pedindo..." relais_search = "Buscar Emprestimo entre Bibliotecas" @@ -842,9 +854,11 @@ renew_error = "Não foi possÃvel renovar os seus empréstimos; por favor, conta renew_fail = "O empréstimo deste exemplar não pode ser renovado" renew_item = "Renovar empréstimo" renew_item_due = "Prazo de devolução termina nas próximas 24 horas" +renew_item_due_tooltip = "Itens com vencimento próximo" renew_item_limit = "Já fez o máximo de renovações permitido para este empréstimo" renew_item_no = "Este exemplar não pode ser renovado" renew_item_overdue = "Exemplar em atraso" +renew_item_overdue_tooltip = "Itens vencidos" renew_item_requested = "Este exemplar foi reservado por outro usuário" renew_select_box = "Renovar empréstimo" renew_selected = "Renovar os empréstimos selecionados" @@ -893,6 +907,7 @@ search_match = "correspondência da busca" search_NOT = "NENHUM termo" search_OR = "QUALQUER Termo" search_save_success = "Busca guardada com sucesso." +search_terms = "Termos de pesquisa" search_unsave_success = "Busca guardada apagada com sucesso." seconds_abbrev = "s" see all = "Ver todos" @@ -1077,6 +1092,7 @@ Video = "VÃdeo" Video Clips = "Video Clipes" Videos = "VÃdeos" View Book Bag = "Ver cesta" +View Complete Issue = "Visualizar edição completa" View Full Collection = "Ver Coleção Completa" View Full Record = "Ver Registro Completo" View in EDS = "Visualizar em EDS" diff --git a/languages/pt.ini b/languages/pt.ini index 5a4573dd36e9218ef28a76a1e202e44a64255bff..42f04ad733a1256b3d01957d1a41934fa2a41fb3 100644 --- a/languages/pt.ini +++ b/languages/pt.ini @@ -335,6 +335,8 @@ fav_list_delete_fail = "Desculpe, ocorreu um erro. Lista não eliminada." Favorites = "Favoritos" Fee = "Multas" Feedback = "Comentário" +feedback_email = "Email" +feedback_login_required = "Você deve entrar na sua conta antes." feedback_name = "Nome" Filter = "Filtro" filter_tags = "Filtro de Trags" @@ -514,6 +516,7 @@ Library Catalog Search = "Pesquisa no Catálogo da Biblioteca" Library Catalog Search Result = "Resultado da pesquisa no Catálogo da Biblioteca" Library Catalog Username = "Login de Utilizador no Catálogo da Biblioteca" Library Web Search = "Pesquisar na Web da Biblioteca" +library_card_edit_password_placeholder = "Nova Senha" lightbox_error = "Erro: janela de pop-ups bloqueada" Limit To = "Limitar a" List = "Lista" diff --git a/languages/ru.ini b/languages/ru.ini index 509f8576e74c2334d699de5a434ca90a945b6fd3..2bf4847d34e9a64d8d140705c10b3c361087d17b 100644 --- a/languages/ru.ini +++ b/languages/ru.ini @@ -366,6 +366,8 @@ fav_list_delete_fail = "Произошла ошибка. Ваш ÑпиÑок у Favorites = "Избранное" Fee = "взноÑ" Feedback = "обратной ÑвÑзи" +feedback_email = "Email" +feedback_login_required = "Сначала войдите в ÑиÑтему." feedback_name = "ИмÑ" File Description = "ОпиÑание файла" Filter = "Фильтр" @@ -562,6 +564,7 @@ Library Catalog Search = "ПоиÑка в библиотечном катало Library Catalog Search Result = "Результат поиÑка по каталогу библиотеки" Library Catalog Username = "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð¾ каталогу библиотеки" Library Web Search = "Web-поиÑк библиотеки" +library_card_edit_password_placeholder = "Ðовый пароль" lightbox_error = "Ошибка: невозможно загрузить вÑплывающее окно." Limit To = "Ограничить:" List = "СпиÑок" diff --git a/languages/sl.ini b/languages/sl.ini index e6a362659b099774bb869454b035f7186c6524eb..aabb4cc9f190eb203c11d929588ef53c116b0c93 100644 --- a/languages/sl.ini +++ b/languages/sl.ini @@ -291,6 +291,8 @@ fav_list_delete_fail = "Oprostite, pojavila se je napaka. VaÅ¡ seznam ni bil izb Favorites = "Priljubljene" Fee = "ÄŒlanarina/zamudnina" Feedback = "PiÅ¡ite nam" +feedback_email = "Email" +feedback_login_required = "Najprej se morate prijaviti." feedback_name = "Ime" Filter = "Filter" filter_tags = "Filter oznake" diff --git a/languages/sv.ini b/languages/sv.ini index 75368406c95fbd169bfd3c435560311fb8ca8633..36f79af8c0ec9c9dcfdab57c75edfebe1b451c78 100644 --- a/languages/sv.ini +++ b/languages/sv.ini @@ -6,6 +6,7 @@ access_denied = "Ã…tkomst nekad" Accession Number = "Accessionsnummer" Account = "Konto" account_block_options_missing = "Vissa alternativ har tagits bort pÃ¥ grund av lÃ¥ne- efter reserveringsförbud. Detaljer: %%details%%" +account_has_alerts = "Kolla ditt konto" Add a Library Card = "Anslut bibliotekskort till konto" Add a Note = "Lägg till en anteckning " Add Tag = "Lägg till en tagg" @@ -45,11 +46,12 @@ Advanced Search = "Avancerad sökning" advSearchError_noRights = "Sökningen kunde inte ändras. Orsaken kan vara att sessionen avbröts." advSearchError_notAdvanced = "Sökningen som du ändrade är inte en avancerad sökning." advSearchError_notFound = "Sökningen hittas inte." +ajax_load_interrupted = "Laddning avbruten" ajaxview_label_information = "Information" ajaxview_label_tools = "Verktyg" All = "Alla" All Fields = "Alla fält" -All Pages Loaded = "All Pages Loaded" +All Pages Loaded = "Alla sidor laddade" All Text = "All text" alphabrowse_matches = "Resultat" alphabrowselink_html = "Bläddra efter %%index%% frÃ¥n <a href="%%url%%">%%from%%</a>." @@ -186,7 +188,7 @@ Checkout Date = "UtlÃ¥ningsdag" Chicago Citation = "Chicago-stil citat" child_record_count = "%%count%% poster" child_records = "InnehÃ¥ll/delar" -Choose a Category to Begin Browsing = "Choose a Category to Begin Browsing" +Choose a Category to Begin Browsing = "Välj en kategori för att börja bläddra" Choose a Column to Begin Browsing = "Välj en kolumn för att börja bläddra" Choose a List = "Välj en lista" choose_login_method = "Välj en inloggningsmetod:" @@ -201,9 +203,9 @@ clear_tag_filter = "Ta bort filter" close = "Stäng" Code = "Kod" Collection = "Samling" -Collection Browse = "Collection Browse" +Collection Browse = "Bläddring av samlingen" Collection Items = "Samlingens innehÃ¥ll" -collection_disambiguation = "Found Multiple Matching Collections" +collection_disambiguation = "Hittade flera samlingar" collection_empty = "Inget att visa" collection_view_record = "Visa posten" Collections = "Samlingar" @@ -232,6 +234,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "Vill du annullera de v Contents = "InnehÃ¥ll" Contributing Source = "Bidragande källa" Contributors = "Övriga upphovsmän" +Coordinates = "Koordinater" Copies = "Exemplar" Copy = "Exemplar" Copyright = "Copyright" @@ -330,7 +333,7 @@ email_sending = "Meddelandet skickas..." email_subject = "Ämne" email_success = "Meddelandet har skickats" Empty = "Tom" -Empty Book Bag = "Empty Book Bag" +Empty Book Bag = "Tömma" Enable Auto Config = "Enable Auto Config" End Page = "Sista sidan" Era = "Tidsperiod" @@ -343,7 +346,7 @@ exclude_newspapers = "Uteslut tidningsartiklar" Expires = "Förfaller" Export = "Exportera" Export Favorites = "Exportera favoriter" -Export Items = "Export Items" +Export Items = "Exportera" Export Record = "Exportera posten" Export to = "Exportera till: " export_choose_format = "Välj exportformat" @@ -363,6 +366,8 @@ external_auth_heading = "Behörighet att komma Ã¥t licensierat material" external_auth_login_message = "Logga in för att komma Ã¥t licensierat material" external_auth_unauthorized = "Du har inte behörighet att komma Ã¥t licensierat material" external_auth_unauthorized_desc = "Du kan inte komma Ã¥t licensierat material med inloggningsmetoden du har använt. Logga ut först och sedan logga in med en annan metod." +facet_list_empty = "Ingen data tillgänglig" +facet_list_for = "Fasettlista för %%field%%" FAQs = "Vanliga frÃ¥gor" fav_delete = "Radera valda favoriter" fav_delete_deleting = "Dina favoriter raderas" @@ -380,6 +385,8 @@ fav_list_delete_fail = "Ett fel har uppstÃ¥tt. Listan raderades inte." Favorites = "Favoriter" Fee = "Avgift" Feedback = "Respons" +feedback_email = "E-post" +feedback_login_required = "Du mÃ¥ste logga in först." feedback_name = "Ditt namn" Field of activity = "VerksamhetsomrÃ¥de" File Description = "Filbeskrivning" @@ -391,6 +398,7 @@ Find More = "Sök mera" Find New Items = "Nyhetskatalog" Finding Aid = "Sökhjälp" Fine = "Avgift" +Fine Date = "Avstämningsdag" fine_limit_patron = "LÃ¥n kan inte förnyas p.g.a. mängden obetalda avgifter" Fines = "Avgifter" First = "Först" @@ -410,6 +418,7 @@ Geographic Search = "Geografisk sökning" Geographic Terms = "Geografiska termer" Geography = "Geografisk" Get full text = "Hämta fulltext" +Get more information = "Mer information" Get RSS Feed = "RSS-flöde" Globe = "Jordglob" Go = "Go" @@ -446,6 +455,7 @@ history_saved_searches = "Sparade sökningar" history_search = "Sökning" history_time = "Tid" hold_available = "Kan avhämtas" +hold_available_until = "Kan avhämtas - sista avhämtningsdag %%date%%" hold_cancel = "Annullera reserveringen" hold_cancel_all = "Annullera alla reserveringar" hold_cancel_fail = "Reserveringen kunde inte annulleras. Kontakta kundtjänst." @@ -509,13 +519,14 @@ ill_request_processed = "Behandlad" ill_request_profile_html = "Logga in med din <a href="%%url%%">bibliotekskort</a> för att se fjärrlÃ¥nbeställningar." ill_request_submit_text = "Beställ" Illustrated = "Illustrerad" +ils_account_create_error = "Kunde inte skapa ett konto i bibliotekssystemet. Kontakta kundtjänst, om problemet kvarstÃ¥r." ils_action_unavailable = "Den begärda Ã¥tgärden är inte tillgänglig med det aktiva bibliotekskortet." ils_connection_failed = "Anslutning till bibliotekssystemet misslyckades. Information relaterad till ditt bibliotekskonto kan inte visas. Kontakta kundtjänst om problemet kvarstÃ¥r." -ils_offline_holdings_message = "Holdings and item availability information is currently unavailable. Please accept our apologies for any inconvenience this may cause and contact us for further assistance:" -ils_offline_home_message = "Your account details and live item information will be unavailable during this time. Please accept our apologies for any inconvenience this may cause and contact us for further assistance:" -ils_offline_login_message = "Your account details will be unavailable during this time. Please accept our apologies for any inconvenience this may cause and contact us for further assistance:" -ils_offline_status = "Our Library Management System is currently under maintenance." -ils_offline_title = "System Under Maintenance" +ils_offline_holdings_message = "Tillgänglighetsinformation kan inte visas för tillfället. Vi beklagar störningen. Kontakta oss om problemet kvarstÃ¥r:" +ils_offline_home_message = "Information om ditt konto kan inte visas för tillfället. Vi beklagar störningen. Kontakta oss om problemet kvarstÃ¥r:" +ils_offline_login_message = "Information om ditt konto kan inte visas för tillfället. Vi beklagar störningen. Kontakta oss om problemet kvarstÃ¥r:" +ils_offline_status = "Bibliotekssystemet är närvarande under underhÃ¥ll." +ils_offline_title = "Systemet under underhÃ¥ll" ils_transaction_history_disabled = "UtlÃ¥ningshistoriken är inte aktiverat för det aktiva bibliotekskortet." Import Record = "Importera posten" in = "i fältet" @@ -583,6 +594,7 @@ Library Catalog Search = "Library Catalog Search" Library Catalog Search Result = "Sökresultat" Library Catalog Username = "Användarnamn i bibliotekssystemet" Library Web Search = "Webbsökning" +library_card_edit_password_placeholder = "Nytt lösenord" lightbox_error = "Fel: kunde inte öppna ett pop-up-fönster." Limit To = "Begränsa till" List = "Lista" @@ -622,7 +634,7 @@ Microfilm = "Mikrofilm" MLA Citation = "MLA-referens" Mobile Number = "Mobiltelefon" mobile_link = "You appear to be on a mobile device; switch to mobile view?" -Monograph Title = "Monografis titel" +Monograph Title = "Monografisk titel" more = "mer" More catalog results = "Fler resultat i katalog" More options = "Fler alternativ" @@ -822,6 +834,14 @@ recovery_user_not_found = "Ditt konto hittades inte" rectangle_center_message = "Mittpunkt för begränsat omrÃ¥de" Refine Results = "Förfina resultatet" Region = "Region" +relais_available = "Materialet är tillgängligt som en fjärrlÃ¥n. Vill du skapa en fjärrlÃ¥nbeställning?" +relais_checking = "Kollar tillgänglighet..." +relais_error_html = "Beställning misslyckades. Skapa en beställning pÃ¥ <a href="%%url%%" target='new'>fjärrlÃ¥nesystemets sidor</a>." +relais_request = "FjärrlÃ¥nbeställning" +relais_requesting = "Skickar beställningen..." +relais_search = "FjärrlÃ¥nsökning" +relais_success_label = "Bekräftelse:" +relais_success_message = "Beställning med id #%%id%% har skapats. Du kommer att fÃ¥ ett bekräftelse per e-post." Related Author = "Relaterad upphovsman" Related Items = "Relaterade poster" Related Subjects = "Relaterade ämnen" @@ -834,9 +854,11 @@ renew_error = "Dina lÃ¥n kunde inte förnyas. Kontakta kundtjänst." renew_fail = "LÃ¥net kunde inte förnyas." renew_item = "Förnya lÃ¥net" renew_item_due = "LÃ¥net förfaller inom ett dygn." +renew_item_due_tooltip = "LÃ¥n förfaller snart" renew_item_limit = "Detta lÃ¥n har förnyats maximalt antal gÃ¥nger." renew_item_no = "Detta lÃ¥n kan inte förnyas." renew_item_overdue = "LÃ¥net är försenat." +renew_item_overdue_tooltip = "Försenade lÃ¥n" renew_item_requested = "En annan kund har reserverat denna." renew_select_box = "Fönya lÃ¥net" renew_selected = "Förnya valda lÃ¥n" @@ -885,6 +907,7 @@ search_match = "Sök" search_NOT = "Ingen sökterm (NOT)" search_OR = "Vilka söktermer som helst (OR)" search_save_success = "Sökningen har sparats." +search_terms = "Sökningsvillkor" search_unsave_success = "Sökningen har raderats." seconds_abbrev = "s" see all = "Visa alla" @@ -1069,6 +1092,7 @@ Video = "Video" Video Clips = "Videoklipp" Videos = "Videor" View Book Bag = "Visa bokkorgen" +View Complete Issue = "Visa hela nummret" View Full Collection = "Visa hel samlingen" View Full Record = "Visa hela posten" View in EDS = "Visa i EDS" diff --git a/languages/tr.ini b/languages/tr.ini index 281acabadf876fdc30128090829d3c374d10e781..0e4d4fb74be0ff679b33aed455185b7464068c77 100644 --- a/languages/tr.ini +++ b/languages/tr.ini @@ -18,6 +18,7 @@ access_denied = "Giriþ engellendi." Accession Number = "Aksesiyon No" Account = "Hesap" account_block_options_missing = "Hesabınızdaki bir engel nedeniyle bazı seçenekler kaldırıldı. Detaylar: %%details%%" +account_has_alerts = "Hesabınızda uyarılar var" Add a Library Card = "Kütüphane Kartı Ekle" Add a Note = "Not Ekle" Add Tag = "Etiketle" @@ -57,6 +58,7 @@ Advanced Search = "GeliÅŸmiÅŸ Tarama" advSearchError_noRights = "Bu taramayı deÄŸiÅŸtirmeye yetkiniz yoktur. Muhtemelen tarayıcınız sonlanmış olabilir?" advSearchError_notAdvanced = "Düzeltmek için istemiÅŸ olduÄŸunuz tarama, geliÅŸmiÅŸ taramada mevcut deÄŸildir." advSearchError_notFound = "Ä°stemiÅŸ olduÄŸunuz tarama bulunamadı." +ajax_load_interrupted = "Yükleme yarıda kesildi" ajaxview_label_information = "Bilgi" ajaxview_label_tools = "Araçlar" All = "Tümü" @@ -244,6 +246,7 @@ confirm_storage_retrieval_request_cancel_selected_text = "SeçmiÅŸ olduÄŸunuz de Contents = "İçindekiler" Contributing Source = "Katkıda Bulunan Kaynak" Contributors = "DiÄŸer Yazarlar" +Coordinates = "Düzenlemeler" Copies = "Kopyalar" Copy = "Kopya Bilgisi" Copyright = "Telif Hakkı" @@ -374,6 +377,8 @@ external_auth_heading = "Lisanslı materyale eriÅŸim" external_auth_login_message = "Lisanslı materyale eriÅŸmek için giriÅŸ yapın" external_auth_unauthorized = "Lisanslı materyale eriÅŸme yetkiniz yok" external_auth_unauthorized_desc = "GiriÅŸ yönteminiz lisanslı materyale eriÅŸim saÄŸlamıyor. Lütfen çıkış yapın ve baÅŸka bir yöntem kullanarak giriÅŸ yapın." +facet_list_empty = "Uygun veri yok" +facet_list_for = "%%field%%" için bölüm listesi" FAQs = "SSS" fav_delete = "SeçilmiÅŸ Favorileri Sil" fav_delete_deleting = "Favorileriniz silinecek." @@ -391,6 +396,8 @@ fav_list_delete_fail = "Bir hata oluÅŸtu. Listeniz silinemedi." Favorites = "Favorilerim" Fee = "Gecikme Cezası" Feedback = "Görüsleriniz" +feedback_email = "Eposta" +feedback_login_required = "Ä°lk önce giriÅŸ yapmalısınız." feedback_name = "Adiniz" Field of activity = "Aktivite Alanı" File Description = "Dosya tanımı" @@ -402,6 +409,7 @@ Find More = "DiÄŸer Taramalar" Find New Items = "Yeni Kayıtları Bul" Finding Aid = "Maaliyet" Fine = "Para Cezası" +Fine Date = "Ceza Tarihi" fine_limit_patron = "Ceza limitiniz dolmuÅŸtur, kayıtları uzatamazsınız." Fines = "Cezalar" First = "Ãlk" @@ -421,6 +429,7 @@ Geographic Search = "CoÄŸrafik Tarama" Geographic Terms = "CoÄŸrafik Terimler" Geography = "CoÄŸrafi" Get full text = "Tam Metin EriÅŸim" +Get more information = "Daha fazla bilgi edinin" Get RSS Feed = "RSS Beslemesi" Globe = "Göre" Go = "Git" @@ -457,6 +466,7 @@ history_saved_searches = "KaydedilmiÅŸ taramalarınız" history_search = "Tarama" history_time = "Zaman" hold_available = "Ödünç alınabilir" +hold_available_until = "%%date%% tarihine kadar mevcut" hold_cancel = "Ayrılmışı iptal et" hold_cancel_all = "Tüm ayrılmışları iptal et" hold_cancel_fail = "Ä°steÄŸiniz iptal edilmedi. Lütfen detayli bilgi için ödünç verme masasına baÅŸvurunuz." @@ -520,6 +530,7 @@ ill_request_processed = "Ä°ÅŸlendi" ill_request_profile_html = "Kütüphaneler arası ödünç alma istek bilgileri için, Lütfen <a href="%%url%%">Kütüphane Katalog Profiline Tıklayınız</a>." ill_request_submit_text = "Ä°stekte bulunun" Illustrated = "Resimli" +ils_account_create_error = "Hesabınız kütüphane yönetim sistemimizde oluÅŸturulamadı. Sorun devam ederse, lütfen kütüphanenize baÅŸvurun." ils_action_unavailable = "Ä°stenen iÅŸlev aktif kütüphane kartında mevcut deÄŸildir." ils_connection_failed = "Kütüphane sistemimiz bakımda." ils_offline_holdings_message = "Kopya kayıtları ve kayıların durum bilgileri ÅŸu anda eriÅŸilebilir deÄŸil. Bunun için özür dileriz, daha fazla yardım için bizimle irtibata geçebilirsiniz:" @@ -594,6 +605,7 @@ Library Catalog Search = "Kütüphane Katalog Taraması" Library Catalog Search Result = "Kütüphane Katalog Tarama Sonucu" Library Catalog Username = "Kütüphane Katalog Kullanıcı Adı" Library Web Search = "Kütüphane Web Taraması" +library_card_edit_password_placeholder = "Yeni Åžifre" lightbox_error = "Lightbox Hatası" Limit To = "AÅŸağıdaki seçenekler ile taramanızı sınırlandırabilirsiniz." List = "Liste" @@ -835,7 +847,7 @@ Refine Results = "Sonuçları Daraltın" Region = "Bölge" relais_available = "Bu kayda Kütüphanelerarası Ödünç Verme yoluyla ulaşılabilir. Talep etmek ister misiniz?" relais_checking = "KullanılabilirliÄŸi kontrol ediliyor..." -relais_error_html = "Bu istekle ilgili bir sorun oluÅŸtu. <a href="%%url%%" target='new'>Buraya tıklayın</a> Kütüphaneler arası ödünç verme web sitesini kullanarak bu öğeyi istemek için.</a>" +relais_error_html = "Bu istekle ilgili bir sorun oluÅŸtu. <a href="%%url%%" target='new'>Buraya tıklayın</a> Kütüphaneler arası ödünç verme web sitesini kullanarak bu öğeyi istemek için." relais_request = "Kütüphaneler Arası Ödünç Verme Ä°steÄŸi" relais_requesting = "Ä°steniyor..." relais_search = "Kütüphanelerarası Ödünç Vermeyi Tara" @@ -853,9 +865,11 @@ renew_error = "Kayıtlarınız uzatılamdı. Lütfen detayli bilgi için ödün renew_fail = "Bu kayıt uzatılamadı" renew_item = "Kaydı uzat" renew_item_due = "Kayıt 24 saat içinde gecikecek" +renew_item_due_tooltip = "Yakında iade edilecek kayıtlar" renew_item_limit = "Bu kayıt uzatma sınırına ulaÅŸtı" renew_item_no = "Kayıt uzatılamadı" renew_item_overdue = "Kayıt geçikmiÅŸ" +renew_item_overdue_tooltip = "Geciken Kayıtlar" renew_item_requested = "Bu kayıt baÅŸkası tarafından ayırtıldı" renew_select_box = "Kayıdı uzat" renew_selected = "SeçilmiÅŸ kayıtları uzat" @@ -904,6 +918,7 @@ search_match = "EÅŸleÅŸtir" search_NOT = "Hiçbir Terim" search_OR = "Herhangi Bir Terim" search_save_success = "Arama baÅŸarıyla kaydedildi." +search_terms = "Arama terimleri" search_unsave_success = "KaydedilmiÅŸ arama baÅŸarıyla silinde." seconds_abbrev = "s" see all = "Hepsini Gör" @@ -1088,6 +1103,7 @@ Video = "Video" Video Clips = "Video Klibi" Videos = "Video" View Book Bag = "Kitap Sepetini Göster" +View Complete Issue = "Tamamlanmış sayıyı görüntüle" View Full Collection = "Tüm Koleksiyonu Görüntüle" View Full Record = "Tam Kayıt Görüntüle" View in EDS = "EDS Görüntüle" diff --git a/languages/vi.ini b/languages/vi.ini new file mode 100644 index 0000000000000000000000000000000000000000..750f34e0e7168e7a14bf439c1ca2afd538470887 --- /dev/null +++ b/languages/vi.ini @@ -0,0 +1,1142 @@ +; For future reference: +;Vietnamese = Tiếng Việt +Abstract = "BaÌ€i toÌm tăÌt" +Access = "Truy cáºp" +Access URL = "Äịa chỉ truy cáºp" +access_denied = "Truy cáºp bị từ chối." +Accession Number = "Số gia nháºp" +Account = "Tà i khoản" +account_block_options_missing = "Má»™t số lá»±a chá»n đã loại ra vì khối vì lợi Ãch của bạn. Chi tiết: %%%details%%" +account_has_alerts = "Tà i khoản của bạn đã cảnh báo" +Add a Library Card = "Thêm thẻ thÆ° viện" +Add a Note = "Thêm chú thÃch" +Add Tag = "Thêm thẻ" +Add Tags = "Thêm nhiá»u thẻ" +Add to another list = "Thêm và o danh sách khác" +Add to Book Bag = "Thêm và o cặp sách" +Add to favorites = "LÆ°u và o danh sách" +Add your comment = "Thêm bình luáºn của bạn" +add_comment_fail_blank = "Chú thÃch không thể được trống." +add_comment_success = "Chú thÃch thêm. " +add_favorite_fail = "Lá»—i : Bản ghi không lÆ°u" +add_list_fail = "Lá»—i : Danh sách không tạo ra" +add_other_libraries = "Bao gồm bà i viết và o thÆ° viện khác" +add_search = "Thêm tìm kiếm" +add_search_group = "Thêm nhóm tìm kiếm" +add_tag_error = "Lá»—i: không thể lÆ°u thẻ" +add_tag_note = "Dấu cách sẽ riêng biệt thẻ. Dấu ngoặc kép sá» dụng cho thẻ nhiá»u chữ." +add_tag_success = "LÆ°u thẻ" +add_to_favorites_html = "Thêm <em>%%title%%</em> và o yêu thÃch" +Address = "Äịa chỉ" +adv_search_all = "Tất cả các trÆ°á»ng" +adv_search_author = "Tác giả" +adv_search_callnumber = "Số Ä‘iện thoại" +adv_search_filters = "Ãp dụng bá»™ lá»c" +adv_search_isn = "số ISBN/ISSN" +adv_search_journaltitle = "Tiêu Ä‘á» tà i liệu ghi chép" +adv_search_label = "Tìm kiếm" +adv_search_publisher = "Nhà xuất bản" +adv_search_select_all = "Chá»n tất cả" +adv_search_series = "Chuá»—i" +adv_search_subject = "Chủ Ä‘á»" +adv_search_title = "Tiêu Ä‘á»" +adv_search_toc = "Bảng mục lục" +adv_search_year = "Năm của ấn phẩm" +Advanced = "Nâng cao" +Advanced Search = "Tìm kiếm nâng cao" +advSearchError_noRights = "Tôi xin lá»—i, nhÆ°ng bạn không được phép chỉnh sá»a tìm kiếm. Có lẽ phiên trình duyệt của bạn có hết hạn?" +advSearchError_notAdvanced = "Khám xét bạn đã yêu cầu để chỉnh sá»a không phải là má»™t tìm kiếm nâng cao." +advSearchError_notFound = "Tìm kiếm của bạn đã yêu cầu không tìm thấy. " +ajax_load_interrupted = "Äang tải bị gián Ä‘oạn" +ajaxview_label_information = "Thông tin" +ajaxview_label_tools = "Công cụ" +All = "Tất cả" +All Fields = "Tất cả các trÆ°á»ng" +All Pages Loaded = "Tải tất cả các trang" +All Text = "Tất cả văn bản" +alphabrowse_matches = "Kết quả" +alphabrowselink_html = "Mục duyệt nhanh bằng %%index%% bắt đầu từ <a href="%%url%%">%%from%%</a>." +An error has occurred = "Lá»—i đã xảy ra" +An error occurred during execution; please try again later. = "Lá»—i xảy ra trong thi hà nh ; vui lòng thá» lại sau." +AND = "Và " +anonymous_tags = "Thẻ ẩn danh" +APA Citation = "TrÃch dẫn APA" +applied_filter = "Ãp dụng bá»™ lá»c" +Article = "Bà i viết" +Ask a Librarian = "Há»i thủ thÆ°" +Associated country = "Kết hợp quốc gia" +Audience = "ThÃnh giả" +Audio = "Âm thanh" +authentication_error_admin = "Chúng tôi không thể nháºt kà bạn tại thá»i gian nà y. Xin liên lạc vá»›i nhân viên quản trị hệ thống của bạn để được trợ giúp." +authentication_error_blank = "Thông tin đăng nháºp không thể được trống." +authentication_error_creation_blocked = " Bạn không được phép tạo ra tà i khoản. " +authentication_error_denied = "Khả năng không trùng khá»›p! Truy cáºp bị từ chối." +authentication_error_invalid = "Không hợp lệ mã đăng nháºp -- vui lòng thá» lại." +authentication_error_loggedout = "Bạn có đăng xuất." +authentication_error_technical = "Chúng tôi không thể nháºt kà bạn tại thá»i gian nà y. Xin vui lòng thá» lại sau." +Author = "Tác giả" +Author Browse = "Duyệt nhanh tác giả" +Author Notes = "Ghi chú tác giả" +Author Results for = "Kết quả tác giả cho" +Author Search Results = "Kết quả tìm kiếm tác giả" +Authority File = "Táºp tin quyá»n hà nh" +Authors = "Nhiá»u tác giả" +Authors Related to Your Search = "Những tác giả liên quan đến tìm kiếm của bạn" +Auto configuration is currently disabled = "Cấu hình tá»± Ä‘á»™ng hiện không thể" +auto_configure_description = "Nếu đây là cà i đặt má»›i, bạn có thể cố định lá»—i sá» dụng công cụ Cấu hình Tá»± Ä‘á»™ng của VuFind. " +auto_configure_disabled = "Cấu hình tá»± Ä‘á»™ng bị vô hiệu." +auto_configure_title = "Cấu hình tá»± Ä‘á»™ng" +Availability = "TÃnh sẵn sà ng" +Available = "Sẵn có" +Available Functionality = "Chức năng sẵn có" +Awards = "Giải thưởng" +Back to Record = "Quay trở lại bản ghi" +Back to Search Results = "Quay trở lại kết quả tìm kiếm" +Backtrace = "Rút lui" +Bag = "Giá»" +Balance = "Cân đối" +Barcode = "Mã vạch" +basic_search_keep_filters = "Giữ lại bá»™ lá»c hiện hà nh" +Be the first to leave a comment = "Là ngÆ°á»i đầu tiên ghi lá»i nháºn xét" +Be the first to tag this record = "Là ngÆ°á»i đầu tiên thẻ bản ghi nà y" +Bibliographic Details = "Chi tiết vá» thÆ° mục" +Bibliography = "ThÆ° mục" +Blu-ray Disc = "ÄÄ©a Blu-ray" +Book = "Sách" +Book Bag = "Túi sách" +Book Chapter = "ChÆ°Æ¡ng của sách" +Book Cover = "Bìa sách" +bookbag_confirm_empty = "Bạn có chắc là bạn muốn đổ hết Túi sách của bạn?" +bookbag_delete = "Xoá bá» khoản mục cặp sách chá»n lá»c" +bookbag_delete_selected = "Xoá bỠđã chá»n" +bookbag_email = "Email danh sách túi sách đã chá»n" +bookbag_email_selected = "Email đã chá»n" +bookbag_export = "Xuất ra danh sách cặp sách đã chá»n" +bookbag_export_selected = "Xuất ra lá»±a chá»n" +bookbag_full = "Äầy đủ" +bookbag_full_msg = "Túi sách của bạn đầy" +bookbag_is_empty = "Túi sách của bạn rá»—ng" +bookbag_print_selected = "In đã chá»n" +bookbag_save = "LÆ°u danh sách túi sách đã chá»n" +bookbag_save_selected = "LÆ°u lá»±a chá»n" +Bookmark = "Äánh dấu" +Books = "Sách" +Borrowing Location = "Khu vá»±c mượn" +Braille = "Chữ nổi" +Brief View = "Góc nhìn ngắn" +Browse = "Duyệt nhanh" +Browse Alphabetically = "Tìm theo thứ tá»± ABC" +Browse for Authors = "Tìm theo tác giả" +Browse Home = "Tìm theo trang chủ" +Browse the Catalog = "Tìm theo Ca-ta-lô" +Browse the Collection = "Tìm theo bá»™ sÆ°u táºp" +Browse the Collection Alphabetically = "Tìm theo bá»™ sÆ°u táºp theo thứ tá»± ABC" +browse_author = "Tác giả" +browse_dewey = "Äiện thoại (Dewey)" +browse_format = "Äịnh dạng" +browse_lcc = "Äiện thoại (LC)" +browse_publishDate = "Ấn phẩm của năm" +browse_title = "Tiêu Ä‘á»" +browse_topic = "Chủ Ä‘á»" +bulk_email_success = "Danh sách của bạn đã được gởi mail" +bulk_email_title = "Danh sách ca-ta-lô thÆ° viện" +bulk_error_missing = "Má»™t số dữ liệu thiếu. Yêu cầu của bạn không thà nh công." +bulk_export_not_supported = "Bản ghi bạn đã chá»n không há»— trợ xuất ra đồ sá»™. " +bulk_fail = "Xin lá»—i, lá»—i đã xảy ra. Xin vui lòng thá» lại." +bulk_noitems_advice = "Khoản mục không được chá»n lá»±a. Xin vui lòng nhắp và o há»™p kiểm tiếp sau khoản mục và thá» lại." +bulk_save_error = "Má»™t số dữ liệu thiếu. Khoản mục của bạn không lÆ°u." +bulk_save_success = "Danh sách của bạn đã lÆ°u thà nh công" +By = "Bằng" +by = "Bằng" +By Alphabetical = "Bằng bảng chữ cái" +By Author = "Bằng tác giả" +By Call Number = "Bằng số Ä‘iện thoại" +By Course = "Bằng khóa há»c" +By Department = "Bằng bá»™ môn" +By Era = "Bằng thá»i đại" +By Genre = "Bằng thể loại" +By Instructor = "Bằng huấn luyện viên" +By Popularity = "Bằng sá»± ủng há»™" +By Recent = "Bằng gần đây" +By Region = "Bằng tôn giáo" +By Title = "Bằng tiêu Ä‘á»" +By Topic = "Bằng chủ Ä‘á»" +Call Number = "SÃ´Ì hiệu" +callnumber_abbrev = "Gá»i #" +Cannot find record = "Không thể tìm bản ghi" +Cannot find similar records = "Không tìm ra được bản ghi tÆ°Æ¡ng tá»±" +Cassette = "Băng cát xét" +cat_establish_account = "Äể thiết láºp hồ sÆ¡ tà i khoản của bạn, xin vui lòng nháºp thông tin sau:" +cat_password_abbrev = "Ca-ta-lô máºt khẩu" +cat_username_abbrev = "Ca-ta-lô tên tà i khoản" +Catalog Login = "Ca-ta-lô đăng nháºp" +Catalog Results = "Ca-ta-lô kết quả" +catalog_login_desc = "Nháºp khả năng danh mục liệt kê của thÆ° viện của bạn." +CD = "CD" +Change Password = "Äổi máºt khẩu" +channel_add_more = "Thêm các kênh nhÆ° thế nà y" +channel_browse = "Duyệt nhanh bản ghi hÆ¡n" +channel_expand = "Các kênh liên quan thám hiểm" +channel_explore = "Khám phá kênh" +channel_search = "Hiển thị khoản mục nhÆ° kết quả tìm kiếm" +channel_searchbox_label = "Tìm kiếm các kênh hÆ¡n:" +Check Hold = "Kiểm tra ảnh hưởng" +Check Recall = "Kiểm tra thu hồi" +Checked Out = "Äã kiểm tra" +Checked Out Items = "Các mục đã kiểm tra" +Checkedout = "Äã kiểm tra" +Checkout Date = "Ngà y thanh toán" +Chicago Citation = "TrÃch dẫn kiểu Chicago" +child_record_count = "%%count%% số dòng" +child_records = "Ná»™i dung/Bá»™ pháºn" +Choose a Category to Begin Browsing = "Chá»n thể loại để bắt đầu tìm kiếm" +Choose a Column to Begin Browsing = "Chá»n cá»™t để bắt đầu tìm kiếm" +Choose a List = "Chá»n má»™t danh sách" +choose_login_method = "Má»i chá»n cách đăng nháºp:" +citation_issue_abbrev = "no." +citation_multipage_abbrev = "pp." +citation_singlepage_abbrev = "p." +citation_volume_abbrev = "Vol." +Cite this = "TrÃch dẫn Ä‘iá»u nà y" +City = "Thà nh phố" +Clear = "Dá»n dẹp" +clear_tag_filter = "Dá»n dẹp bá»™ lá»c" +close = "Äóng" +Code = "Mã" +Collection = "Bá»™ sÆ°u táºp" +Collection Browse = "Tìm theo bá»™ sÆ°u táºp" +Collection Items = "Mục bá»™ sÆ°u táºp" +collection_disambiguation = "Äã tìm nhiá»u bá»™ sÆ°u táºp phù hợp" +collection_empty = "Không có mục hiển thị." +collection_view_record = "Xem bản ghi" +Collections = "Nhiá»u bá»™ sÆ°u táºp" +comment_anonymous_user = "Ẩn danh" +comment_error_load = "Lá»—i: Không thể hiển thị danh sách bình luáºn" +comment_error_save = "Lá»—i: Không thể lÆ°u bình luáºn" +Comments = "Những bình luáºn" +Company/Entity = "Công ty/Doanh nghiệp" +Configuration = "Cấu hình" +confirm_delete = "Bạn có chắc muốn xóa nó?" +confirm_delete_brief = "Xóa danh mục?" +confirm_delete_library_card_brief = "Bạn muốn xóa thẻ thÆ° viện?" +confirm_delete_library_card_text = "Bạn có muốn xóa thẻ thÆ° viện nà y không?" +confirm_delete_list_brief = "Xóa danh sách?" +confirm_delete_list_text = "Bạn có chắc muốn xóa danh sách nà y?" +confirm_delete_tags_brief = "Xóa thẻ?" +confirm_dialog_no = "Không" +confirm_dialog_yes = "Äồng ý" +confirm_hold_cancel_all_text = "Bạn có muốn hủy thao tác hiện tại không?" +confirm_hold_cancel_selected_text = "Bạn có muốn hủy lá»±a chá»n hiện tại không?" +confirm_ill_request_cancel_all_text = "Bạn có muá»—n hủy yêu cầu mượn liên thÆ° viện hiện tại không?" +confirm_ill_request_cancel_selected_text = "Bạn có muốn hủy yêu cầu chá»n liên thÆ° viện hiện tại không?" +confirm_new_password = "Nháºp máºt khẩu má»›i" +confirm_storage_retrieval_request_cancel_all_text = "Bạn có muốn hủy tất cả yêu cầu truy xuất bá»™ nhá»› hiện tại của mình không?" +confirm_storage_retrieval_request_cancel_selected_text = "Bạn có muốn hủy yêu cầu truy xuất bá»™ nhá»› đã chá»n của mình không?" +Contents = "Ná»™i dung" +Contributing Source = "Nguồn đóng góp" +Contributors = "Công tác viên" +Coordinates = "Tá»a Ä‘á»™" +Copies = "Bản sao" +Copy = "Sao chép" +Copyright = "Bản quyá»n" +Corporate Author = "Tác giả của công ty" +Corporate Authors = "Nhiá»u tác giả của công ty" +Country = "Quốc gia" +Course = "Khóa há»c" +Course Reserves = "Khóa há»c dá»± trữ" +course_reserves_empty_list = "Không tìm thấy khóa há»a dá»± trữ phù hợp." +Cover Image = "Ảnh bìa" +Create a List = "Tạo danh sách" +Create New Account = "Tạo tà i khoản má»›i" +Create New Password = "Tạo máºt khẩu má»›i" +Created = "Äã tạo" +Database = "CÆ¡ sở dữ liệu" +Date = "Ngà y" +Date of birth = "Sinh nháºt" +Date of death = "Ngà y giá»—" +date_day_placeholder = "D" +date_from = "Từ ngà y" +date_month_placeholder = "M" +date_to = "Tá»›i ngà y" +date_year_placeholder = "Y" +Debug Information = "Thông tin gỡ lá»—i" +del_search = "Bá» nhóm tìm kiếm" +Delete = "Xóa" +delete_account_confirm = "Bạn có chắc muốn xóa tà i khoản?" +delete_account_description_html = "Các lÆ°u trữ tìm kiếm và danh sách yêu thÃch sẽ bị xóa. Bạn vẫn có thể tạo tà i khoản má»›i sau nà y nếu bạn muốn." +delete_account_failure = "Thất bại khi xóa tà i khoản." +delete_account_success_message = "Tà i khoản của bạn đã xóa. Äăng xuất..." +delete_account_title = "Xóa tà i khoản" +delete_all = "Xóa tất cả" +delete_comment_failure = "Không thể xóa bình luáºn." +delete_comment_success = "Bình luáºn đã xóa." +delete_list = "Xóa danh sách" +delete_page = "Xóa trang" +delete_selected = "Xóa đã chá»n" +delete_selected_favorites = "Xóa danh sách yêu thÃch đã chá»n" +delete_tag = "Xóa thẻ" +delete_tags = "Xóa nhiá»u thẻ" +delete_tags_by = "Xóa nhiá»u thẻ bằng" +Department = "Sở" +Description = "Miêu tả" +Desired Username = "Tên ngÆ°á»i dùng mong muốn" +Detailed View = "Detailed View" +Details = "Staff View" +Displaying the top = "Hiển thị hà ng đầu" +Document Inspector = "Kiểm tra tà i liệu" +Document Type = "Kiểu tà i liệu" +DOI = "DOI" +doi_detected_html = "Tìm kiếm của bạn dÆ°á»ng nhÆ° chứa DOI. Nhấp và o đây để kiểm tra tÃnh khả dụng của tà i nguyên: <a href="%%url%%">%%doi%%</a>" +Draw Search Box = "Vẽ há»™p tìm kiếm" +draw_searchbox_end = "Nhả chuá»™t để hoà n thà nh bản vẽ." +draw_searchbox_start = "Nhấp và o kéo để chá»n khu vá»±c." +Due = "Due" +Due Date = "Ngà y đáo hạn" +DVD = "ÄÄ©a DVD" +eBook = "eBook" +Edit = "Chỉnh sá»a" +Edit Library Card = "Chỉnh sá»a thẻ thÆ° viện" +Edit this Advanced Search = "Chỉnh sá»a tìm kiếm nâng cao nà y" +edit_list = "Chỉnh sá»a danh sách" +edit_list_fail = "Xin lá»—i, bạn không có quyá»n chỉnh sá»a danh sách nà y" +edit_list_success = "Danh sách cáºp nháºt thà nh công." +Edition = "Phiên bản" +eds_expander_fulltext = "CÅ©ng tìm kiếm trong toà n bá»™ ná»™i dung của các bà i viết" +eds_expander_relatedsubjects = "Ãp dụng các chủ Ä‘á» tÆ°Æ¡ng Ä‘Æ°Æ¡ng" +eds_expander_thesaurus = "Ãp dụng các từ liên quan" +eds_limiter_FC = "Chỉnh danh mục" +eds_limiter_FC1 = "Chỉ kho lÆ°u trữ thể chế" +eds_limiter_FM6 = "Âm thanh có sẵn" +eds_limiter_FR = "Tham khảo có sẵn" +eds_limiter_FT = "Văn bản đầy đủ" +eds_limiter_FT1 = "Có sẵn trong bá»™ sÆ°u táºp thÆ° viện" +eds_limiter_RV = "Äã dánh giá ngang hà ng" +eds_mode_all = "Tìm tất cả cụm từ tìm kiếm" +eds_mode_any = "Tìm bất kỳ cụm từ tìm kiếm nà o" +eds_mode_bool = "Boolean/Phrase" +eds_mode_smart = "Tìm kiếm thông minh" +eds_modes_and_expanders = "Chế Ä‘á»™ tìm kiếm và tăng cÆ°á»ng" +Electronic = "Äiện tá»" +Email = "Email" +Email Address = "Äịa chỉ email" +Email address is invalid = "Äịa chỉ email không hợp lệ" +Email Record = "Bản ghi email" +Email this = "Email nà y" +Email this Search = "Tìm kiếm email nà y" +email_failure = "Lá»—i - Tin nhắn không thể gởi" +email_link = "Liên kết" +email_maximum_recipients_note = "Tối Ä‘a %%max%% ngÆ°á»i nháºn được phép." +email_multiple_recipients_note = "Bạn có thể chỉ định nhiá»u ngÆ°á»i nháºn được phân tách bằng dấu phẩy." +email_selected = "Email đã chá»n" +email_selected_favorites = "Äanh mục yêu thÃch đã chá»n" +email_sending = "Gởi tin nhắn..." +email_subject = "Môn há»c" +email_success = "Tin nhắn đã gởi" +Empty = "Trống" +Empty Book Bag = "Túi sách rá»—ng" +Enable Auto Config = "Báºt cấu hình tá»± Ä‘á»™ng" +End Page = "Cuối trang" +Era = "Ká»· nguyên" +error_inconsistent_parameters = "Xin lá»—i, đã có lá»—i xảy ra. Äã phát hiện các thông số không nhất quán." +error_page_parameter_list_heading = "Yêu cầu tham số" +Exception = "Ngoại lệ" +Excerpt = "Äoạn trÃch" +exclude_facet = "Loại trừ kết quả phù hợp" +exclude_newspapers = "Loại trừ các bà i viết" +Expires = "Hết hạn" +Export = "Xuất" +Export Favorites = "Xuất mục Æ°a thÃch" +Export Items = "Xuất mục" +Export Record = "Xuất bản ghi" +Export to = "Xuất tá»›i " +export_choose_format = "Hãy chá»n kiểu xuất." +export_download = "Tải táºp tin" +export_exporting = "Tạo táºp tin xuất" +export_fail = "Các mục của bạn không được xuất" +export_invalid_format = "Äịnh dạng xuất đã chá»n không được bản ghi nà y há»— trợ." +export_missing = "Má»™t số dữ liệu bị thiếu. Các mục của bạn chÆ°a được xuất." +export_no_formats = "Hồ sÆ¡ nà y không há»— trợ xuất khẩu." +export_save = "LÆ°u táºp tin" +export_selected = "Xuất lá»±a chá»n" +export_selected_favorites = "Xuất danh mục Æ°u thÃch đã chá»n" +export_send = "Gởi tá»›i %%service%%" +export_success = "Sẵn sà ng xuất" +export_unsupported_format = "Không há»— trợ định đạng xuất" +external_auth_heading = "Truy cáºp tà i liệu được cấp phép" +external_auth_login_message = "Äăng nháºp để truy cáºp tà i liệu được cấp phép" +external_auth_unauthorized = "Bạn không được phép truy cáºp tà i liệu được cấp phép" +external_auth_unauthorized_desc = "PhÆ°Æ¡ng thức đăng nháºp của bạn không cung cấp quyá»n truy cáºp và o tà i liệu được cấp phép. Vui lòng đăng xuất rồi đăng nháºp bằng phÆ°Æ¡ng thức khác." +facet_list_empty = "Không có dữ liệu" +facet_list_for = "Danh sách khÃa cạnh cho %%field%%" +FAQs = "FAQs" +fav_delete = "Xóa mục yêu thÃch đã chá»n" +fav_delete_deleting = "(Các) yêu thÃch của bạn Ä‘ang bị xóa." +fav_delete_fail = "Xin lá»—i, đã có lá»—i xảy ra. (Các) yêu thÃch của bạn không bị xóa." +fav_delete_missing = "Má»™t số dữ liệu bị thiếu. (Các) yêu thÃch của bạn không bị xóa." +fav_delete_success = "(Các) yêu thÃch của bạn đã bị xóa." +fav_delete_warn = "Bạn sắp xóa các mục Æ°a thÃch nà y khá»i tất cả các danh sách của mình - Nếu bạn chỉ muốn xóa các mục Æ°a thÃch khá»i danh sách cụ thể, vui lòng chá»n danh sách trÆ°á»›c khi nhấp và o xóa." +fav_email_fail = "Xin lá»—i, đã có lá»—i xảy ra. (Các) yêu thÃch của bạn không được gá»i qua email." +fav_email_missing = "Má»™t số dữ liệu bị thiếu. (Các) yêu thÃch của bạn không được gá»i qua email." +fav_email_success = "(Các) yêu thÃch của bạn đã được gá»i qua email theo yêu cầu." +fav_export = "Xuất mục Æ°a thÃch" +fav_list_delete = "Danh sách đã bị xóa." +fav_list_delete_cancel = "Danh sách nà y không bị xóa." +fav_list_delete_fail = "Xin lá»—i, đã có lá»—i xảy ra. Danh sách của bạn không bị xóa." +Favorites = "Các mục đã lÆ°u" +Fee = "Há»c phÃ" +Feedback = "Phản hồi" +feedback_email = "Email" +feedback_login_required = "Bạn phải đăng nháºp trÆ°á»›c." +feedback_name = "Tên" +Field of activity = "LÄ©nh vá»±c hoạt Ä‘á»™ng" +File Description = "Mô tả táºp tin" +Filter = "Bá»™ lá»c" +filter_tags = "Thẻ bá»™ lá»c" +filter_wildcard = "Bất kì" +Find = "Tìm kiếm" +Find More = "Tìm thêm" +Find New Items = "Tìm mục má»›i" +Finding Aid = "Tìm viện trợ" +Fine = "Tiá»n phạt" +Fine Date = "Ngà y đẹp trá»i" +fine_limit_patron = "Bạn đã đạt đến giá»›i hạn tiá»n phạt của mình và không thể gia hạn các mục" +Fines = "Tiá»n phạt" +First = "Äầu tiên" +First Name = "Tên" +fix_metadata = "Có, sá»a siêu dữ liệu; tôi sẽ đợi" +for search = "Tìm kiếm" +Forgot Password = "Quên máºt khẩu" +Form Submitted! = "Äã gởi biểu mẫu!" +Format = "Äịnh dạng" +From = "Từ" +Full description = "Mô tả đầy đủ" +Full text is not displayed to guests = "Văn bản không được hiển thị cho khách." +fulltext_limit = "Giá»›i hạn bà i viết vá»›i văn bản có sẵn" +Gender = "Giá»›i tÃnh" +Genre = "Thể loại" +Geographic Search = "Tìm kiếm địa lý" +Geographic Terms = "Äiá»u khoản địa lý" +Geography = "Äịa lý" +Get full text = "lấy văn bản" +Get more information = "Lấy nhiá»u thông tin" +Get RSS Feed = "Nháºn nguồn cấp dữ liệu RSS" +Globe = "Quả địa cầu" +Go = "Chuyển đến" +Go to Standard View = "Chuyển đến chế Ä‘á»™ xem chuẩn" +go_to_list = "Chuyển tá»›i danh sách" +google_map_cluster = "Cluster" +google_map_cluster_points = "Äiểm Cluster" +Grid = "LÆ°á»›i" +Group = "Nhóm" +group_AND = "Tất cả các nhóm" +group_OR = "Bất kỳ nhóm" +Has Illustrations = "Có hình minh há»a" +Help = "Trợ giúp" +Help with Advanced Search = "Trợ giúp vá»›i tìm kiếm nâng cao" +Help with Search Operators = "Trợ giúp vá»›i toán tá» tìm kiếm" +help_page_missing = "Trang trợ giúp yêu cầu không tồn tại." +hierarchy_hide_tree = "Ẩn phân cấp đầy đủ" +hierarchy_show_tree = "Hiện phân cấp đầy đủ" +hierarchy_tree = "Äịnh nghÄ©a văn bản" +hierarchy_tree_error = "Rất tiếc, chúng tôi không thể tải cây phân cấp" +hierarchy_view_context = "Xem định nghÄ©a văn bản" +History = "Lịch sá»" +history_delete = "Xóa" +history_delete_link = "Xóa" +history_empty_search = "Má»i thú (Tìm kiếm rá»—ng)" +history_limits = "Giá»›i hạn" +history_no_searches = "Hiện không có tìm kiếm nà o trong lịch sá» của bạn." +history_purge = "Lá»c các tìm kiếm chÆ°a lÆ°u" +history_recent_searches = "Tìm kiếm gần đây" +history_results = "Các kết quả" +history_save = "LÆ°u không?" +history_save_link = "LÆ°u" +history_saved_searches = "Tìm kiếm đã lÆ°u" +history_search = "Tìm kiếm" +history_time = "Thá»i gian" +hold_available = "Có sẵn để nháºn" +hold_available_until = "Có sẵn để nháºn cho tá»›i khi %%date%%" +hold_cancel = "Hủy giữ" +hold_cancel_all = "Hủy tất cả các lần giữ" +hold_cancel_fail = "Yêu cầu của bạn không bị hủy. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +hold_cancel_selected = "Hủy các khoản giữ đã chá»n" +hold_cancel_success = "Yêu cầu của bạn đã hủy thà nh công" +hold_cancel_success_items = "%%count%% (các) yêu cầu đã được hủy thà nh công" +hold_date_invalid = "Vui lòng nháºp ngà y hợp lệ" +hold_date_past = "Vui lòng nháºp má»™t ngà y trong tÆ°Æ¡ng lai" +hold_empty_selection = "Không có khoản giữ nà o được chá»n" +hold_error_blocked = "Bạn không có đủ đặc quyá»n để đặt khoản giữ trên mặt hà ng nà y" +hold_error_fail = "Yêu cầu của bạn không thà nh công. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +hold_invalid_pickup = "Äã nháºp vị trà tìm kiếm không hợp lệ. Vui lòng thá» lại" +hold_invalid_request_group = "Nhóm yêu cầu giữ không hợp lệ đã được nháºp. Vui lòng thá» lại" +hold_items_available = "Không thể đặt lệnh giữ vì các mục có sẵn." +hold_login = "Äăng nháºp để giữ và thu hồi thông tin" +hold_place = "Yêu cầu địa Ä‘iểm" +hold_place_fail_missing = "Yêu cầu của bạn không thà nh công. Má»™t số dữ liệu bị thiếu. Vui lòng liên hệ vá»›i bà n lÆ°u hà nh để được trợ giúp thêm" +hold_place_success_html = "Yêu cầu của bạn đã thà nh công. <a href="%%url%%">Giữ và thu hồi của bạn</a>." +hold_profile_html = "Äể giữ và thu hồi thông tin, vui lòng thiết láºp <a href="%%url%%">Hồ sÆ¡ danh mục thÆ° viện</a>." +hold_queue_position = "Vị trà xếp hà ng" +hold_record_already_on_loan = "Bạn đã có hồ sÆ¡ vá» mượn" +hold_request_group = "Yêu cầu từ" +hold_requested_group = "Äã yêu cầu từ" +hold_required_by = "Không còn cần thiết sau" +hold_success = "Yêu cầu của bạn đã thà nh công" +Holdings = "Äang giữ" +Holdings at Other Libraries = "Äang giữ tại các thÆ° viện khác" +holdings_details_from = "Chi tiết quỹ từ %%location%%" +Holdings_notes = "Ghi chú" +Holds = "Nắm giữ" +Holds and Recalls = "Giữ và thu hồi" +Home = "Trang chủ" +home_browse = "Tìm theo" +HTML Full Text = "HTML toà n văn" +Identifier = "Số nháºn dạng" +ill_request_available = "Có sẵn cho nháºn" +ill_request_cancel = "Hủy yêu cầu mượn liên thÆ° viện" +ill_request_cancel_all = "Hủy tất cả yêu cầu khoản vay liên thÆ° viện" +ill_request_cancel_fail = "Yêu cầu của bạn không bị hủy. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +ill_request_cancel_selected = "Hủy yêu cầu khoản mượn liên thÆ° viện đã chá»n" +ill_request_cancel_success = "Yêu cầu của bạn đã được hủy thà nh công" +ill_request_cancel_success_items = "%%count%% (các) yêu cầu đã được hủy thà nh công" +ill_request_canceled = "Äã hủy" +ill_request_check_text = "Kiểm tra yêu cầu mượn liên thÆ° viện" +ill_request_comments = "Bình luáºn" +ill_request_date_invalid = "Vui lòng nháºp ngà y hợp lệ" +ill_request_date_past = "Vui lòng nháºp ngà y trong tÆ°Æ¡ng lai" +ill_request_empty_selection = "Không có yêu cầu mượn liên thÆ° viện nà o được chá»n" +ill_request_error_blocked = "Bạn không có đủ đặc quyá»n để yêu cầu mượn liên thÆ° viện trên quyển sách nà y" +ill_request_error_fail = "Yêu cầu của bạn không thà nh công. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +ill_request_error_technical = "Yêu cầu của bạn không thà nh công do lá»—i hệ thống. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +ill_request_error_unknown_patron_source = "ThÆ° viện bảo trợ không được xác định trong yêu cầu mượn liên thÆ° viện." +ill_request_invalid_pickup = "Äã nháºp vị trà không hợp lệ. Vui lòng thá» lại" +ill_request_pick_up_library = "Chá»n thÆ° viện" +ill_request_pick_up_location = "Chá»n địa Ä‘iểm" +ill_request_place_fail_missing = "Yêu cầu của bạn không thà nh công. Má»™t số dữ liệu bị thiếu. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +ill_request_place_success = "Yêu cầu của bạn đã thà nh công" +ill_request_place_success_html = "Yêu cầu của bạn đã thà nh công. <a href="%%url%%">Yêu cầu mượn liên thÆ° viện</a>." +ill_request_place_text = "Äặt yêu cầu mượn liên thÆ° viện" +ill_request_processed = "Xá» lý" +ill_request_profile_html = "Äể biết thông tin yêu cầu mượn liên thÆ° viện, vui lòng thiết láºp <a href="%%url%%">Hồ sÆ¡ danh mục thÆ° viện</a>." +ill_request_submit_text = "Yêu cầu địa Ä‘iểm" +Illustrated = "Minh há»a" +ils_account_create_error = "Không thể tạo tà i khoản của bạn trong hệ thống quản lý thÆ° viện của chúng tôi. Nếu sá»± cố vẫn tiếp diá»…n, vui lòng liên hệ vá»›i thÆ° viện của bạn." +ils_action_unavailable = "Chức năng được yêu cầu không khả dụng vá»›i thẻ thÆ° viện hoạt Ä‘á»™ng." +ils_connection_failed = "Không thể kết nối vá»›i hệ thống quản lý thÆ° viện. Không thể hiển thị thông tin liên quan đến tà i khoản thÆ° viện của bạn. Nếu sá»± cố vẫn tiếp diá»…n, vui lòng liên hệ vá»›i thÆ° viện của bạn." +ils_offline_holdings_message = "Thông tin vá» trạng thái tà i khoản và mục khả dụng hiện không khả dụng. Vui lòng chấp nháºn lá»i xin lá»—i của chúng tôi vì bất kỳ sá»± bất tiện nà o mà điá»u nà y có thể gây ra và liên hệ vá»›i chúng tôi để được há»— trợ thêm:" +ils_offline_home_message = "Chi tiết tà i khoản của bạn và thông tin mục trá»±c tiếp sẽ không khả dụng trong thá»i gian nà y. Vui lòng chấp nháºn lá»i xin lá»—i của chúng tôi vì bất kỳ sá»± bất tiện nà o mà điá»u nà y có thể gây ra và liên hệ vá»›i chúng tôi để được há»— trợ thêm:" +ils_offline_login_message = "Chi tiết tà i khoản của bạn sẽ không khả dụng trong thá»i gian nà y. Vui lòng chấp nháºn lá»i xin lá»—i của chúng tôi vì bất kỳ sá»± bất tiện nà o mà điá»u nà y có thể gây ra và liên hệ vá»›i chúng tôi để được há»— trợ thêm:" +ils_offline_status = "Hệ thống quản lý thÆ° viện của chúng tôi hiện Ä‘ang được bảo trì." +ils_offline_title = "Hệ thống Ä‘ang được bảo trì" +ils_transaction_history_disabled = "Lịch sá» cho mượn không được kÃch hoạt cho thẻ thÆ° viện hoạt Ä‘á»™ng." +Import Record = "Nháºp bản ghi" +in = "trong" +In This Collection = "Trong bá»™ sÆ°u táºp nà y" +in_collection_label = "Trong bá»™ sÆ°u táºp:" +include_synonyms = "Mở rá»™ng kết quả bằng từ đồng nghÄ©a" +Index Terms = "Äiá»u khoản chỉ mục" +Indexes = "Chỉ mục" +information = "Thông tin" +Institution = "Tổ chức giáo dục" +Institutional Login = "Äăng nháºp tổ chức" +institutional_login_desc = "Nháºp tên ngÆ°á»i dùng và máºt khẩu toà n trÆ°á»ng của bạn." +Instructor = "NgÆ°á»i hÆ°á»›ng dẫn" +Interlibrary Loan Requests = "Yêu cầu khoản mượn liên thÆ° viện" +Internet = "Internet" +Invalid Patron Login = "Äăng nháºp ngÆ°á»i bảo trợ không hợp lệ" +Invalid phone number. = "Số Ä‘iện thoại không hợp lệ." +Invalid Recipient Email Address = "Äịa chỉ email ngÆ°á»i nháºn không hợp lệ" +Invalid Sender Email Address = "Äịa chỉ email ngÆ°á»i gá»i không hợp lệ" +ISBN = "số ISBN" +ISBN/ISSN = "số ISBN/ISSN" +ISSN = "số ISSN" +Issue = "Vấn Ä‘á»" +Item Description = "Mô tả sách" +Item Notes = "Ghi chú" +Item removed from favorites = "Äã xóa sách khá»i mục yêu thÃch" +Item removed from list = "Äã xóa sách khá»i danh sách" +Items = "Cuốn sách" +items = "cuốn sách" +items_added_to_bookbag = "%%count%% quyển sách đã được thêm và o Túi sách của bạn" +items_already_in_bookbag = "%%count%% (các) quyển sách đã có trong Túi Sách của bạn hoặc không thể được thêm và o" +Journal = "Tạp chÃ" +Journal Articles = "Bà i viết tạp chÃ" +Journal Info = "Thông tin tạp chÃ" +Journal Title = "Tiêu Ä‘á» tạp chÃ" +Journals = "Nhiá»u tạp chÃ" +Jump to = "Chuyển đến" +just_cataloged = "Chỉ cần láºp danh mục" +Keyword = "Từ khóa" +Keyword Filter = "Bá»™ lá»c từ khóa" +Kit = "Bá»™ dụng cụ" +Language = "Ngôn ngữ" +large = "Lá»›n" +Last = "Cuối" +Last Modified = "Sá»a đổi lần cuối" +Last Name = "Há»" +less = "Ãt hÆ¡n" +libphonenumber_invalid = "Số Ä‘iện thoại không hợp lệ" +libphonenumber_invalidcountry = "Mã gá»i quốc gia không hợp lệ" +libphonenumber_invalidregion = "Mã vùng không hợp lệ:" +libphonenumber_notanumber = "Chuá»—i được cung cấp dÆ°á»ng nhÆ° không phải là số Ä‘iện thoại" +libphonenumber_toolong = "Chuá»—i được cung cấp quá dà i để là số Ä‘iện thoại" +libphonenumber_tooshort = "Chuá»—i được cung cấp quá ngắn để không phải là số Ä‘iện thoại" +libphonenumber_tooshortidd = "Số Ä‘iện thoại quá ngắn sau IDD" +Library = "ThÆ° viện" +Library Card = "Thẻ thÆ° viện" +Library Card Deleted = "Thẻ thÆ° viện đã bị xóa" +Library Card Name = "Tên thẻ thÆ° viện" +Library Cards = "Thẻ thÆ° viện" +Library Cards Disabled = "Thẻ thÆ° viện bị vô hiệu hóa" +Library Catalog Password = "Máºt khẩu danh mục thÆ° viện" +Library Catalog Profile = "Hồ sÆ¡ danh mục thÆ° viện" +Library Catalog Record = "Bản ghi danh mục thÆ° viện" +Library Catalog Search = "Tìm kiếm danh mục thÆ° viện" +Library Catalog Search Result = "Kết quả tìm kiếm danh mục thÆ° viện" +Library Catalog Username = "Tên ngÆ°á»i dùng danh mục thÆ° viện" +Library Web Search = "Tìm kiếm của thÆ° viện" +library_card_edit_password_placeholder = "Máºt khẩu má»›i" +lightbox_error = "Lá»—i: Không thể tải há»™p báºt lên" +Limit To = "Giá»›i hạn" +List = "Danh sách" +List Tags = "Danh sách thẻ" +list_access_denied = "Bạn không có quyá»n xem danh sách nà y." +list_edit_name_required = "Tên danh sách là bắt buá»™c." +load_tag_error = "Lá»—i: Không thể tải thẻ" +Loading = "Äang tải" +Loan History = "Lịch sá» cho vay" +loan_history_empty = "Bạn không có bất kỳ khoản mượn nà o trong lịch sá» cho mượn." +Local Login = "Äăng nháºp cục bá»™" +local_login_desc = "Nháºp tên ngÆ°á»i dùng và máºt khẩu bạn đã tạo cho trang web nà y." +Located = "Nằm" +Location = "Vị trÃ" +Log Out = "Äăng xuất" +Login = "Äăng nháºp" +Login for full access = "Äăng nháºp để truy cáºp đầy đủ." +login_disabled = "Äăng nháºp không khả dụng tại thá»i Ä‘iểm nà y." +login_target = "ThÆ° viện" +Logout = "Äăng xuất" +Main Author = "Tác giả chÃnh" +Main Authors = "Những tác giả chÃnh" +Major Categories = "Danh mục chÃnh" +Manage Tags = "Quản lý thẻ" +Manuscript = "Bản thảo" +Map = "Bản đồ" +Map View = "Chế Ä‘á»™ xem bản đồ" +map_results_label = "Tại vị trà nà y:" +Maps = "Bản đồ" +Media Format = "Äịnh dạng phÆ°Æ¡ng tiện thông tin" +medium = "Trung bình" +MeSH Terms = "Äiá»u khoản MeSH" +Message = "Thông Ä‘iệp" +Message From Sender = "Thông báo từ ngÆ°á»i gá»i" +Metadata Prefix = "Tiá»n tố siêu dữ liệu" +Microfilm = "Microfilm" +MLA Citation = "TrÃch dẫn MLA" +Mobile Number = "Số Ä‘iện thoại" +mobile_link = "DÆ°á»ng nhÆ° bạn Ä‘ang ở trên thiết bị di Ä‘á»™ng; chuyển sang chế Ä‘á»™ xem di Ä‘á»™ng?" +Monograph Title = "Tiêu Ä‘á» chuyên khảo" +more = "hÆ¡n" +More catalog results = "Kết quả danh mục khác" +More options = "Lá»±a chá»n khác" +More Summon results = "Kết quả triệu hồi khác" +More Topics = "Chủ Ä‘á» khác" +more_authors_abbrev = "et al." +more_info_toggle = "Hiện / ẩn thêm thông tin" +more_topics = "%%count%% nhiá»u chủ Ä‘á» hÆ¡n" +Most Recent Received Issues = "Các vấn đỠđã nháºn gần đây nhất" +Multiple Call Numbers = "Nhiá»u số cuá»™c gá»i" +Multiple Locations = "Nhiá»u địa Ä‘iểm" +Musical Score = "Äiểm nhạc" +My Favorites = "Yêu thÃch" +My Fines = "Tiá»n phạt" +My Holds = "Nắm giữ" +My Profile = "Hồ sÆ¡" +Narrow Search = "Tìm kiếm hẹp" +navigate_back = "Trở lại" +nearby_items = "Sách gần "%%title%%"" +Need Help? = "Cần giúp đỡ?" +New Item Feed = "Nguồn cấp dữ liệu sách má»›i" +New Item Search = "Tìm kiếm sách má»›i" +New Item Search Results = "Kết quả tìm kiếm sách má»›i" +New Items = "Sách má»›i" +New Title = "Tiêu Ä‘á» má»›i" +new_password = "Máºt khẩu má»›i" +new_password_success = "Máºt khẩu của bạn đã được thay đổi thà nh công" +new_user_welcome_subject = "Tà i khoản má»›i của bạn tại %%library%%" +new_user_welcome_text = "Xin chà o tá»›i %%library%%. Má»™t tà i khoản má»›i đã được mở cho %%firstname%% %%lastname%%. Tà i khoản của bạn là %%username%%. Vui lòng đặt máºt khẩu trên trang nà y: %%url%%" +Newspaper = "Báo chÃ" +Next = "Tiếp theo" +No citations are available for this record = "Không có trÃch dẫn nà o cho hồ sÆ¡ nà y" +No Cover Image = "Không có hình ảnh bìa" +No dependency problems found = "Không tìm thấy vấn Ä‘á» phụ thuá»™c" +No excerpts were found for this record. = "Không tìm thấy trÃch Ä‘oạn nà o cho hồ sÆ¡ nà y." +No library account = "Không có tà i khoản thÆ° viện" +No new item information is currently available. = "Hiện không có thông tin sách má»›i nà o." +No Preference = "Không có sở thÃch" +No reviews were found for this record = "Không tìm thấy bà i đánh giá nà o cho hồ sÆ¡ nà y" +No Tags = "Không có thẻ" +no_description = "Mô tả không khả dụng." +no_items_selected = "Không có mục nà o được chá»n" +nohit_active_filters = "Má»™t hoặc nhiá»u bá»™ lá»c khÃa cạnh đã được áp dụng cho tìm kiếm nà y. Nếu bạn xóa bá»™ lá»c, bạn có thể truy xuất thêm kết quả." +nohit_change_tab = "Bạn đã tìm kiếm trong tab "%%activeTab%%". Bạn có thể tìm thấy thứ gì đó ở má»™t trong các tab khác:" +nohit_filters = "Các bá»™ lá»c hiện được áp dụng cho tìm kiếm nà y:" +nohit_heading = "Ko có kết quả!" +nohit_lookfor_html = "Tìm kiếm của bạn - <strong>%%lookfor%%</strong> - không khá»›p vá»›i bất kỳ tà i nguyên nà o." +nohit_no_filters = "Không có bá»™ lá»c nà o được áp dụng cho tìm kiếm nà y." +nohit_parse_error = "DÆ°á»ng nhÆ° có sá»± cố vá»›i truy vấn tìm kiếm của bạn. Vui lòng kiểm tra cú pháp. Nếu bạn không cố gắng sá» dụng các tÃnh năng nâng cao, việc đặt truy vấn bên trong dấu nháy kép có thể hữu Ãch." +nohit_query_without_filters = "Xóa tất cả bá»™ lá»c khá»i tìm kiếm nà y." +nohit_spelling = "Có lẽ bạn nên thá» má»™t số biến thể chÃnh tả" +nohit_suggest = "Bạn có thể muốn sá»a đổi cụm từ tìm kiếm của mình bằng cách xóa má»™t số từ hoặc kiểm tra chÃnh tả của bạn." +NOT = "Không" +Not Illustrated = "Không được minh há»a" +Not On Reserve = "Không đặt trÆ°á»›c" +not_applicable = "n/a" +Note = "Chú thÃch" +note_760 = "Truyện chÃnh" +note_762 = "Äăng ký" +note_765 = "Bản dịch của" +note_767 = "Dịch" +note_770 = "Có bổ sung" +note_772 = "Bổ sung cho" +note_773 = "Chứa trong" +note_774 = "ÄÆ¡n vị cấu thà nh" +note_775 = "Ấn bản khác có sẵn" +note_776 = "Biểu mẫu bổ sung" +note_777 = "Ban hà nh vá»›i" +note_780_0 = "Tiếp tục" +note_780_1 = "Tiếp tục má»™t phần" +note_780_2 = "Bá» qua" +note_780_3 = "Bá» qua má»™t phần" +note_780_4 = "Äược hình thà nh bởi" +note_780_5 = "Hấp thụ" +note_780_6 = "Hấp thụ má»™t phần" +note_780_7 = "Tách biệt vá»›i" +note_785_0 = "Tiếp tục bởi" +note_785_1 = "Tiếp tục má»™t phần bởi" +note_785_2 = "Thay thế bởi" +note_785_3 = "Thay thế má»™t phần bởi" +note_785_4 = "Bị hấp thụ bởi" +note_785_5 = "Hấp thụ má»™t phần bởi" +note_785_6 = "Chia thà nh" +note_785_7 = "Hợp nhất vá»›i / Biểu mẫu" +note_785_8 = "Äã thay đổi trở lại" +note_787 = "Mối quan hệ khác" +Notes = "Ghi chú" +Number = "Con số" +number_decimal_point = "." +number_thousands_separator = "," +OAI Server = "Máy chủ OAI" +Occupation = "Nghá» nghiệp" +of_num_results = "#%%position%% của %%total%% kết quả" +old_password = "Máºt khẩu cÅ©" +On Reserve = "Ngà y dá»± trữ" +On Reserve - Ask at Circulation Desk = "Ngà y dá»± trữ - Há»i tại quầy lÆ°u hà nh" +on_reserve = "Dá»± trữ - Yêu cầu lÆ°u hà nh" +on_topic = "%%count%% (các) sách vá» chủ Ä‘á» nà y" +Online Access = "Truy cáºp trá»±c tuyến" +online_resources = "Bà i toà n văn" +open_access_limit = "Giá»›i hạn ná»™i dung Truy cáºp mở" +operator_contains = "chứa" +operator_exact = "là (chÃnh xác)" +OR = "Hoặc" +or create a new list = "hoặc tạo danh sách má»›i" +original = "Nguyên văn" +Other associated place = "Äịa Ä‘iểm liên quan khác" +Other Authors = "Tác giả khác" +Other Editions = "Các ấn bản khác" +Other Libraries = "ThÆ° viện khác" +Other Sources = "Những nguồn khác" +Page not found. = "Không tìm thấy trang." +Password = "Máºt khẩu" +Password Again = "Nháºp lại máºt khẩu" +Password cannot be blank = "Không được để trống máºt khẩu" +password_error_invalid = "Máºt khẩu má»›i không hợp lệ (và dụ: chứa các ký tá»± không hợp lệ)" +password_error_not_unique = "Máºt khẩu không được thay đổi" +password_maximum_length = "Äá»™ dà i máºt khẩu tối Ä‘a là %%maxlength%% ký tá»±" +password_minimum_length = "Äá»™ dà i máºt khẩu tối thiểu là %%minlength%% ký tá»±" +password_only_alphanumeric = "Chỉ số và chữ cái A-Z" +password_only_numeric = "Chỉ số" +Passwords do not match = "Máºt khẩu không đúng" +past_days = "%%range%% ngà y trÆ°á»›c" +PDF Full Text = "Bà i toà n văn PDF" +peer_reviewed = "Äã đánh giá ngang hà ng" +peer_reviewed_limit = "Giá»›i hạn bà i viết từ các tạp chà được đánh giá ngang hà ng" +permission_denied = "Bạn đã yêu cầu má»™t trang hoặc hà nh Ä‘á»™ng, nhÆ°ng bạn không có quyá»n cần thiết." +permission_denied_title = "Quyá»n bị từ chối" +Phone Number = "Số Ä‘iện thoại" +Photo = "Ảnh" +Physical Description = "Mô tả váºt lý" +Physical Object = "Váºt lý" +pick_up_location = "Chá»n địa Ä‘iểm" +Place a Hold = "Äặt Giữ" +Place of birth = "NÆ¡i sinh" +Place of death = "NÆ¡i an nghỉ" +Playing Time = "Giá» chÆ¡i" +Please check back soon = "Là m Æ¡n hãy kiểm tra lại sá»›m" +Please contact the Library Reference Department for assistance = "Vui lòng liên hệ vá»›i Phòng Tham khảo ThÆ° viện để được há»— trợ" +Please enable JavaScript. = "Vui lòng báºt JavaScript." +Please upgrade your browser. = "Vui lòng nâng cấp trình duyệt của bạn." +Preferences = "Sở thÃch" +Preferred Library = "ThÆ° viện Æ°u tiên" +Prev = "TrÆ°á»›c" +Preview = "Xem trÆ°á»›c" +Preview from = "Xem trÆ°á»›c từ" +Previous Title = "Tiêu Ä‘á» trÆ°á»›c" +Print = "In" +print_selected = "In đã chá»n" +Private = "Riêng tÆ°" +Production Credits = "Sản phẩm tÃn dụng" +Profile = "Hồ sÆ¡" +profile_update = "Hồ sÆ¡ của bạn đã được cáºp nháºt theo yêu cầu" +pronounced = "phát âm" +Provider = "Các nhà cung cấp" +Public = "Công khai" +Publication = "Ấn phẩm" +Publication Date = "Ngà y xuất bản" +Publication Frequency = "Tần suất xuất bản" +Publication Information = "Thông tin xuất bản" +Publication Type = "Loại xuất bản" +Publication Year = "Năm xuất bản" +Publication_Place = "NÆ¡i xuất bản" +Published = "Äược phát hà nh" +Published in = "Xuất bản năm" +Publisher = "Nhà xuất bản" +Publisher Information = "Thông tin nhà xuất bản" +Publisher Permissions = "Quyá»n của nhà xuất bản" +QR Code = "Mã QR" +qrcode_hide = "Ẩn mã QR" +qrcode_show = "Hiển thị mã QR" +query time = "thá»i gian truy vấn" +random_recommendation_title = "Các quyển sách ngẫu nhiên từ kết quả của bạn" +Range = "Phạm vi" +Range slider = "Phạm vi thanh trượt " +Read the full review online... = "Äá»c toà n bá»™ đánh giá trá»±c tuyến ..." +Recall This = "Gá»i lại Ä‘iá»u nà y" +recaptcha_not_passed = "CAPTCHA không được thông qua" +recently_returned_channel_title = "Äã trả lại gần đây" +Record Citations = "Ghi lại trÃch dẫn" +Record Count = "Số bản ghi" +Record Type = "Loại bản ghi" +Recover Account = "Khôi phục tà i khoản" +recovery_by_email = "Khôi phục bằng email" +recovery_by_username = "Khôi phục bằng tên ngÆ°á»i dùng" +recovery_disabled = "Khôi phục máºt khẩu không được báºt" +recovery_email_notification = "Yêu cầu được thá»±c hiện để khôi phục máºt khẩu cho tà i khoản của bạn vá»›i %%library%%." +recovery_email_sent = "HÆ°á»›ng dẫn khôi phục máºt khẩu đã được gá»i đến địa chỉ email đã đăng ký vá»›i tà i khoản nà y." +recovery_email_subject = "Khôi phục tà i khoản VuFind" +recovery_email_url_pretext = "Bạn có thể đặt lại máºt khẩu của mình tại URL nà y: %%url%%" +recovery_expired_hash = "Liên kết khôi phục nà y đã hết hạn" +recovery_invalid_hash = "Liên kết khôi phục không được nháºn dạng" +recovery_new_disabled = "Bạn không được phép thay đổi máºt khẩu của mình và o lúc nà y" +recovery_title = "Khôi phục máºt khẩu" +recovery_too_soon = "Quá nhiá»u yêu cầu khôi phục đã được thá»±c hiện, vui lòng thá» lại sau" +recovery_user_not_found = "Chúng tôi không thể tìm thấy tà i khoản của bạn" +rectangle_center_message = "Äây là điểm trung tâm của hình chữ nháºt được đánh dấu" +Refine Results = "Tinh chỉnh kết quả" +Region = "Miá»n" +relais_available = "Mục nà y có sẵn thông qua cho mượn Liên thÆ° viện. Bạn có muốn yêu cầu không?" +relais_checking = "Äang kiểm tra tÃnh khả dụng ..." +relais_error_html = "Äã xảy ra sá»± cố vá»›i yêu cầu nà y. Nhấp chuá»™t <a href="%%url%%" target='new'>here</a> để yêu cầu mục nà y sá» dụng trang web mượn Liên thÆ° viện." +relais_request = "Yêu cầu mượn liên thÆ° viện" +relais_requesting = "Äang yêu cầu ..." +relais_search = "Tìm kiếm thÆ° viện liên thÆ° viện" +relais_success_label = "Xác nháºn:" +relais_success_message = "Id yêu cầu #%%id%% đã được tạo. Bạn sẽ nháºn được má»™t email xác nháºn." +Related Author = "Tác giả liên quan" +Related Items = "Các quyển sách có liên quan" +Related Subjects = "Các môn há»c liên quan" +Remove Filters = "Xóa bá»™ lá»c" +Remove from Book Bag = "Xóa khá»i Túi Sách" +renew_all = "Gia hạn tất cả các mục" +renew_determine_fail = "Chúng tôi không thể xác định liệu sách của bạn có thể được gia hạn hay không. Vui lòng liên hệ vá»›i má»™t nhân viên." +renew_empty_selection = "Không có sách nà o được chá»n" +renew_error = "Chúng tôi không thể gia hạn (các) sách của bạn - Vui lòng liên hệ vá»›i nhân viên của chúng tôi" +renew_fail = "Không thể gia hạn sách nà y" +renew_item = "Gia hạn sách" +renew_item_due = "Sách đến hạn trong vòng 24 giá» tá»›i" +renew_item_due_tooltip = "Sắp có hà ng" +renew_item_limit = "Sách nà y đã đạt đến giá»›i hạn gia hạn của nó" +renew_item_no = "Không thể gia hạn sách nà y" +renew_item_overdue = "Sách quá hạn" +renew_item_overdue_tooltip = "Những sách quá hạn" +renew_item_requested = "Sách nà y đã được má»™t ngÆ°á»i dùng khác yêu cầu" +renew_select_box = "Gia hạn sách" +renew_selected = "Gia hạn các sách đã chá»n" +renew_success = "Gia hạn thà nh công" +Renewed = "Äã gia hạn" +Request full text = "Yêu cầu bà i toà n văn" +request_in_transit = "Äang trên Ä‘Æ°á»ng tá»›i chá»n địa Ä‘iểm" +request_place_text = "Äặt yêu cầu" +request_submit_text = "Gá»i lá»i Ä‘á» nghị" +Requests = "Yêu cầu" +Reserves = "Dá»± trữ" +Reserves Search = "Tìm kiếm dá»± trữ" +Reserves Search Results = "LÆ°u trữ kết quả tìm kiếm" +result_checkbox_label = "Chá»n kết quả số %%number%%" +result_count = "%%count%% kết quả" +Results = "Kết quả" +results = "kết quả" +Results for = "Kết quả cho" +Results per page = "Kết quả má»—i trang" +Resumption Token = "Mã thông báo tiếp tục" +Return Date = "Ngà y trở lại" +Review by = "Duyệt laÌ£i bởi" +Reviews = "Duyệt laÌ£i" +Save = "LÆ°u" +Save Comment = "LÆ°u nháºn xét" +save_search = "LÆ°u tìm kiếm" +save_search_remove = "Xóa Tìm kiếm đã LÆ°u" +Saved in = "Äã lÆ°u trong" +scholarly_limit = "Giá»›i hạn bà i viết từ các tạp chà há»c thuáºt" +Scroll to Load More = "Cuá»™n để tải thêm" +Search = "Tìm kiếm" +Search For = "Tìm kiếm" +Search For Items on Reserve = "Tìm kiếm các quyển sách vá» dá»± trữ" +Search History = "Lịch sá» tìm kiếm" +Search Home = "Trang chủ tìm kiếm" +Search Mode = "Chế Ä‘á»™ tìm kiếm" +Search Options = "Tùy chá»n tìm kiếm" +Search Results = "Kết quả tìm kiếm" +search results of = "Kết quả tìm kiếm của" +Search Tips = "Mẹo tìm kiếm" +Search Tools = "Công cụ tìm kiếm" +Search Type = "Loại tìm kiếm" +search_AND = "Tất cả Ä‘iá»u khoản" +search_groups = "Tìm kiếm nhóm" +search_match = "Phù hợp" +search_NOT = "Không có Ä‘iá»u khoản" +search_OR = "Bấy kỳ Ä‘iá»u khoản" +search_save_success = "Tìm kiếm được lÆ°u thà nh công." +search_terms = "Cụm từ tìm kiếm" +search_unsave_success = "Äã xóa tìm kiếm đã lÆ°u thà nh công." +seconds_abbrev = "s" +see all = "Xem tất cả" +See also = "Xem thêm" +Select this record = "Chá»n bản ghi nà y" +Select your carrier = "Chá»n nhà cung cấp dịch vụ của bạn" +select_page = "Chá»n trang" +select_pickup_location = "Chá»n địa Ä‘iểm tìm kiếm" +select_request_group = "Chá»n nhóm yêu cầu" +Selected = "Äã chá»n" +Send = "Gởi" +Send us your feedback! = "Gá»i cho chúng tôi phản hồi của bạn!" +send_an_email_copy = "Gá»i má»™t bản sao đến địa chỉ nà y" +send_email_copy_to_me = "Gá»i má»™t bản sao cho tôi" +Sensor Image = "Hình ảnh cảm biến" +Serial = "Số seri" +Series = "Loạt" +Set = "Bá»™" +showing_items_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> quyển sách" +showing_items_of_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> của <strong>%%total%%</strong> quyển sách" +showing_results_for_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> kết quả tìm kiếm '<strong>%%lookfor%%</strong>'" +showing_results_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> results" +showing_results_of_for_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> kết quả của <strong>%%total%%</strong> cho tìm kiếm '<strong>%%lookfor%%</strong>'" +showing_results_of_html = "Äang hiển thị <strong>%%start%% - %%end%%</strong> kết quả của <strong>%%total%%</strong>" +sidebar_close = "Thu gá»n Thanh bên" +sidebar_expand = "Mở rá»™ng thanh bên" +Similar Items = "Những quyển sách tÆ°Æ¡ng tá»±" +Skip to content = "Chuyển đến ná»™i dung" +skip_confirm = "Bạn có chắc chắn muốn bá» qua bÆ°á»›c nà y không?" +skip_fix_metadata = "Không sá»a siêu dữ liệu tại thá»i Ä‘iểm nà y." +skip_step = "Bá» qua bÆ°á»›c nà y" +Slide = "Slide" +sms_failure = "Lá»—i! Không thể gá»i tin nhắn." +sms_phone_number = "Số Ä‘iện thoại gồm 10 số" +sms_sending = "Äang gởi tin nhắn..." +sms_success = "Tin nhắn đã gởi." +Software = "Phần má»m" +Sorry, but the help you requested is unavailable in your language. = "Xin lá»—i, nhÆ°ng sá»± trợ giúp bạn yêu cầu không có sẵn trong ngôn ngữ của bạn." +Sort = "Sắp xếp" +sort_alphabetic = "Theo thứ tá»± chữ cái" +sort_author = "Tác giả" +sort_author_author = "Theo thứ tá»± chữ cái" +sort_author_relevance = "Mức Ä‘á»™ phổ biến" +sort_callnumber = "Số cuá»™c gá»i" +sort_checkout_date_asc = "Ngà y thanh toán (ngà y cÅ© nhất)" +sort_checkout_date_desc = "Ngà y thanh toán (ngà y má»›i nhất)" +sort_count = "Số kết quả" +sort_due_date_asc = "Ngà y đến hạn (ngà y cÅ© nhất)" +sort_due_date_desc = "Ngà y đến hạn (ngà y má»›i nhất)" +sort_relevance = "Mức Ä‘á»™ liên quan" +sort_return_date_asc = "Ngà y trả vá» (ngà y cÅ© nhất)" +sort_return_date_desc = "Ngà y trả vá» (ngà y má»›i nhất)" +sort_title = "Tiêu Ä‘á»" +sort_year = "Ngà y giảm dần" +sort_year asc = "Ngà y tăng dần" +Source = "Nguồn" +Source Title = "Tiêu Ä‘á» nguồn" +spell_expand_alt = "Mở rá»™ng tìm kiếm" +spell_suggest = "Tìm kiếm thay thế" +Staff View = "Chế Ä‘á»™ xem nhân viên" +Start a new Advanced Search = "Bắt đầu Tìm kiếm nâng cao má»›i" +Start a new Basic Search = "Bắt đầu má»™t tìm kiếm cÆ¡ bản má»›i" +Start Page = "Trang bắt đầu" +starting from = "Bắt đầu từ" +Status = "Trạng thái" +status_unknown_message = "Trạng thái trá»±c tiếp không khả dụng" +Storage Retrieval Requests = "Yêu cầu truy xuất bá»™ nhá»›" +storage_retrieval_request_available = "Có sẵn cho tìm kiếm" +storage_retrieval_request_cancel = "Hủy yêu cầu truy xuất bá»™ nhá»›" +storage_retrieval_request_cancel_all = "Hủy tất cả yêu cầu truy xuất bá»™ nhá»›" +storage_retrieval_request_cancel_fail = "Yêu cầu của bạn không bị hủy. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +storage_retrieval_request_cancel_selected = "Hủy yêu cầu truy xuất bá»™ nhá»› đã chá»n" +storage_retrieval_request_cancel_success = "Yêu cầu của bạn đã được hủy thà nh công" +storage_retrieval_request_cancel_success_items = "%%count%% (các) yêu cầu đã được hủy thà nh công" +storage_retrieval_request_canceled = "Äã hủy" +storage_retrieval_request_check_text = "Kiểm tra yêu cầu truy xuất bá»™ nhá»›" +storage_retrieval_request_comments = "Bình luáºn" +storage_retrieval_request_date_invalid = "Vui lòng nháºp ngà y hợp lệ" +storage_retrieval_request_date_past = "Vui lòng nháºp ngà y trong tÆ°Æ¡ng lai" +storage_retrieval_request_empty_selection = "Không có yêu cầu truy xuất bá»™ nhá»› nà o được chá»n" +storage_retrieval_request_error_blocked = "Bạn không có đủ đặc quyá»n để đặt yêu cầu truy xuất bá»™ nhá»› trên mục nà y" +storage_retrieval_request_error_fail = "Yêu cầu của bạn không thà nh công. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +storage_retrieval_request_invalid_pickup = "Äã nháºp vị trà nháºn không hợp lệ. Vui lòng thá» lại" +storage_retrieval_request_issue = "Ngà y" +storage_retrieval_request_place_fail_missing = "Yêu cầu của bạn không thà nh công. Má»™t số dữ liệu bị thiếu. Vui lòng liên hệ vá»›i quầy lÆ°u hà nh để được trợ giúp thêm" +storage_retrieval_request_place_success = "Yêu cầu của bạn đã thà nh công" +storage_retrieval_request_place_success_html = "Yêu cầu của bạn đã thà nh công. <a href="%%url%%">Yêu cầu truy xuất bá»™ nhá»›</a>." +storage_retrieval_request_place_text = "Äặt yêu cầu truy xuất bá»™ nhá»›" +storage_retrieval_request_processed = "Xá» lý" +storage_retrieval_request_profile_html = "Äể biết thông tin yêu cầu truy xuất bá»™ nhá»›, vui lòng thiết láºp <a href="%%url%%">Hồ sÆ¡ danh mục thÆ° viện</a> của bạn." +storage_retrieval_request_reference = "Tà i liệu tham khảo" +storage_retrieval_request_selected_item = "Äã chá»n sách" +storage_retrieval_request_submit_text = "Yêu cầu địa Ä‘iểm" +storage_retrieval_request_volume = "Âm lượng" +storage_retrieval_request_year = "Năm" +Subcollection = "Bá»™ sÆ°u táºp phụ" +Subject = "Chủ Ä‘á»" +Subject Area = "Khu vá»±c chủ Ä‘á»" +Subject Geographic = "Chủ đỠđịa lý" +Subject Recommendations = "Äá» xuất chủ Ä‘á»" +Subject Terms = "Äiá»u khoản chủ Ä‘á»" +Subject(s) = "(Những) chủ Ä‘á»" +Subjects = "Những chủ Ä‘á»" +Submit = "Gá»i Ä‘i" +Submitting = "Äang gởi Ä‘i" +Suggested Topics = "Chủ đỠđược Ä‘á» xuất" +Summary = "Tóm tắt" +Summon Results = "Gá»i kết quả" +summon_database_recommendations = "Bạn có thể tìm thêm tà i nguyên tại đây:" +Supplements = "Bổ sung" +Supplied by Amazon = "Cung cấp bởi Amazon" +switch_view = "Chuyển chế Ä‘á»™ xem thà nh %%view%%" +switchquery_fuzzy = "Thá»±c hiện tìm kiếm má» có thể truy xuất các cụm từ có cách viết tÆ°Æ¡ng tá»±" +switchquery_intro = "Bạn có thể nháºn được nhiá»u kết quả hÆ¡n bằng cách Ä‘iá»u chỉnh truy vấn tìm kiếm của bạn." +switchquery_lowercasebools = "Nếu bạn Ä‘ang cố gắng sá» dụng toán tá» Boolean, chúng phải là ALL CAPS" +switchquery_truncatechar = "Hãy rút ngắn truy vấn tìm kiếm của bạn để mở rá»™ng kết quả của bạn" +switchquery_unwantedbools = "Các từ AND, OR và NOT có thể gây nhầm lẫn cho việc tìm kiếm; thá» thêm dấu ngoặc kép" +switchquery_unwantedquotes = "Xóa dấu ngoặc kép có thể cho phép tìm kiếm rá»™ng hÆ¡n" +switchquery_wildcard = "Thêm ký tá»± đại diện có thể truy xuất các biến thể từ" +System Unavailable = "Hệ thống không khả dụng" +Table of Contents = "Mục lục" +Table of Contents unavailable = "Mục lục không khả dụng" +Tag = "Nhãn" +Tag Management = "Quản lý thẻ" +tag_delete_filter = "Bạn Ä‘ang sá» dụng bá»™ lá»c sau - Tên ngÆ°á»i dùng: %username%, Nhãn: %tag%, Tà i nguyên: %resource%" +tag_delete_warning = "Cảnh báo! Bạn sắp xóa %count% (các) thẻ tà i nguyên" +tag_filter_empty = "Không có thẻ nà o cho bá»™ lá»c nà y" +Tags = "Các nhãn" +tags_deleted = "%count% (Các) nhãn đã xóa" +test_fail = "Äã thất bại" +test_fix = "Sá»a" +test_ok = "OK" +Text this = "Văn bản nà y" +Thank you for your feedback. = "Cảm Æ¡n phản hôi của baÌ£n." +That email address is already used = "Äịa chỉ email đó đã được sá» dụng" +That username is already taken = "Tên ngÆ°á»i dùng đó đã được sá» dụng" +The record you selected is not part of any of your lists. = "Bản ghi bạn đã chá»n không thuá»™c bất kỳ danh sách nà o của bạn." +The record you selected is not part of the selected list. = "Bản ghi bạn đã chá»n không thuá»™c danh sách được chá»n." +The system is currently unavailable due to system maintenance = "Hệ thống hiện không khả dụng do bảo trì hệ thống" +Theme = "Chủ Ä‘á»" +This email was sent from = "Email nà y đã được gá»i từ" +This field is required = "TrÆ°á»ng nà y là bắt buá»™c" +This item is already part of the following list/lists = "Sách nà y đã là má»™t phần của danh sách / các danh sách" +This result not is displayed to guests = "Kết quả nà y không được hiển thị cho khách." +Title = "Tiêu Ä‘á»" +Title not available = "Tiêu Ä‘á» không khả dụng" +Title View = "Chế Ä‘á»™ xem tiêu Ä‘á»" +title_hold_place = "Äặt yêu cầu cấp tiêu Ä‘á»" +To = "Tá»›i" +Too Many Email Recipients = "Quá nhiá»u ngÆ°á»i nháºn email" +too_many_favorites = "Danh sách nà y quá lá»›n để hiển thị tất cả cùng má»™t lúc. Thá» sắp xếp lại các mục yêu thÃch của bạn thà nh nhiá»u danh sách hÆ¡n hoặc hạn chế sá» dụng thẻ." +too_many_new_items = "Có quá nhiá»u sách má»›i để hiển thị trong má»™t danh sách duy nhất. Hãy thá» hạn chế tìm kiếm của bạn." +too_many_reserves = "Có quá nhiá»u dá»± trữ khóa há»c để hiển thị trong má»™t danh sách duy nhất. Hãy thá» hạn chế tìm kiếm của bạn." +top_facet_label = "%%label%% trong tìm kiếm của bạn." +Topic = "Äá» tà i" +Topics = "Nhiá»u Ä‘á» tà i" +Total Balance Due = "Tổng số dÆ° đến hạn" +total_comments = "Tổng số nháºn xét" +total_lists = "Tổng số danh sách" +total_resources = "Tổng số tà i nguyên" +total_saved_items = "Tổng số sách đã lÆ°u" +total_tags = "Tổng số thẻ" +total_users = "Tổng số ngÆ°á»i dùng" +Transliterated Title = "Tiêu đỠđược chuyển ngữ" +tree_search_limit_reached_html = "Tìm kiếm của bạn trả lại quá nhiá»u kết quả để hiển thị trong cây. Chỉ hiển thị đầu tiên <b>%%limit%%</b> quyển sách. Äối vá»›i tìm kiếm đầy đủ má»™t nhấp chuá»™t <a id="fullSearchLink" href="%%url%%" target="_blank">ở đây.</a>" +trending_items_channel_title = "Sách xu hÆ°á»›ng" +unique_tags = "Thẻ duy nhất" +University Library = "ThÆ° viện trÆ°á»ng đại há»c" +Unknown = "Không biết" +unrecognized_facet_label = "Khác" +Upgrade VuFind = "Nâng cấp Vufind" +upgrade_description = "Nếu bạn Ä‘ang nâng cấp phiên bản VuFind trÆ°á»›c đó, bạn có thể tải cà i đặt cÅ© của mình bằng công cụ nà y." +URL = "URL" +Use for = "Sá» dụng cho" +Use instead = "Sá» dụng thay thế" +User Account = "Tà i khoản ngÆ°á»i dùng" +Username = "Tên ngÆ°á»i dùng" +Username cannot be blank = "Tên ngÆ°á»i dùng không thể trống" +Username is already in use in another library card = "Tên ngÆ°á»i dùng đã được sá» dụng trong má»™t thẻ thÆ° viện khác" +VHS = "VHS" +Video = "Video" +Video Clips = "Video Clips" +Videos = "Videos" +View Book Bag = "Xem túi sách" +View Complete Issue = "Xem vấn Ä‘á» hoà n chỉnh" +View Full Collection = "Xem bá»™ sÆ°u táºp đầy đủ" +View Full Record = "Xem toà n bá»™ hồ sÆ¡" +View in EDS = "Xem trong EDS" +View online: Full view Book Preview from the Hathi Trust = "Xem trá»±c tuyến: Xem toà n bá»™ sách trÆ°á»›c đó từ Hathi Trust" +View Record = "Xem bản ghi" +View Records = "Xem nhiá»u bản ghi" +View this record in EBSCOhost = "Xem hồ sÆ¡ nà y trong EBSCOhost" +view_already_selected = "%%current%% chế Ä‘á»™ xem đã được chá»n" +visual_facet_parent = "Từ" +Volume = "Âm lượng" +Volume Holdings = "Giữ âm lượng" +VuFind Configuration = "Cấu hình VuFind" +vufind_upgrade_fail = "Chúng tôi không thể nâng cấp Vufind lúc nà y" +Warning: These citations may not always be 100% accurate = "Cảnh báo: Các trÃch dẫn nà y có thể không phải lúc nà o cÅ©ng chÃnh xác 100%" +wcterms_broader = "Äối tượng rá»™ng hÆ¡n" +wcterms_exact = "Äối tượng liên quan" +wcterms_narrower = "Äối tượng hẹp hÆ¡n" +Web = "Web" +What am I looking at = "Tôi Ä‘ang nhìn cái gì thế nà y?" +widen_prefix = "Thá» mở rá»™ng tìm kiếm của bạn thà nh" +wiki_link = "Äược cung cấp bởi Wikipedia" +with filters = "vá»›i bá»™ lá»c" +with_selected = "vá»›i đã chá»n" +Year of Publication = "Năm xuất bản" +Yesterday = "Hôm qua" +You do not have any fines = "Bạn không có tiá»n phạt nà o" +You do not have any holds or recalls placed = "Bạn không có bất kỳ lệnh giữ hoặc lệnh gá»i lại nà o được đặt" +You do not have any interlibrary loan requests placed = "Bạn không có bất kỳ yêu cầu mượn liên thÆ° viện nà o được đặt" +You do not have any items checked out = "Bạn không có bất kỳ sách nà o được kiểm tra" +You do not have any library cards = "Bạn không có thẻ thÆ° viện nà o" +You do not have any saved resources = "Bạn không có bất kỳ tà i nguyên nà o được lÆ°u. Thá»±c hiện tìm kiếm và sá» dụng nút Thêm và o Ưa thÃch để lÆ°u các quyển sách." +You do not have any storage retrieval requests placed = "Bạn không có bất kỳ yêu cầu truy xuất bá»™ nhá»› nà o được đặt" +You must be logged in first = "Bạn phải đăng nháºp trÆ°á»›c" +Your Account = "Tà i khoản của bạn" +Your book bag is empty = "Túi sách của bạn rá»—ng" +Your Checked Out Items = "Các quyển sách đã kiểm tra của bạn" +Your Comment = "Bình luáºn của bạn" +Your Favorites = "Các quyển sách đã lÆ°u" +Your Fines = "Tiá»n phạt của bạn" +Your Holds and Recalls = "Giữ và thu hồi của bạn" +Your Lists = "Danh sách của bạn" +Your Profile = "Hồ sÆ¡ của bạn" +Your search terms = "Cụm từ tìm kiếm của bạn" +Your Tags = "Thẻ của bạn" +your_match_would_be_here = "Tráºn đấu của bạn sẽ ở đây." +Zip = "Zip" +zoom = "Thu phóng" diff --git a/languages/zh-cn.ini b/languages/zh-cn.ini index dc9cdc022324ed3ecc6b42c0c6df2c5ff0cfe2a7..b3b0b7f8647a2c821f79b4f4a0bef5de92959ff5 100644 --- a/languages/zh-cn.ini +++ b/languages/zh-cn.ini @@ -240,6 +240,8 @@ fav_list_delete_cancel = "è¿™ä¸ªåˆ—è¡¨æ²¡è¢«åˆ é™¤" fav_list_delete_fail = "很抱æ‰ï¼Œå‘生错误. æ‚¨çš„åˆ—è¡¨æ²¡è¢«åˆ é™¤." Favorites = "最爱" Fee = "è´¹" +feedback_email = "电å邮件" +feedback_login_required = "您必须先登录" Find = "检索" Find More = "查找更多" Find New Items = "寻找新项目" diff --git a/languages/zh.ini b/languages/zh.ini index 8b8c43efb1ca9dc252ebf3682e6b846d3a09861d..ba6278e3e947943cc344ae46afd0b4d5c7dc0cd3 100644 --- a/languages/zh.ini +++ b/languages/zh.ini @@ -240,6 +240,8 @@ fav_list_delete_cancel = "這個列表沒被刪除" fav_list_delete_fail = "很抱æ‰ï¼Œç™¼ç”ŸéŒ¯èª¤. 您的列表沒被刪除." Favorites = "最愛" Fee = "è²»" +feedback_email = "é›»å郵件" +feedback_login_required = "æ‚¨å¿…é ˆå…ˆç™»éŒ„" Find = "檢索" Find More = "查找更多" Find New Items = "å°‹æ‰¾æ–°é …ç›®" diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index 40ea0d9483f61ea0041a48ab78809070e22cea97..de4b68990a08e58f2876c51371c6a644ed930d8b 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -342,8 +342,10 @@ $config = [ 'VuFind\Db\AdapterFactory' => 'VuFind\Service\ServiceWithConfigIniFactory', 'VuFind\Db\Row\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', 'VuFind\Db\Table\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', + 'VuFind\DoiLinker\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', 'VuFind\Export' => 'VuFind\ExportFactory', 'VuFind\Favorites\FavoritesService' => 'VuFind\Favorites\FavoritesServiceFactory', + 'VuFind\Form\Form' => 'VuFind\Form\FormFactory', 'VuFind\GeoFeatures\BasemapConfig' => 'VuFind\GeoFeatures\AbstractConfigFactory', 'VuFind\GeoFeatures\MapTabConfig' => 'VuFind\GeoFeatures\AbstractConfigFactory', 'VuFind\GeoFeatures\MapSelectionConfig' => 'VuFind\GeoFeatures\AbstractConfigFactory', @@ -362,6 +364,7 @@ $config = [ 'VuFind\QRCode\Loader' => 'VuFind\QRCode\LoaderFactory', 'VuFind\Recommend\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', 'VuFind\Record\Cache' => 'VuFind\Record\CacheFactory', + 'VuFind\Record\FallbackLoader\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', 'VuFind\Record\Loader' => 'VuFind\Record\LoaderFactory', 'VuFind\Record\Router' => 'VuFind\Record\RouterFactory', 'VuFind\RecordDriver\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory', @@ -514,12 +517,14 @@ $config = [ 'cover_layer' => [ /* see VuFind\Cover\Layer\PluginManager for defaults */ ], 'db_row' => [ /* see VuFind\Db\Row\PluginManager for defaults */ ], 'db_table' => [ /* see VuFind\Db\Table\PluginManager for defaults */ ], + 'doilinker' => [ /* see VuFind\DoiLinker\PluginManager for defaults */ ], 'hierarchy_driver' => [ /* see VuFind\Hierarchy\Driver\PluginManager for defaults */ ], 'hierarchy_treedataformatter' => [ /* see VuFind\Hierarchy\TreeDataFormatter\PluginManager for defaults */ ], 'hierarchy_treedatasource' => [ /* see VuFind\Hierarchy\TreeDataSource\PluginManager for defaults */ ], 'hierarchy_treerenderer' => [ /* see VuFind\Hierarchy\TreeRenderer\PluginManager for defaults */ ], 'ils_driver' => [ /* See VuFind\ILS\Driver\PluginManager for defaults */ ], 'recommend' => [ /* See VuFind\Recommend\PluginManager for defaults */ ], + 'record_fallbackloader' => [ /* See VuFind\Record\FallbackLoader\PluginManager for defaults */ ], 'recorddriver' => [ /* See VuFind\RecordDriver\PluginManager for defaults */ ], 'recordtab' => [ /* See VuFind\RecordTab\PluginManager for defaults */ ], 'related' => [ /* See VuFind\Related\PluginManager for defaults */ ], @@ -673,6 +678,7 @@ $recordRoutes = [ // Define dynamic routes -- controller => [route name => action] $dynamicRoutes = [ + 'Feedback' => ['feedback-form' => 'Form/[:id]'], 'MyResearch' => ['userList' => 'MyList/[:id]', 'editList' => 'EditList/[:id]'], 'LibraryCards' => ['editLibraryCard' => 'editCard/[:id]'], ]; diff --git a/module/VuFind/sql/migrations/pgsql/5.1/001-modify-resource-columns.sql b/module/VuFind/sql/migrations/pgsql/5.1/001-modify-resource-columns.sql new file mode 100644 index 0000000000000000000000000000000000000000..8ef7bb71a5b4eb6dddb5ec6340af1aec4ae33c74 --- /dev/null +++ b/module/VuFind/sql/migrations/pgsql/5.1/001-modify-resource-columns.sql @@ -0,0 +1,6 @@ +-- +-- Modifications to table `resource` +-- + +ALTER TABLE "resource" + ADD COLUMN extra_metadata text DEFAULT NULL; diff --git a/module/VuFind/sql/migrations/pgsql/5.1/002-modify-user-columns.sql b/module/VuFind/sql/migrations/pgsql/5.1/002-modify-user-columns.sql new file mode 100644 index 0000000000000000000000000000000000000000..553306cecb816747f246fea921fa65187d2c7d31 --- /dev/null +++ b/module/VuFind/sql/migrations/pgsql/5.1/002-modify-user-columns.sql @@ -0,0 +1,10 @@ +-- +-- Modifications to table `user` +-- + +ALTER TABLE "user" + ALTER COLUMN cat_pass_enc TYPE varchar(255); + +ALTER TABLE "user_card" + ALTER COLUMN cat_password TYPE varchar(70), + ALTER COLUMN cat_pass_enc TYPE varchar(255); diff --git a/module/VuFind/sql/mysql.sql b/module/VuFind/sql/mysql.sql index 57593a89c161a3c8797f8bb440aed1d856365ae8..8d46fbeacf60880b359525c2c309ba9eddf02f0c 100644 --- a/module/VuFind/sql/mysql.sql +++ b/module/VuFind/sql/mysql.sql @@ -74,6 +74,7 @@ CREATE TABLE `resource` ( `author` varchar(255) DEFAULT NULL, `year` mediumint(6) DEFAULT NULL, `source` varchar(50) NOT NULL DEFAULT 'Solr', + `extra_metadata` mediumtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `record_id` (`record_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -192,7 +193,7 @@ CREATE TABLE `user` ( `cat_id` varchar(255) DEFAULT NULL, `cat_username` varchar(50) DEFAULT NULL, `cat_password` varchar(70) DEFAULT NULL, - `cat_pass_enc` varchar(170) DEFAULT NULL, + `cat_pass_enc` varchar(255) DEFAULT NULL, `college` varchar(100) NOT NULL DEFAULT '', `major` varchar(100) NOT NULL DEFAULT '', `home_library` varchar(100) NOT NULL DEFAULT '', @@ -259,8 +260,8 @@ CREATE TABLE `user_card` ( `user_id` int(11) NOT NULL, `card_name` varchar(255) NOT NULL DEFAULT '', `cat_username` varchar(50) NOT NULL DEFAULT '', - `cat_password` varchar(50) DEFAULT NULL, - `cat_pass_enc` varchar(110) DEFAULT NULL, + `cat_password` varchar(70) DEFAULT NULL, + `cat_pass_enc` varchar(255) DEFAULT NULL, `home_library` varchar(100) NOT NULL DEFAULT '', `created` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', `saved` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, diff --git a/module/VuFind/sql/pgsql.sql b/module/VuFind/sql/pgsql.sql index 76d41610e8dafd9c6a00ab16532f479ded9f9de5..c92723756a2925261c632607db7af0f1fa4a332b 100644 --- a/module/VuFind/sql/pgsql.sql +++ b/module/VuFind/sql/pgsql.sql @@ -31,6 +31,7 @@ title varchar(255) NOT NULL DEFAULT '', author varchar(255) DEFAULT NULL, year int DEFAULT NULL, source varchar(50) NOT NULL DEFAULT 'Solr', +extra_metadata text DEFAULT NULL, PRIMARY KEY (id) ); CREATE INDEX resource_record_id_idx ON resource (record_id); diff --git a/module/VuFind/src/VuFind/AjaxHandler/AbstractIlsAndUserActionFactory.php b/module/VuFind/src/VuFind/AjaxHandler/AbstractIlsAndUserActionFactory.php index 15fe7d0cb361c9bf64fd0bee8d932ffa69a32a9b..19b2b2c6c3a3fc7650d6baf6c34497edc74142e8 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/AbstractIlsAndUserActionFactory.php +++ b/module/VuFind/src/VuFind/AjaxHandler/AbstractIlsAndUserActionFactory.php @@ -60,14 +60,12 @@ class AbstractIlsAndUserActionFactory public function __invoke(ContainerInterface $container, $requestedName, array $options = null ) { - if (!empty($options)) { - throw new \Exception('Unexpected options passed to factory.'); - } return new $requestedName( $container->get('VuFind\Session\Settings'), $container->get('VuFind\ILS\Connection'), $container->get('VuFind\Auth\ILSAuthenticator'), - $container->get('VuFind\Auth\Manager')->isLoggedIn() + $container->get('VuFind\Auth\Manager')->isLoggedIn(), + ...($options ?: []) ); } } diff --git a/module/VuFind/src/VuFind/AjaxHandler/AbstractUserRequestAction.php b/module/VuFind/src/VuFind/AjaxHandler/AbstractUserRequestAction.php new file mode 100644 index 0000000000000000000000000000000000000000..8928f5bef48d813d705c9fe51276c32f133ac0ec --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/AbstractUserRequestAction.php @@ -0,0 +1,82 @@ +<?php +/** + * Abstract base class for fetching information about user requests. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use Zend\Mvc\Controller\Plugin\Params; + +/** + * Abstract base class for fetching information about user requests. + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +abstract class AbstractUserRequestAction extends AbstractIlsAndUserAction +{ + /** + * ILS driver method for data retrieval. + * + * @var string + */ + protected $lookupMethod; // must be set in subclass + + /** + * Handle a request. + * + * @param Params $params Parameter helper from controller + * + * @return array [response data, internal status code, HTTP status code] + */ + public function handleRequest(Params $params) + { + $this->disableSessionWrites(); // avoid session write timing bug + $patron = $this->ilsAuthenticator->storedCatalogLogin(); + if (!$patron) { + return $this->formatResponse('', self::STATUS_NEED_AUTH, 401); + } + if (!$this->ils->checkCapability($this->lookupMethod)) { + return $this->formatResponse('', self::STATUS_ERROR, 405); + } + $requests = $this->ils->{$this->lookupMethod}($patron); + $status = [ + 'available' => 0, + 'in_transit' => 0 + ]; + foreach ($requests as $request) { + if ($request['available'] ?? false) { + $status['available'] += 1; + } + if ($request['in_transit'] ?? false) { + $status['in_transit'] += 1; + } + } + return $this->formatResponse($status); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/DoiLookup.php b/module/VuFind/src/VuFind/AjaxHandler/DoiLookup.php new file mode 100644 index 0000000000000000000000000000000000000000..deb055ba809529152658c3fcce3df421663455b3 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/DoiLookup.php @@ -0,0 +1,86 @@ +<?php +/** + * AJAX handler to look up DOI data. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use VuFind\DoiLinker\PluginManager; +use Zend\Mvc\Controller\Plugin\Params; + +/** + * AJAX handler to look up DOI data. + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class DoiLookup extends AbstractBase +{ + /** + * DOI Linker Plugin Manager + * + * @var PluginManager + */ + protected $pluginManager; + + /** + * DOI resolver configuration value + * + * @var string + */ + protected $resolver; + + /** + * Constructor + * + * @param PluginManager $pluginManager DOI Linker Plugin Manager + * @param string $resolver DOI resolver configuration value + */ + public function __construct(PluginManager $pluginManager, $resolver) + { + $this->pluginManager = $pluginManager; + $this->resolver = $resolver; + } + + /** + * Handle a request. + * + * @param Params $params Parameter helper from controller + * + * @return array [response data, HTTP status code] + */ + public function handleRequest(Params $params) + { + $response = []; + if ($this->pluginManager->has($this->resolver)) { + $dois = (array)$params->fromQuery('doi', []); + $response = $this->pluginManager->get($this->resolver)->getLinks($dois); + } + return $this->formatResponse($response); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/DoiLookupFactory.php b/module/VuFind/src/VuFind/AjaxHandler/DoiLookupFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..fb41749f91e84acb254463b29a21f84b861489e4 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/DoiLookupFactory.php @@ -0,0 +1,69 @@ +<?php +/** + * Factory for DoiLookup AJAX handler. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use Interop\Container\ContainerInterface; + +/** + * Factory for DoiLookup AJAX handler. + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class DoiLookupFactory implements \Zend\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $config = $container->get('VuFind\Config\PluginManager')->get('config'); + $pluginManager = $container->get('VuFind\DoiLinker\PluginManager'); + return new $requestedName($pluginManager, $config->DOI->resolver ?? null); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetResolverLinks.php b/module/VuFind/src/VuFind/AjaxHandler/GetResolverLinks.php index 16483c1aa03c7db72ddde29ef1ad0b1abf6540dc..8e24b129313e10b0145b9c37008566c8815dcc8f 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/GetResolverLinks.php +++ b/module/VuFind/src/VuFind/AjaxHandler/GetResolverLinks.php @@ -105,7 +105,7 @@ class GetResolverLinks extends AbstractBase implements TranslatorAwareInterface $searchClassId = $params->fromQuery('searchClassId', ''); $resolverType = isset($this->config->OpenURL->resolver) - ? $this->config->OpenURL->resolver : 'other'; + ? $this->config->OpenURL->resolver : 'generic'; if (!$this->pluginManager->has($resolverType)) { return $this->formatResponse( $this->translate("Could not load driver for $resolverType"), diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetSideFacets.php b/module/VuFind/src/VuFind/AjaxHandler/GetSideFacets.php new file mode 100644 index 0000000000000000000000000000000000000000..b8568d7a5a39e1cdbb3c20c1f9c42a07a28f519b --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetSideFacets.php @@ -0,0 +1,302 @@ +<?php +/** + * "Get Side Facets" AJAX handler + * + * PHP version 7 + * + * Copyright (C) The National Library of Finland 2018-2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use VuFind\Recommend\PluginManager as RecommendPluginManager; +use VuFind\Recommend\SideFacets; +use VuFind\Search\Base\Results; +use VuFind\Search\RecommendListener; +use VuFind\Search\SearchRunner; +use VuFind\Search\Solr\HierarchicalFacetHelper; +use VuFind\Search\UrlQueryHelper; +use VuFind\Session\Settings as SessionSettings; +use Zend\Mvc\Controller\Plugin\Params; +use Zend\View\Renderer\RendererInterface; + +/** + * "Get Side Facets" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetSideFacets extends \VuFind\AjaxHandler\AbstractBase + implements \Zend\Log\LoggerAwareInterface +{ + use \VuFind\Log\LoggerAwareTrait; + + /** + * Recommend plugin manager + * + * @var RecommendPluginManager + */ + protected $recommendPluginManager; + + /** + * Search runner + * + * @var SearchRunner + */ + protected $searchRunner; + + /** + * Hierarchical facet helper + * + * @var HierarchicalFacetHelper + */ + protected $facetHelper; + + /** + * Main facet configuration + * + * @var \VuFind\Config\PluginManager + */ + protected $facetConfig; + + /** + * View renderer + * + * @var RendererInterface + */ + protected $renderer; + + /** + * Constructor + * + * @param SessionSettings $ss Session settings + * @param RecommendPluginManager $rpm Recommend plugin manager + * @param SearchRunner $sr Search runner + * @param HierarchicalFacetHelper $fh Facet helper + * @param \Zend\Config\Config $fc Facet config + * @param RendererInterface $renderer View renderer + */ + public function __construct(SessionSettings $ss, + \VuFind\Recommend\PluginManager $rpm, + SearchRunner $sr, HierarchicalFacetHelper $fh, + \Zend\Config\Config $fc, RendererInterface $renderer + ) { + $this->sessionSettings = $ss; + $this->recommendPluginManager = $rpm; + $this->searchRunner = $sr; + $this->facetHelper = $fh; + $this->facetConfig = $fc; + $this->renderer = $renderer; + } + + /** + * Handle a request. + * + * @param Params $params Parameter helper from controller + * + * @return array [response data, HTTP status code] + */ + public function handleRequest(Params $params) + { + $this->disableSessionWrites(); // avoid session write timing bug + + // Allow both GET and POST variables: + $request = $params->fromQuery() + $params->fromPost(); + + $configIndex = $request['configIndex'] ?? 0; + $configLocation = $request['location'] ?? 'side'; + $results = $this->getFacetResults($request, $configIndex, $configLocation); + if ($results instanceof \VuFind\Search\EmptySet\Results) { + $this->logError('Faceting request failed'); + return $this->formatResponse('', self::STATUS_HTTP_ERROR); + } + + $recommend = $results->getRecommendations($configLocation)[0]; + + $context = [ + 'recommend' => $recommend, + 'params' => $results->getParams(), + 'searchClassId' => $request['searchClassId'] ?? DEFAULT_SEARCH_BACKEND + ]; + if (isset($request['enabledFacets'])) { + // Render requested facets separately + $facets = $this->formatFacets( + $context, $recommend, $request['enabledFacets'], $results + ); + return $this->formatResponse(compact('facets')); + } + + // Render full sidefacets + $html = $this->renderer->render( + 'Recommend/SideFacets.phtml', + $context + ); + return $this->formatResponse(compact('html')); + } + + /** + * Perform search and return the results + * + * @param array $request Request params + * @param string $index Index of SideFacetsDeferred in configuration + * @param string $loc Location where SideFacetsDeferred is configured + * + * @return Results + */ + protected function getFacetResults(array $request, $index, $loc) + { + $setupCallback = function ($runner, $params, $searchId) use ($index, $loc) { + $listener = new RecommendListener( + $this->recommendPluginManager, $searchId + ); + $config = []; + $rawConfig = $params->getOptions() + ->getRecommendationSettings($params->getSearchHandler()); + $settings = explode(':', $rawConfig[$loc][$index] ?? ''); + if ($settings[0] === 'SideFacetsDeferred') { + $settings[0] = 'SideFacets'; + $config[$loc][] = implode(':', $settings); + } + $listener->setConfig($config); + $listener->attach($runner->getEventManager()->getSharedManager()); + + $params->setLimit(0); + if (is_callable([$params, 'setHierarchicalFacetLimit'])) { + $params->setHierarchicalFacetLimit(-1); + } + $options = $params->getOptions(); + $options->disableHighlighting(); + $options->spellcheckEnabled(false); + }; + + $runner = $this->searchRunner; + return $runner->run( + $request, + $request['searchClassId'] ?? DEFAULT_SEARCH_BACKEND, + $setupCallback + ); + } + + /** + * Format facets according to their type + * + * @param array $context View rendering context + * @param SideFacets $recommend Recommendation module + * @param array $facets Facets to process + * @param Results $results Search results + * + * @return array + */ + protected function formatFacets($context, SideFacets $recommend, $facets, + Results $results + ) { + $response = []; + $hierarchicalFacets = []; + $options = $results->getOptions(); + if (is_callable([$options, 'getHierarchicalFacets'])) { + $hierarchicalFacets = $options->getHierarchicalFacets(); + $hierarchicalFacetSortOptions + = $recommend->getHierarchicalFacetSortOptions(); + } + $facetSet = $recommend->getFacetSet(); + $urlHelper = $results->getUrlQuery(); + foreach ($facets as $facet) { + if (strpos($facet, ':')) { + $response[$facet]['checkboxCount'] + = $this->getCheckboxFacetCount($facet, $results); + } elseif (in_array($facet, $hierarchicalFacets)) { + $response[$facet]['list'] = $this->getHierarchicalFacetData( + $facet, + $hierarchicalFacetSortOptions, + $facetSet[$facet]['list'] ?? [], + $urlHelper + ); + } else { + $context['facet'] = $facet; + $context['cluster'] = $facetSet[$facet] ?? []; + $response[$facet]['html'] = $this->renderer->render( + 'Recommend/SideFacets/facet.phtml', + $context + ); + } + } + return $response; + } + + /** + * Get the result count for a checkbox facet + * + * @param string $facet Facet + * @param Results $results Search results + * + * @return int|null + */ + protected function getCheckboxFacetCount($facet, Results $results) + { + // There's currently no good way to return counts for checkbox filters. + return null; + } + + /** + * Get facet data for a hierarchical facet + * + * @param string $facet Facet + * @param array $sortOptions Hierarhical facet sort options + * @param array $facetList Facet list + * @param UrlQueryHelper $urlHelper UrlQueryHelper for creating facet URLs + * + * @return array + */ + protected function getHierarchicalFacetData($facet, $sortOptions, $facetList, + UrlQueryHelper $urlHelper + ) { + if (!empty($sortOptions[$facet])) { + $this->facetHelper->sortFacetList( + $facetList, + 'top' === $sortOptions[$facet] + ); + } + + $result = $this->facetHelper->buildFacetArray( + $facet, $facetList, $urlHelper, false + ); + + if (!empty($this->facetConfig->FacetFilters->$facet) + || !empty($this->facetConfig->ExcludeFilters->$facet) + ) { + $filters = !empty($this->facetConfig->FacetFilters->$facet) + ? $this->facetConfig->FacetFilters->$facet->toArray() : []; + $excludeFilters = !empty($this->facetConfig->ExcludeFilters->$facet) + ? $this->facetConfig->ExcludeFilters->$facet->toArray() : []; + + $result = $this->facetHelper->filterFacets( + $result, + $filters, + $excludeFilters + ); + } + + return $result; + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetSideFacetsFactory.php b/module/VuFind/src/VuFind/AjaxHandler/GetSideFacetsFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..9ea6a726bd58d091f57336b643f5b481fbab269a --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetSideFacetsFactory.php @@ -0,0 +1,75 @@ +<?php +/** + * Factory for GetSideFacets AJAX handler. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use Interop\Container\ContainerInterface; + +/** + * Factory for GetSideFacets AJAX handler. + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetSideFacetsFactory implements \Zend\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $result = new $requestedName( + $container->get('VuFind\Session\Settings'), + $container->get('VuFind\Recommend\PluginManager'), + $container->get('VuFind\SearchRunner'), + $container->get('VuFind\Search\Solr\HierarchicalFacetHelper'), + $container->get('VuFind\Config\PluginManager')->get('facets'), + $container->get('ViewRenderer') + ); + return $result; + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserFines.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserFines.php new file mode 100644 index 0000000000000000000000000000000000000000..37af9326d0debb75818c550bae2f32861c5957d0 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserFines.php @@ -0,0 +1,89 @@ +<?php +/** + * "Get User Fines" AJAX handler + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use VuFind\Auth\ILSAuthenticator; +use VuFind\Db\Row\User; +use VuFind\ILS\Connection; +use VuFind\Session\Settings as SessionSettings; +use VuFind\View\Helper\Root\SafeMoneyFormat; +use Zend\Mvc\Controller\Plugin\Params; + +/** + * "Get User Fines" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserFines extends AbstractIlsAndUserAction +{ + /** + * Constructor + * + * @param SessionSettings $ss Session settings + * @param Connection $ils ILS connection + * @param ILSAuthenticator $ilsAuthenticator ILS authenticator + * @param User|bool $user Logged in user (or false) + * @param SafeMoneyFormat $safeMoneyFormat Money formatting view helper + */ + public function __construct(SessionSettings $ss, Connection $ils, + ILSAuthenticator $ilsAuthenticator, $user, SafeMoneyFormat $safeMoneyFormat + ) { + parent::__construct($ss, $ils, $ilsAuthenticator, $user); + $this->safeMoneyFormat = $safeMoneyFormat; + } + + /** + * Handle a request. + * + * @param Params $params Parameter helper from controller + * + * @return array [response data, internal status code, HTTP status code] + */ + public function handleRequest(Params $params) + { + $this->disableSessionWrites(); // avoid session write timing bug + $patron = $this->ilsAuthenticator->storedCatalogLogin(); + if (!$patron) { + return $this->formatResponse('', self::STATUS_NEED_AUTH, 401); + } + if (!$this->ils->checkCapability('getMyFines')) { + return $this->formatResponse('', self::STATUS_ERROR, 405); + } + $sum = 0; + foreach ($this->ils->getMyFines($patron) as $fine) { + $sum += $fine['balance']; + } + $value = $sum / 100; + $display = $this->safeMoneyFormat->__invoke($sum / 100); + return $this->formatResponse(compact('value', 'display')); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserFinesFactory.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserFinesFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..de13fa22efe0feda3e5313ac38ab698793fddf8a --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserFinesFactory.php @@ -0,0 +1,69 @@ +<?php +/** + * Factory for GetUserFines AJAX handler. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use Interop\Container\ContainerInterface; + +/** + * Factory for GetUserFines AJAX handler. + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserFinesFactory extends AbstractIlsAndUserActionFactory + implements \Zend\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $helper = $container->get('ViewHelperManager')->get('safeMoneyFormat'); + return parent::__invoke($container, $requestedName, [$helper]); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserHolds.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserHolds.php new file mode 100644 index 0000000000000000000000000000000000000000..3ae377e8f04e2f897b9070599fdd5743a5997eea --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserHolds.php @@ -0,0 +1,47 @@ +<?php +/** + * "Get User Holds" AJAX handler + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +/** + * "Get User Holds" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserHolds extends AbstractUserRequestAction +{ + /** + * ILS driver method for data retrieval. + * + * @var string + */ + protected $lookupMethod = 'getMyHolds'; +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserILLRequests.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserILLRequests.php new file mode 100644 index 0000000000000000000000000000000000000000..bec831eddbf68f612409b90ded548b7bad631661 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserILLRequests.php @@ -0,0 +1,47 @@ +<?php +/** + * "Get User ILL Requests" AJAX handler + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +/** + * "Get User ILL Requests" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserILLRequests extends AbstractUserRequestAction +{ + /** + * ILS driver method for data retrieval. + * + * @var string + */ + protected $lookupMethod = 'getMyILLRequests'; +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserStorageRetrievalRequests.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserStorageRetrievalRequests.php new file mode 100644 index 0000000000000000000000000000000000000000..52b39390853e50f7a5a4ce49fdce406ad7d44d50 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserStorageRetrievalRequests.php @@ -0,0 +1,47 @@ +<?php +/** + * "Get User Storage Retrieval Requests" AJAX handler + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +/** + * "Get User Storage Retrieval Requests" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserStorageRetrievalRequests extends AbstractUserRequestAction +{ + /** + * ILS driver method for data retrieval. + * + * @var string + */ + protected $lookupMethod = 'getMyStorageRetrievalRequests'; +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetUserTransactions.php b/module/VuFind/src/VuFind/AjaxHandler/GetUserTransactions.php new file mode 100644 index 0000000000000000000000000000000000000000..94ceb988c943a3aa90610cf7d82e514d0a078985 --- /dev/null +++ b/module/VuFind/src/VuFind/AjaxHandler/GetUserTransactions.php @@ -0,0 +1,80 @@ +<?php +/** + * "Get User Transactions" AJAX handler + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\AjaxHandler; + +use Zend\Mvc\Controller\Plugin\Params; + +/** + * "Get User Transactions" AJAX handler + * + * @category VuFind + * @package AJAX + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class GetUserTransactions extends AbstractIlsAndUserAction +{ + /** + * Handle a request. + * + * @param Params $params Parameter helper from controller + * + * @return array [response data, internal status code, HTTP status code] + */ + public function handleRequest(Params $params) + { + $this->disableSessionWrites(); // avoid session write timing bug + $patron = $this->ilsAuthenticator->storedCatalogLogin(); + if (!$patron) { + return $this->formatResponse('', self::STATUS_NEED_AUTH, 401); + } + if (!$this->ils->checkCapability('getMyTransactions')) { + return $this->formatResponse('', self::STATUS_ERROR, 405); + } + $items = $this->ils->getMyTransactions($patron); + $counts = [ + 'ok' => 0, + 'warn' => 0, + 'overdue' => 0 + ]; + foreach ($items['records'] as $item) { + if (!isset($item['dueStatus'])) { + continue; + } + if ($item['dueStatus'] == 'overdue') { + $counts['overdue'] += 1; + } elseif ($item['dueStatus'] == 'due') { + $counts['warn'] += 1; + } else { + $counts['ok'] += 1; + } + } + return $this->formatResponse($counts); + } +} diff --git a/module/VuFind/src/VuFind/AjaxHandler/PluginManager.php b/module/VuFind/src/VuFind/AjaxHandler/PluginManager.php index 5f0e3295b8e5fcc9dd97d4174566ce1b72947541..0f1ea45bd9284f7dd34646e351f40deda97748e4 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/PluginManager.php +++ b/module/VuFind/src/VuFind/AjaxHandler/PluginManager.php @@ -44,30 +44,35 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager * @var array */ protected $aliases = [ - 'checkRequestIsValid' => 'VuFind\AjaxHandler\CheckRequestIsValid', - 'commentRecord' => 'VuFind\AjaxHandler\CommentRecord', - 'deleteRecordComment' => 'VuFind\AjaxHandler\DeleteRecordComment', - 'getACSuggestions' => 'VuFind\AjaxHandler\GetACSuggestions', - 'getFacetData' => 'VuFind\AjaxHandler\GetFacetData', - 'getIlsStatus' => 'VuFind\AjaxHandler\GetIlsStatus', - 'getItemStatuses' => 'VuFind\AjaxHandler\GetItemStatuses', - 'getLibraryPickupLocations' => - 'VuFind\AjaxHandler\GetLibraryPickupLocations', - 'getRecordCommentsAsHTML' => 'VuFind\AjaxHandler\GetRecordCommentsAsHTML', - 'getRecordDetails' => 'VuFind\AjaxHandler\GetRecordDetails', - 'getRecordTags' => 'VuFind\AjaxHandler\GetRecordTags', - 'getRequestGroupPickupLocations' => - 'VuFind\AjaxHandler\GetRequestGroupPickupLocations', - 'getResolverLinks' => 'VuFind\AjaxHandler\GetResolverLinks', - 'getSaveStatuses' => 'VuFind\AjaxHandler\GetSaveStatuses', - 'getVisData' => 'VuFind\AjaxHandler\GetVisData', - 'keepAlive' => 'VuFind\AjaxHandler\KeepAlive', - 'recommend' => 'VuFind\AjaxHandler\Recommend', - 'relaisAvailability' => 'VuFind\AjaxHandler\RelaisAvailability', - 'relaisInfo' => 'VuFind\AjaxHandler\RelaisInfo', - 'relaisOrder' => 'VuFind\AjaxHandler\RelaisOrder', - 'systemStatus' => 'VuFind\AjaxHandler\SystemStatus', - 'tagRecord' => 'VuFind\AjaxHandler\TagRecord', + 'checkRequestIsValid' => CheckRequestIsValid::class, + 'commentRecord' => CommentRecord::class, + 'deleteRecordComment' => DeleteRecordComment::class, + 'doiLookup' => DoiLookup::class, + 'getACSuggestions' => GetACSuggestions::class, + 'getFacetData' => GetFacetData::class, + 'getIlsStatus' => GetIlsStatus::class, + 'getItemStatuses' => GetItemStatuses::class, + 'getLibraryPickupLocations' => GetLibraryPickupLocations::class, + 'getRecordCommentsAsHTML' => GetRecordCommentsAsHTML::class, + 'getRecordDetails' => GetRecordDetails::class, + 'getRecordTags' => GetRecordTags::class, + 'getRequestGroupPickupLocations' => GetRequestGroupPickupLocations::class, + 'getResolverLinks' => GetResolverLinks::class, + 'getSaveStatuses' => GetSaveStatuses::class, + 'getSideFacets' => GetSideFacets::class, + 'getUserFines' => GetUserFines::class, + 'getUserHolds' => GetUserHolds::class, + 'getUserILLRequests' => GetUserILLRequests::class, + 'getUserStorageRetrievalRequests' => GetUserStorageRetrievalRequests::class, + 'getUserTransactions' => GetUserTransactions::class, + 'getVisData' => GetVisData::class, + 'keepAlive' => KeepAlive::class, + 'recommend' => Recommend::class, + 'relaisAvailability' => RelaisAvailability::class, + 'relaisInfo' => RelaisInfo::class, + 'relaisOrder' => RelaisOrder::class, + 'systemStatus' => SystemStatus::class, + 'tagRecord' => TagRecord::class, ]; /** @@ -76,46 +81,37 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager * @var array */ protected $factories = [ - 'VuFind\AjaxHandler\CheckRequestIsValid' => - 'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory', - 'VuFind\AjaxHandler\CommentRecord' => - 'VuFind\AjaxHandler\CommentRecordFactory', - 'VuFind\AjaxHandler\DeleteRecordComment' => - 'VuFind\AjaxHandler\DeleteRecordCommentFactory', - 'VuFind\AjaxHandler\GetACSuggestions' => - 'VuFind\AjaxHandler\GetACSuggestionsFactory', - 'VuFind\AjaxHandler\GetFacetData' => - 'VuFind\AjaxHandler\GetFacetDataFactory', - 'VuFind\AjaxHandler\GetIlsStatus' => - 'VuFind\AjaxHandler\GetIlsStatusFactory', - 'VuFind\AjaxHandler\GetItemStatuses' => - 'VuFind\AjaxHandler\GetItemStatusesFactory', - 'VuFind\AjaxHandler\GetLibraryPickupLocations' => - 'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory', - 'VuFind\AjaxHandler\GetRecordCommentsAsHTML' => - 'VuFind\AjaxHandler\GetRecordCommentsAsHTMLFactory', - 'VuFind\AjaxHandler\GetRecordDetails' => - 'VuFind\AjaxHandler\GetRecordDetailsFactory', - 'VuFind\AjaxHandler\GetRecordTags' => - 'VuFind\AjaxHandler\GetRecordTagsFactory', - 'VuFind\AjaxHandler\GetRequestGroupPickupLocations' => - 'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory', - 'VuFind\AjaxHandler\GetResolverLinks' => - 'VuFind\AjaxHandler\GetResolverLinksFactory', - 'VuFind\AjaxHandler\GetSaveStatuses' => - 'VuFind\AjaxHandler\GetSaveStatusesFactory', - 'VuFind\AjaxHandler\GetVisData' => 'VuFind\AjaxHandler\GetVisDataFactory', - 'VuFind\AjaxHandler\KeepAlive' => 'VuFind\AjaxHandler\KeepAliveFactory', - 'VuFind\AjaxHandler\Recommend' => 'VuFind\AjaxHandler\RecommendFactory', - 'VuFind\AjaxHandler\RelaisAvailability' => - 'VuFind\AjaxHandler\AbstractRelaisActionFactory', - 'VuFind\AjaxHandler\RelaisInfo' => - 'VuFind\AjaxHandler\AbstractRelaisActionFactory', - 'VuFind\AjaxHandler\RelaisOrder' => - 'VuFind\AjaxHandler\AbstractRelaisActionFactory', - 'VuFind\AjaxHandler\SystemStatus' => - 'VuFind\AjaxHandler\SystemStatusFactory', - 'VuFind\AjaxHandler\TagRecord' => 'VuFind\AjaxHandler\TagRecordFactory', + CheckRequestIsValid::class => AbstractIlsAndUserActionFactory::class, + CommentRecord::class => CommentRecordFactory::class, + DeleteRecordComment::class => DeleteRecordCommentFactory::class, + DoiLookup::class => DoiLookupFactory::class, + GetACSuggestions::class => GetACSuggestionsFactory::class, + GetFacetData::class => GetFacetDataFactory::class, + GetIlsStatus::class => GetIlsStatusFactory::class, + GetItemStatuses::class => GetItemStatusesFactory::class, + GetLibraryPickupLocations::class => AbstractIlsAndUserActionFactory::class, + GetRecordCommentsAsHTML::class => GetRecordCommentsAsHTMLFactory::class, + GetRecordDetails::class => GetRecordDetailsFactory::class, + GetRecordTags::class => GetRecordTagsFactory::class, + GetRequestGroupPickupLocations::class => + AbstractIlsAndUserActionFactory::class, + GetResolverLinks::class => GetResolverLinksFactory::class, + GetSaveStatuses::class => GetSaveStatusesFactory::class, + GetSideFacets::class => GetSideFacetsFactory::class, + GetUserFines::class => GetUserFinesFactory::class, + GetUserHolds::class => AbstractIlsAndUserActionFactory::class, + GetUserILLRequests::class => AbstractIlsAndUserActionFactory::class, + GetUserStorageRetrievalRequests::class => + AbstractIlsAndUserActionFactory::class, + GetUserTransactions::class => AbstractIlsAndUserActionFactory::class, + GetVisData::class => GetVisDataFactory::class, + KeepAlive::class => KeepAliveFactory::class, + Recommend::class => RecommendFactory::class, + RelaisAvailability::class => AbstractRelaisActionFactory::class, + RelaisInfo::class => AbstractRelaisActionFactory::class, + RelaisOrder::class => AbstractRelaisActionFactory::class, + SystemStatus::class => SystemStatusFactory::class, + TagRecord::class => TagRecordFactory::class, ]; /** @@ -126,6 +122,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager */ protected function getExpectedInterface() { - return 'VuFind\AjaxHandler\AjaxHandlerInterface'; + return AjaxHandlerInterface::class; } } diff --git a/module/VuFind/src/VuFind/Auth/Database.php b/module/VuFind/src/VuFind/Auth/Database.php index 68882265812c239517c157b58f628d1ccd1639b9..307802c0d6f7f7ddcb8faab9f9b54ad918e611ab 100644 --- a/module/VuFind/src/VuFind/Auth/Database.php +++ b/module/VuFind/src/VuFind/Auth/Database.php @@ -376,5 +376,3 @@ class Database extends AbstractBase return $user; } } -?> - diff --git a/module/VuFind/src/VuFind/Auth/Manager.php b/module/VuFind/src/VuFind/Auth/Manager.php index 67f64d0090ffc2cc40b0bc40d9f50b5745016c58..131a5fd761e983559fec9a69d2895ca6c3f86d93 100644 --- a/module/VuFind/src/VuFind/Auth/Manager.php +++ b/module/VuFind/src/VuFind/Auth/Manager.php @@ -362,6 +362,28 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface : true; } + /** + * Is login currently allowed? + * + * @return bool + */ + public function ajaxEnabled() + { + // Assume ajax is enabled unless explicitly turned off: + return $this->config->Authentication->enableAjax ?? true; + } + + /** + * Is login currently allowed? + * + * @return bool + */ + public function dropdownEnabled() + { + // Assume dropdown is disabled unless explicitly turned on: + return $this->config->Authentication->enableDropdown ?? false; + } + /** * Log out the current user. * diff --git a/module/VuFind/src/VuFind/Cache/Manager.php b/module/VuFind/src/VuFind/Cache/Manager.php index 8ced9ece90a15358cf494ec6314e2ed3fb799620..80dcde821661270083146da67ded7af77ac568bc 100644 --- a/module/VuFind/src/VuFind/Cache/Manager.php +++ b/module/VuFind/src/VuFind/Cache/Manager.php @@ -207,7 +207,7 @@ class Manager } /** - * Create a new file cache for the given theme name if neccessary. Return + * Create a new file cache for the given theme name if necessary. Return * the name of the cache. * * @param string $themeName Name of the theme diff --git a/module/VuFind/src/VuFind/Cart.php b/module/VuFind/src/VuFind/Cart.php index 1fed7c18ffb7cf84e4f54a7afc6d39e1b3d13f79..a9e4bf4b13a6164ac20e024fc132652dd5de4aa2 100644 --- a/module/VuFind/src/VuFind/Cart.php +++ b/module/VuFind/src/VuFind/Cart.php @@ -312,9 +312,9 @@ class Cart // Save the cookies: $cookie = implode(self::CART_COOKIE_DELIM, $ids); - $this->cookieManager->set(self::CART_COOKIE, $cookie, 0); + $this->cookieManager->set(self::CART_COOKIE, $cookie, 0, false); $srcCookie = implode(self::CART_COOKIE_DELIM, $sources); - $this->cookieManager->set(self::CART_COOKIE_SOURCES, $srcCookie, 0); + $this->cookieManager->set(self::CART_COOKIE_SOURCES, $srcCookie, 0, false); } /** diff --git a/module/VuFind/src/VuFind/ChannelProvider/AlphaBrowse.php b/module/VuFind/src/VuFind/ChannelProvider/AlphaBrowse.php index 0527d8d6bd1d2e4f7b3c6d031708ceeb9a257f0d..91d25c794ba0e1285d1a7b90fb99ff4aaad5be22 100644 --- a/module/VuFind/src/VuFind/ChannelProvider/AlphaBrowse.php +++ b/module/VuFind/src/VuFind/ChannelProvider/AlphaBrowse.php @@ -30,7 +30,6 @@ namespace VuFind\ChannelProvider; use VuFind\I18n\Translator\TranslatorAwareInterface; use VuFind\Record\Router as RecordRouter; use VuFind\RecordDriver\AbstractBase as RecordDriver; -use VuFind\Search\Base\Params; use VuFind\Search\Base\Results; use VuFindSearch\Backend\Solr\Backend; use VuFindSearch\ParamBag; diff --git a/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php b/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php index 9c01d2ca71993d7e9eeab63d7c2a323e03284c73..a69a61266153650dd7e1ec06dab6efb489c8bb82 100644 --- a/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php +++ b/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php @@ -30,7 +30,6 @@ namespace VuFind\ChannelProvider; use VuFind\I18n\Translator\TranslatorAwareInterface; use VuFind\Record\Router as RecordRouter; use VuFind\RecordDriver\AbstractBase as RecordDriver; -use VuFind\Search\Base\Params; use VuFind\Search\Base\Results; use Zend\Mvc\Controller\Plugin\Url; diff --git a/module/VuFind/src/VuFind/Config/YamlReader.php b/module/VuFind/src/VuFind/Config/YamlReader.php index 9b75189a2e97f03190c5ba8e7826e5b8ec8be383..4186ed9603415d718e13bd84e0abd7de97380668 100644 --- a/module/VuFind/src/VuFind/Config/YamlReader.php +++ b/module/VuFind/src/VuFind/Config/YamlReader.php @@ -74,17 +74,19 @@ class YamlReader /** * Return a configuration * - * @param string $filename config file name + * @param string $filename Config file name + * @param boolean $useLocalConfig Use local configuration if available + * @param boolean $ignoreFileCache Read from file even if config has been cached. * * @return array */ - public function get($filename) + public function get($filename, $useLocalConfig = true, $ignoreFileCache = false) { // Load data if it is not already in the object's cache: - if (!isset($this->files[$filename])) { + if ($ignoreFileCache || !isset($this->files[$filename])) { $this->files[$filename] = $this->getFromPaths( Locator::getBaseConfigPath($filename), - Locator::getLocalConfigPath($filename) + ($useLocalConfig ? Locator::getLocalConfigPath($filename) : null) ); } diff --git a/module/VuFind/src/VuFind/Content/Covers/BrowZine.php b/module/VuFind/src/VuFind/Content/Covers/BrowZine.php new file mode 100644 index 0000000000000000000000000000000000000000..840cae4513160a63b4a3fae61c99fcb0fd603b8d --- /dev/null +++ b/module/VuFind/src/VuFind/Content/Covers/BrowZine.php @@ -0,0 +1,83 @@ +<?php +/** + * BrowZine cover content loader. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Content + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\Content\Covers; + +use VuFindSearch\Backend\BrowZine\Connector; + +/** + * BrowZine cover content loader. + * + * @category VuFind + * @package Content + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class BrowZine extends \VuFind\Content\AbstractCover +{ + /** + * BrowZine connector. + * + * @var Connector + */ + protected $connector; + + /** + * Constructor + * + * @param Connector $connector BrowZine connector object + */ + public function __construct(Connector $connector) + { + $this->connector = $connector; + $this->supportsIssn = true; + } + + /** + * Get image URL for a particular API key and set of IDs (or false if invalid). + * + * @param string $key API key + * @param string $size Size of image to load (small/medium/large) + * @param array $ids Associative array of identifiers (keys may include 'isbn' + * pointing to an ISBN object and 'issn' pointing to a string) + * + * @return string|bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getUrl($key, $size, $ids) + { + // Don't bother trying if ISSN is missing: + if (!isset($ids['issn'])) { + return false; + } + + $result = $this->connector->lookupIssns($ids['issn']); + return $result['data'][0]['coverImageUrl'] ?? false; + } +} diff --git a/module/VuFind/src/VuFind/Content/Covers/BrowZineFactory.php b/module/VuFind/src/VuFind/Content/Covers/BrowZineFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..8545902e0642d7c91e90af6f8f6a2952dec81be3 --- /dev/null +++ b/module/VuFind/src/VuFind/Content/Covers/BrowZineFactory.php @@ -0,0 +1,68 @@ +<?php +/** + * BrowZine cover loader factory + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Content + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\Content\Covers; + +use Interop\Container\ContainerInterface; + +/** + * BrowZine cover loader factory + * + * @category VuFind + * @package Content + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +class BrowZineFactory implements \Zend\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $backend = $container->get('VuFind\Search\BackendManager')->get('BrowZine'); + return new $requestedName($backend->getConnector()); + } +} diff --git a/module/VuFind/src/VuFind/Content/Covers/PluginManager.php b/module/VuFind/src/VuFind/Content/Covers/PluginManager.php index 0b26f0d95f07479d1c5ba8a3ef275d1b838a92f5..c6095735a307c9085984435e660faa43a3c69ddf 100644 --- a/module/VuFind/src/VuFind/Content/Covers/PluginManager.php +++ b/module/VuFind/src/VuFind/Content/Covers/PluginManager.php @@ -47,6 +47,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'amazon' => 'VuFind\Content\Covers\Amazon', 'booksite' => 'VuFind\Content\Covers\Booksite', 'buchhandel' => 'VuFind\Content\Covers\Buchhandel', + 'browzine' => 'VuFind\Content\Covers\BrowZine', 'contentcafe' => 'VuFind\Content\Covers\ContentCafe', 'google' => 'VuFind\Content\Covers\Google', 'librarything' => 'VuFind\Content\Covers\LibraryThing', @@ -65,6 +66,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'VuFind\Content\Covers\Amazon' => 'VuFind\Content\Covers\Factory::getAmazon', 'VuFind\Content\Covers\Booksite' => 'VuFind\Content\Covers\Factory::getBooksite', + 'VuFind\Content\Covers\BrowZine' => 'VuFind\Content\Covers\BrowZineFactory', 'VuFind\Content\Covers\Buchhandel' => 'VuFind\Content\Covers\Factory::getBuchhandel', 'VuFind\Content\Covers\ContentCafe' => diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php index 033d9f56ff8c2800c94e62c4e483334728633531..faa08158a0b47aef8e837d69ab16e786cc4bcbbe 100644 --- a/module/VuFind/src/VuFind/Controller/AbstractBase.php +++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php @@ -616,6 +616,15 @@ class AbstractBase extends AbstractActionController return; } + // If the referer is the MyResearch/UserLogin action, it probably means + // that the user is repeatedly mistyping their password. We should + // ignore this and instead rely on any previously stored referer. + $myUserLogin = $this->getServerUrl('myresearch-userlogin'); + $mulNorm = $this->normalizeUrlForComparison($myUserLogin); + if (0 === strpos($refererNorm, $mulNorm)) { + return; + } + // If we got this far, we want to store the referer: $this->followup()->store([], $referer); } diff --git a/module/VuFind/src/VuFind/Controller/AlmaController.php b/module/VuFind/src/VuFind/Controller/AlmaController.php index d2ef5671e71127aea822ce1262495348475b0f49..555d088cbc17d0932c83e7e1b55c2f94a9679a0b 100644 --- a/module/VuFind/src/VuFind/Controller/AlmaController.php +++ b/module/VuFind/src/VuFind/Controller/AlmaController.php @@ -83,7 +83,7 @@ class AlmaController extends AbstractBase protected $userTable; /** - * Alma Controler constructor. + * Alma Controller constructor. * * @param ServiceLocatorInterface $sm The ServiceLocatorInterface */ @@ -429,7 +429,7 @@ class AlmaController extends AbstractBase /** * Helper function to check access permissions defined in permissions.ini. * The function validateAccessPermission() will throw an exception that can be - * catched when the permission is denied. + * caught when the permission is denied. * * @param string $accessPermission The permission name from permissions.ini that * should be checked. diff --git a/module/VuFind/src/VuFind/Controller/FeedbackController.php b/module/VuFind/src/VuFind/Controller/FeedbackController.php index 211bbe1d34a04d5accfbba7ba464e00c8c17bee0..7251b3b5399a2942d56753aceeb688f510a99a43 100644 --- a/module/VuFind/src/VuFind/Controller/FeedbackController.php +++ b/module/VuFind/src/VuFind/Controller/FeedbackController.php @@ -1,28 +1,29 @@ <?php /** - * Feedback Controller + * Controller for configurable forms (feedback etc). * * PHP version 7 * * @category VuFind * @package Controller * @author Josiah Knoll <jk1135@ship.edu> + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org Main Site */ namespace VuFind\Controller; use VuFind\Exception\Mail as MailException; +use VuFind\Form\Form; use Zend\Mail\Address; /** - * Feedback Class - * - * Controls the Feedback + * Controller for configurable forms (feedback etc). * * @category VuFind * @package Controller * @author Josiah Knoll <jk1135@ship.edu> + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ @@ -35,70 +36,165 @@ class FeedbackController extends AbstractBase */ public function homeAction() { - return $this->forwardTo('Feedback', 'Email'); + return $this->forwardTo('Feedback', 'Form'); } /** - * Receives input from the user and sends an email to the recipient set in - * the config.ini + * Handles rendering and submit of dynamic forms. + * Form configurations are specified in FeedbackForms.json * * @return void */ - public function emailAction() + public function formAction() { - $view = $this->createViewModel(); - $view->useRecaptcha = $this->recaptcha()->active('feedback'); - $view->name = $this->params()->fromPost('name'); - $view->email = $this->params()->fromPost('email'); - $view->comments = $this->params()->fromPost('comments'); - - // Process form submission: - if ($this->formWasSubmitted('submit', $view->useRecaptcha)) { - if (empty($view->email) || empty($view->comments)) { - $this->flashMessenger()->addMessage('bulk_error_missing', 'error'); - return; - } + $formId = $this->params()->fromRoute('id', $this->params()->fromQuery('id')); + if (!$formId) { + $formId = 'FeedbackSite'; + } - // These settings are set in the feedback settion of your config.ini - $config = $this->serviceLocator->get('VuFind\Config\PluginManager') - ->get('config'); - $feedback = isset($config->Feedback) ? $config->Feedback : null; - $recipient_email = isset($feedback->recipient_email) - ? $feedback->recipient_email : null; - $recipient_name = isset($feedback->recipient_name) - ? $feedback->recipient_name : 'Your Library'; - $email_subject = isset($feedback->email_subject) - ? $feedback->email_subject : 'VuFind Feedback'; - $sender_email = isset($feedback->sender_email) - ? $feedback->sender_email : 'noreply@vufind.org'; - $sender_name = isset($feedback->sender_name) - ? $feedback->sender_name : 'VuFind Feedback'; - if ($recipient_email == null) { - throw new \Exception( - 'Feedback Module Error: Recipient Email Unset (see config.ini)' - ); - } + $user = $this->getUser(); - $email_message = empty($view->name) ? '' : 'Name: ' . $view->name . "\n"; - $email_message .= 'Email: ' . $view->email . "\n"; - $email_message .= 'Comments: ' . $view->comments . "\n\n"; - - // This sets up the email to be sent - // Attempt to send the email and show an appropriate flash message: - try { - $mailer = $this->serviceLocator->get('VuFind\Mailer\Mailer'); - $mailer->send( - new Address($recipient_email, $recipient_name), - new Address($sender_email, $sender_name), - $email_subject, $email_message - ); - $this->flashMessenger()->addMessage( - 'Thank you for your feedback.', 'success' - ); - } catch (MailException $e) { - $this->flashMessenger()->addMessage($e->getMessage(), 'error'); - } + $form = $this->serviceLocator->get('VuFind\Form\Form'); + $form->setFormId($formId); + + if (!$form->isEnabled()) { + throw new \VuFind\Exception\Forbidden("Form '$formId' is disabled"); } + + $view = $this->createViewModel(compact('form', 'formId', 'user')); + $view->useRecaptcha + = $this->recaptcha()->active('feedback') && $form->useCaptcha(); + + $params = $this->params(); + $form->setData($params->fromPost()); + + if (!$this->formWasSubmitted('submit', $view->useRecaptcha)) { + $form = $this->prefillUserInfo($form, $user); + return $view; + } + + if (! $form->isValid()) { + return $view; + } + + list($messageParams, $template) + = $form->formatEmailMessage($this->params()->fromPost()); + $emailMessage = $this->getViewRenderer()->partial( + $template, ['fields' => $messageParams] + ); + + list($senderName, $senderEmail) = $this->getSender(); + + $replyToName = $params->fromPost( + 'name', + $user ? trim($user->firstname . ' ' . $user->lastname) : null + ); + $replyToEmail = $params->fromPost( + 'email', + $user ? $user->email : null + ); + + list($recipientName, $recipientEmail) = $form->getRecipient(); + + $emailSubject = $form->getEmailSubject($params->fromPost()); + + list($success, $errorMsg) = $this->sendEmail( + $recipientName, $recipientEmail, $senderName, $senderEmail, + $replyToName, $replyToEmail, $emailSubject, $emailMessage + ); + + $this->showResponse($view, $form, $success, $errorMsg); + return $view; } + + /** + * Prefill form sender fields for logged in users. + * + * @param Form $form Form + * @param array $user User + * + * @return Form + */ + protected function prefillUserInfo($form, $user) + { + if ($user) { + $form->setData( + [ + 'name' => $user->firstname . ' ' . $user->lastname, + 'email' => $user['email'] + ] + ); + } + return $form; + } + + /** + * Send form data as email. + * + * @param string $recipientName Recipient name + * @param string $recipientEmail Recipient email + * @param string $senderName Sender name + * @param string $senderEmail Sender email + * @param string $replyToName Reply-to name + * @param string $replyToEmail Reply-to email + * @param string $emailSubject Email subject + * @param string $emailMessage Email message + * + * @return array with elements success:boolean, errorMessage:string (optional) + */ + protected function sendEmail( + $recipientName, $recipientEmail, $senderName, $senderEmail, + $replyToName, $replyToEmail, $emailSubject, $emailMessage + ) { + try { + $mailer = $this->serviceLocator->get('VuFind\Mailer\Mailer'); + if ($replyToEmail) { + $mailer->setFromAddressOverride(''); + } + $mailer->send( + new Address($recipientEmail, $recipientName), + new Address($senderEmail, $senderName), + $emailSubject, $emailMessage, null, $replyToEmail + ); + return [true, null]; + } catch (MailException $e) { + return [false, $e->getMessage()]; + } + } + + /** + * Show response after form submit. + * + * @param View $view View + * @param Form $form Form + * @param boolean $success Was email sent successfully? + * @param string $errorMsg Error message (optional) + * + * @return array with name, email + */ + protected function showResponse($view, $form, $success, $errorMsg = null) + { + if ($success) { + $this->flashMessenger()->addMessage( + $form->getSubmitResponse(), 'success' + ); + } else { + $this->flashMessenger()->addMessage($errorMsg, 'error'); + } + } + + /** + * Return email sender from configuration. + * + * @return array with name, email + */ + protected function getSender() + { + $config = $this->getConfig()->Feedback; + $email = $config->sender_email ?? 'noreply@vufind.org'; + $name = $config->sender_name ?? 'VuFind Feedback'; + + return [$name, $email]; + } } diff --git a/module/VuFind/src/VuFind/Controller/InstallController.php b/module/VuFind/src/VuFind/Controller/InstallController.php index 4ca799742f22a479c38b572d512da5ae62dac14a..0bbd22c2a4a4258a7df9ae174f2582fa07b98907 100644 --- a/module/VuFind/src/VuFind/Controller/InstallController.php +++ b/module/VuFind/src/VuFind/Controller/InstallController.php @@ -555,11 +555,11 @@ class InstallController extends AbstractBase = opendir(APPLICATION_PATH . '/module/VuFind/src/VuFind/ILS/Driver'); $drivers = []; $blacklist = [ - 'Sample.php', 'Demo.php', 'DriverInterface.php', 'AbstractBase.php', - 'PluginManager.php', + 'Sample.php', 'Demo.php', 'DriverInterface.php', 'PluginManager.php', ]; while ($line = readdir($dir)) { if (stristr($line, '.php') && !in_array($line, $blacklist) + && substr($line, 0, 8) !== 'Abstract' && substr($line, -11) !== 'Factory.php' && substr($line, -9) !== 'Trait.php' ) { diff --git a/module/VuFind/src/VuFind/Controller/LibraryCardsController.php b/module/VuFind/src/VuFind/Controller/LibraryCardsController.php index f700a488a7be8182bd7692b72a0b277ddcc252dd..909c51aa604964690fe1ab89bb7c6d7d3b7728c4 100644 --- a/module/VuFind/src/VuFind/Controller/LibraryCardsController.php +++ b/module/VuFind/src/VuFind/Controller/LibraryCardsController.php @@ -29,6 +29,8 @@ */ namespace VuFind\Controller; +use VuFind\Exception\ILS as ILSException; + /** * Controller for the library card functionality. * @@ -131,7 +133,6 @@ class LibraryCardsController extends AbstractBase 'cardName' => $cardName, 'target' => $target ? $target : $defaultTarget, 'username' => $username, - 'password' => $card->cat_password, 'targets' => $targets, 'defaultTarget' => $defaultTarget ] @@ -190,16 +191,25 @@ class LibraryCardsController extends AbstractBase } $cardID = $this->params()->fromQuery('cardID'); + if (null === $cardID) { + return $this->redirect()->toRoute('myresearch-home'); + } $user->activateLibraryCard($cardID); // Connect to the ILS and check that the credentials are correct: - $catalog = $this->getILS(); - $patron = $catalog->patronLogin( - $user->cat_username, $user->getCatPassword() - ); - if (!$patron) { + try { + $catalog = $this->getILS(); + $patron = $catalog->patronLogin( + $user->cat_username, + $user->getCatPassword() + ); + if (!$patron) { + $this->flashMessenger() + ->addMessage('authentication_error_invalid', 'error'); + } + } catch (ILSException $e) { $this->flashMessenger() - ->addMessage('authentication_error_invalid', 'error'); + ->addMessage('authentication_error_technical', 'error'); } $this->setFollowupUrlToReferer(); @@ -224,8 +234,9 @@ class LibraryCardsController extends AbstractBase $target = $this->params()->fromPost('target', ''); $username = $this->params()->fromPost('username', ''); $password = $this->params()->fromPost('password', ''); + $id = $this->params()->fromRoute('id', $this->params()->fromQuery('id')); - if (!$username || !$password) { + if (!$username) { $this->flashMessenger() ->addMessage('authentication_error_blank', 'error'); return false; @@ -235,16 +246,20 @@ class LibraryCardsController extends AbstractBase $username = "$target.$username"; } - // Connect to the ILS and check that the credentials are correct: - $catalog = $this->getILS(); - $patron = $catalog->patronLogin($username, $password); - if (!$patron) { - $this->flashMessenger() - ->addMessage('authentication_error_invalid', 'error'); - return false; + // Check the credentials if the username is changed or a new password is + // entered: + $card = $user->getLibraryCard($id == 'NEW' ? null : $id); + if ($card->cat_username !== $username || trim($password)) { + // Connect to the ILS and check that the credentials are correct: + $catalog = $this->getILS(); + $patron = $catalog->patronLogin($username, $password); + if (!$patron) { + $this->flashMessenger() + ->addMessage('authentication_error_invalid', 'error'); + return false; + } } - $id = $this->params()->fromRoute('id', $this->params()->fromQuery('id')); try { $user->saveLibraryCard( $id == 'NEW' ? null : $id, $cardName, $username, $password diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php index f0f331671899ff0245125c22c79612c4fd1eb834..937a691131c3d147cf03404cfb59a0e30784cdde 100644 --- a/module/VuFind/src/VuFind/Controller/MyResearchController.php +++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php @@ -32,6 +32,7 @@ use VuFind\Exception\Forbidden as ForbiddenException; use VuFind\Exception\ILS as ILSException; use VuFind\Exception\ListPermission as ListPermissionException; use VuFind\Exception\Mail as MailException; +use VuFind\ILS\PaginationHelper; use VuFind\Search\RecommendListener; use Zend\Stdlib\Parameters; use Zend\View\Model\ViewModel; @@ -47,6 +48,13 @@ use Zend\View\Model\ViewModel; */ class MyResearchController extends AbstractBase { + /** + * ILS Pagination Helper + * + * @var PaginationHelper + */ + protected $paginationHelper = null; + /** * Are we currently in a lightbox context? * @@ -465,7 +473,7 @@ class MyResearchController extends AbstractBase */ public function addAccountBlocksToFlashMessenger($catalog, $patron) { - if ($catalog->checkCapability('getAccountBlocks', compact($patron)) + if ($catalog->checkCapability('getAccountBlocks', compact('patron')) && $blocks = $catalog->getAccountBlocks($patron) ) { foreach ($blocks as $block) { @@ -1195,30 +1203,32 @@ class MyResearchController extends AbstractBase // By default, assume we will not need to display a renewal form: $renewForm = false; - // Get checked out item details: - $result = $catalog->getMyTransactions($patron); - - // Get page size: + // Get paging setup: $config = $this->getConfig(); - $limit = isset($config->Catalog->checked_out_page_size) - ? $config->Catalog->checked_out_page_size : 50; + $pageOptions = $this->getPaginationHelper()->getOptions( + (int)$this->params()->fromQuery('page', 1), + $this->params()->fromQuery('sort'), + $config->Catalog->checked_out_page_size ?? 50, + $catalog->checkFunction('getMyTransactions', $patron) + ); + + // Get checked out item details: + $result = $catalog->getMyTransactions($patron, $pageOptions['ilsParams']); // Build paginator if needed: - if ($limit > 0 && $limit < count($result)) { - $adapter = new \Zend\Paginator\Adapter\ArrayAdapter($result); - $paginator = new \Zend\Paginator\Paginator($adapter); - $paginator->setItemCountPerPage($limit); - $paginator->setCurrentPageNumber($this->params()->fromQuery('page', 1)); + $paginator = $this->getPaginationHelper()->getPaginator( + $pageOptions, $result['count'], $result['records'] + ); + if ($paginator) { $pageStart = $paginator->getAbsoluteItemNumber(1) - 1; - $pageEnd = $paginator->getAbsoluteItemNumber($limit) - 1; + $pageEnd = $paginator->getAbsoluteItemNumber($pageOptions['limit']) - 1; } else { - $paginator = false; $pageStart = 0; - $pageEnd = count($result); + $pageEnd = $result['count']; } $transactions = $hiddenTransactions = []; - foreach ($result as $i => $current) { + foreach ($result['records'] as $i => $current) { // Add renewal details if appropriate: $current = $this->renewals()->addRenewDetails( $catalog, $current, $renewStatus @@ -1231,7 +1241,7 @@ class MyResearchController extends AbstractBase } // Build record driver (only for the current visible page): - if ($i >= $pageStart && $i <= $pageEnd) { + if ($pageOptions['ilsPaging'] || ($i >= $pageStart && $i <= $pageEnd)) { $transactions[] = $this->getDriverForILSRecord($current); } else { $hiddenTransactions[] = $current; @@ -1241,10 +1251,13 @@ class MyResearchController extends AbstractBase $displayItemBarcode = !empty($config->Catalog->display_checked_out_item_barcode); + $ilsPaging = $pageOptions['ilsPaging']; + $sortList = $pageOptions['sortList']; + $params = $pageOptions['ilsParams']; return $this->createViewModel( compact( - 'transactions', 'renewForm', 'renewResult', 'paginator', - 'hiddenTransactions', 'displayItemBarcode' + 'transactions', 'renewForm', 'renewResult', 'paginator', 'ilsPaging', + 'hiddenTransactions', 'displayItemBarcode', 'sortList', 'params' ) ); } @@ -1273,73 +1286,31 @@ class MyResearchController extends AbstractBase return $this->createViewModel(); } - // Get page and page size: - $page = (int)$this->params()->fromQuery('page', 1); + // Get paging setup: $config = $this->getConfig(); - $limit = isset($config->Catalog->historic_loan_page_size) - ? $config->Catalog->historic_loan_page_size : 50; - $ilsPaging = true; - if (isset($functionConfig['max_results'])) { - $limit = min([$functionConfig['max_results'], $limit]); - } elseif (isset($functionConfig['page_size'])) { - if (!in_array($limit, $functionConfig['page_size'])) { - $limit = $functionConfig['default_page_size'] - ?? $functionConfig['page_size'][0]; - } - } else { - $ilsPaging = false; - } - - // Get sort settings - $sort = false; - if (!empty($functionConfig['sort'])) { - $sort = $this->params()->fromQuery('sort'); - if (!isset($functionConfig['sort'][$sort])) { - if (isset($functionConfig['default_sort'])) { - $sort = $functionConfig['default_sort']; - } else { - reset($functionConfig['sort']); - $sort = key($functionConfig['sort']); - } - } - } - - // Configure call params - $params = [ - 'sort' => $sort - ]; - if ($ilsPaging) { - $params['page'] = $page; - $params['limit'] = $limit; - } + $pageOptions = $this->getPaginationHelper()->getOptions( + (int)$this->params()->fromQuery('page', 1), + $this->params()->fromQuery('sort'), + $config->Catalog->historic_loan_page_size ?? 50, + $functionConfig + ); // Get checked out item details: - $result = $catalog->getMyTransactionHistory($patron, $params); + $result + = $catalog->getMyTransactionHistory($patron, $pageOptions['ilsParams']); if (isset($result['success']) && !$result['success']) { $this->flashMessenger()->addErrorMessage($result['status']); return $this->createViewModel(); } - // Build paginator if needed: - if ($ilsPaging && $limit < $result['count']) { - $adapter = new \Zend\Paginator\Adapter\NullFill($result['count']); - $paginator = new \Zend\Paginator\Paginator($adapter); - $paginator->setItemCountPerPage($limit); - $paginator->setCurrentPageNumber($page); - $pageStart = $paginator->getAbsoluteItemNumber(1) - 1; - $pageEnd = $paginator->getAbsoluteItemNumber($limit) - 1; - } elseif ($limit > 0 && $limit < $result['count']) { - $adapter = new \Zend\Paginator\Adapter\ArrayAdapter( - $result['transactions'] - ); - $paginator = new \Zend\Paginator\Paginator($adapter); - $paginator->setItemCountPerPage($limit); - $paginator->setCurrentPageNumber($page); + $paginator = $this->getPaginationHelper()->getPaginator( + $pageOptions, $result['count'], $result['transactions'] + ); + if ($paginator) { $pageStart = $paginator->getAbsoluteItemNumber(1) - 1; - $pageEnd = $paginator->getAbsoluteItemNumber($limit) - 1; + $pageEnd = $paginator->getAbsoluteItemNumber($pageOptions['limit']) - 1; } else { - $paginator = false; $pageStart = 0; $pageEnd = $result['count']; } @@ -1347,25 +1318,15 @@ class MyResearchController extends AbstractBase $transactions = $hiddenTransactions = []; foreach ($result['transactions'] as $i => $current) { // Build record driver (only for the current visible page): - if ($ilsPaging || ($i >= $pageStart && $i <= $pageEnd)) { + if ($pageOptions['ilsPaging'] || ($i >= $pageStart && $i <= $pageEnd)) { $transactions[] = $this->getDriverForILSRecord($current); } else { $hiddenTransactions[] = $current; } } - // Handle view params for sorting - $sortList = []; - if (!empty($functionConfig['sort'])) { - foreach ($functionConfig['sort'] as $key => $value) { - $sortList[$key] = [ - 'desc' => $value, - 'url' => '?sort=' . urlencode($key), - 'selected' => $sort == $key - ]; - } - } - + $sortList = $pageOptions['sortList']; + $params = $pageOptions['ilsParams']; return $this->createViewModel( compact( 'transactions', 'paginator', 'params', @@ -1757,4 +1718,17 @@ class MyResearchController extends AbstractBase } return $view; } + + /** + * Get the ILS pagination helper + * + * @return PaginationHelper + */ + protected function getPaginationHelper() + { + if (null === $this->paginationHelper) { + $this->paginationHelper = new PaginationHelper(); + } + return $this->paginationHelper; + } } diff --git a/module/VuFind/src/VuFind/Controller/OaiController.php b/module/VuFind/src/VuFind/Controller/OaiController.php index 0024247a4874f9d9a602b98a90c4f0520d80b066..5e53f01b7e08a0e6fd41088a321992d092d6b71d 100644 --- a/module/VuFind/src/VuFind/Controller/OaiController.php +++ b/module/VuFind/src/VuFind/Controller/OaiController.php @@ -108,6 +108,9 @@ class OaiController extends AbstractBase $server->setRecordLinkHelper( $this->getViewRenderer()->plugin('recordLink') ); + $server->setRecordFormatter( + $this->serviceLocator->get('VuFindApi\Formatter\RecordFormatter') + ); $xml = $server->getResponse(); } catch (\Exception $e) { $response->setStatusCode(500); diff --git a/module/VuFind/src/VuFind/Controller/RelaisController.php b/module/VuFind/src/VuFind/Controller/RelaisController.php index 7975838a6bcff1caddd8ae3fd283964fea5ee067..d66afb60c230883295a9245fd298a270f44d2162 100644 --- a/module/VuFind/src/VuFind/Controller/RelaisController.php +++ b/module/VuFind/src/VuFind/Controller/RelaisController.php @@ -64,7 +64,7 @@ class RelaisController extends AbstractBase . '&dest=discovery&group=patron&PI=' . urlencode($patron['cat_username']); if (!empty($q)) { - $url .= '&query=' . urlencode($q); + $url .= '&query=' . rawurlencode($q); } return $this->redirect()->toUrl($url); } diff --git a/module/VuFind/src/VuFind/Cookie/CookieManager.php b/module/VuFind/src/VuFind/Cookie/CookieManager.php index 7bdd0ea6ddb89fd401b450f3ebed1b5b1f59e330..411d30fe63aad2c05c757bc9a3d70afd8de145a6 100644 --- a/module/VuFind/src/VuFind/Cookie/CookieManager.php +++ b/module/VuFind/src/VuFind/Cookie/CookieManager.php @@ -59,6 +59,13 @@ class CookieManager */ protected $secure; + /** + * Are cookies HTTP only? + * + * @var bool + */ + protected $httpOnly; + /** * The name of the session cookie * @@ -75,14 +82,16 @@ class CookieManager * @param bool $secure Are cookies secure only? (default = false) * @param string $sessionName Session cookie name (if null defaults to PHP * settings) + * @param bool $httpOnly Are cookies HTTP only? (default = true) */ public function __construct($cookies, $path = '/', $domain = null, - $secure = false, $sessionName = null + $secure = false, $sessionName = null, $httpOnly = true ) { $this->cookies = $cookies; $this->path = $path; $this->domain = $domain; $this->secure = $secure; + $this->httpOnly = $httpOnly; $this->sessionName = $sessionName; } @@ -126,6 +135,16 @@ class CookieManager return $this->secure; } + /** + * Are cookies set to "HTTP only" mode? + * + * @return bool + */ + public function isHttpOnly() + { + return $this->httpOnly; + } + /** * Get the name of the cookie * @@ -144,26 +163,31 @@ class CookieManager */ public function proxySetCookie() { - // Special case: in test suite -- don't actually write headers! - return defined('VUFIND_PHPUNIT_RUNNING') + // Special case: in CLI -- don't actually write headers! + return 'cli' === PHP_SAPI ? true : call_user_func_array('setcookie', func_get_args()); } /** * Support method for set() -- set the actual cookie in PHP. * - * @param string $key Name of cookie to set - * @param mixed $value Value to set - * @param int $expire Cookie expiration time + * @param string $key Name of cookie to set + * @param mixed $value Value to set + * @param int $expire Cookie expiration time + * @param null|bool $httpOnly Whether the cookie should be "HTTP only" * * @return bool */ - public function setGlobalCookie($key, $value, $expire) + public function setGlobalCookie($key, $value, $expire, $httpOnly = null) { + if (null === $httpOnly) { + $httpOnly = $this->httpOnly; + } // Simple case: flat value. if (!is_array($value)) { return $this->proxySetCookie( - $key, $value, $expire, $this->path, $this->domain, $this->secure + $key, $value, $expire, $this->path, $this->domain, $this->secure, + $httpOnly ); } @@ -172,7 +196,7 @@ class CookieManager foreach ($value as $i => $curr) { $lastSuccess = $this->proxySetCookie( $key . '[' . $i . ']', $curr, $expire, - $this->path, $this->domain, $this->secure + $this->path, $this->domain, $this->secure, $httpOnly ); if (!$lastSuccess) { $success = false; @@ -184,15 +208,16 @@ class CookieManager /** * Set a cookie. * - * @param string $key Name of cookie to set - * @param mixed $value Value to set - * @param int $expire Cookie expiration time + * @param string $key Name of cookie to set + * @param mixed $value Value to set + * @param int $expire Cookie expiration time + * @param null|bool $httpOnly Whether the cookie should be "HTTP only" * * @return bool */ - public function set($key, $value, $expire = 0) + public function set($key, $value, $expire = 0, $httpOnly = null) { - if ($success = $this->setGlobalCookie($key, $value, $expire)) { + if ($success = $this->setGlobalCookie($key, $value, $expire, $httpOnly)) { $this->cookies[$key] = $value; } return $success; diff --git a/module/VuFind/src/VuFind/Cookie/CookieManagerFactory.php b/module/VuFind/src/VuFind/Cookie/CookieManagerFactory.php index 5b84634381439d8527c1ebd6a195807826526a7b..e92ea718d403fac8fd3dddca8224cd73c41e9913 100644 --- a/module/VuFind/src/VuFind/Cookie/CookieManagerFactory.php +++ b/module/VuFind/src/VuFind/Cookie/CookieManagerFactory.php @@ -64,24 +64,19 @@ class CookieManagerFactory implements FactoryInterface } $config = $container->get('VuFind\Config\PluginManager')->get('config'); $path = '/'; - if (isset($config->Cookies->limit_by_path) - && $config->Cookies->limit_by_path - ) { + if ($config->Cookies->limit_by_path ?? false) { $path = Console::isConsole() ? '' : $container->get('Request')->getBasePath(); if (empty($path)) { $path = '/'; } } - $secure = isset($config->Cookies->only_secure) - ? $config->Cookies->only_secure - : false; - $domain = isset($config->Cookies->domain) - ? $config->Cookies->domain - : null; - $session_name = isset($config->Cookies->session_name) - ? $config->Cookies->session_name - : null; - return new $requestedName($_COOKIE, $path, $domain, $secure, $session_name); + $secure = $config->Cookies->only_secure ?? false; + $httpOnly = $config->Cookies->http_only ?? true; + $domain = $config->Cookies->domain ?? null; + $session_name = $config->Cookies->session_name ?? null; + return new $requestedName( + $_COOKIE, $path, $domain, $secure, $session_name, $httpOnly + ); } } diff --git a/module/VuFind/src/VuFind/Db/Row/Resource.php b/module/VuFind/src/VuFind/Db/Row/Resource.php index e2ecfd618b77628f4a73eb978fdb2d85a11b9d71..d0f14a80da830adf3173cade7840597598413bb4 100644 --- a/module/VuFind/src/VuFind/Db/Row/Resource.php +++ b/module/VuFind/src/VuFind/Db/Row/Resource.php @@ -196,6 +196,9 @@ class Resource extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf $this->year = intval($year); } + if ($extra = $driver->tryMethod('getExtraResourceMetadata')) { + $this->extra_metadata = json_encode($extra); + } return $this; } } diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php index a0de0e5de28d5af9f9d3248de6429f313d4debda..2b3205e04782d9a00dd16de08247a68243bde0aa 100644 --- a/module/VuFind/src/VuFind/Db/Row/User.php +++ b/module/VuFind/src/VuFind/Db/Row/User.php @@ -567,9 +567,11 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface, $row->save(); - // If this is the first library card or no credentials are currently set, - // activate the card now - if ($this->getLibraryCards()->count() == 1 || empty($this->cat_username)) { + // If this is the first or active library card, or no credentials are + // currently set, activate the card now + if ($this->getLibraryCards()->count() == 1 || empty($this->cat_username) + || $this->cat_username === $row->cat_username + ) { $this->activateLibraryCard($row->id); } diff --git a/module/VuFind/src/VuFind/Db/Table/Resource.php b/module/VuFind/src/VuFind/Db/Table/Resource.php index 4fe1921e2568360d68aa59368f696ae8c845bb6d..fd28573bd3344ee2eb64b20be40e67ab5a2b1896 100644 --- a/module/VuFind/src/VuFind/Db/Table/Resource.php +++ b/module/VuFind/src/VuFind/Db/Table/Resource.php @@ -222,6 +222,54 @@ class Resource extends Gateway return $this->select($callback); } + /** + * Update the database to reflect a changed record identifier. + * + * @param string $oldId Original record ID + * @param string $newId Revised record ID + * @param string $source Record source + * + * @return void + */ + public function updateRecordId($oldId, $newId, $source = DEFAULT_SEARCH_BACKEND) + { + if ($oldId !== $newId + && $resource = $this->findResource($oldId, $source) + ) { + // Do this as a transaction to prevent odd behavior: + $connection = $this->getAdapter()->getDriver()->getConnection(); + $connection->beginTransaction(); + // Does the new ID already exist? + if ($newResource = $this->findResource($newId, $source)) { + // Special case: merge new ID and old ID: + $tableObjects = []; + foreach (['comments', 'userresource', 'resourcetags'] as $table) { + $tableObjects[$table] = $this->getDbTable($table); + $tableObjects[$table]->update( + ['resource_id' => $newResource->id], + ['resource_id' => $resource->id] + ); + } + $resource->delete(); + } else { + // Default case: just update the record ID: + $resource->record_id = $newId(); + $resource->save(); + } + // Done -- commit the transaction: + $connection->commit(); + + // Deduplicate rows where necessary (this can be safely done outside + // of the transaction): + if (isset($tableObjects['resourcetags'])) { + $tableObjects['resourcetags']->deduplicate(); + } + if (isset($tableObjects['userresource'])) { + $tableObjects['userresource']->deduplicate(); + } + } + } + /** * Apply a sort parameter to a query on the resource table. * diff --git a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php index 6dfe17c2b1b17a9b08c198551de0ab1c0628f12f..21b8883402fe0c53047f50e5834495e8753b6dfc 100644 --- a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php +++ b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php @@ -591,4 +591,67 @@ class ResourceTags extends Gateway $this->delete($callback); return count($ids); } + + /** + * Get a list of duplicate rows (this sometimes happens after merging IDs, + * for example after a Summon resource ID changes). + * + * @return mixed + */ + public function getDuplicates() + { + $callback = function ($select) { + $select->columns( + [ + 'resource_id' => new Expression( + 'MIN(?)', ['resource_id'], [Expression::TYPE_IDENTIFIER] + ), + 'tag_id' => new Expression( + 'MIN(?)', ['tag_id'], [Expression::TYPE_IDENTIFIER] + ), + 'list_id' => new Expression( + 'MIN(?)', ['list_id'], [Expression::TYPE_IDENTIFIER] + ), + 'user_id' => new Expression( + 'MIN(?)', ['user_id'], [Expression::TYPE_IDENTIFIER] + ), + 'cnt' => new Expression( + 'COUNT(?)', ['resource_id'], [Expression::TYPE_IDENTIFIER] + ), + 'id' => new Expression( + 'MIN(?)', ['id'], [Expression::TYPE_IDENTIFIER] + ) + ] + ); + $select->group(['resource_id', 'tag_id', 'list_id', 'user_id']); + $select->having('COUNT(resource_id) > 1'); + }; + return $this->select($callback); + } + + /** + * Deduplicate rows (sometimes necessary after merging foreign key IDs). + * + * @return void + */ + public function deduplicate() + { + foreach ($this->getDuplicates() as $dupe) { + $callback = function ($select) use ($dupe) { + // match on all relevant IDs in duplicate group + $select->where( + [ + 'resource_id' => $dupe['resource_id'], + 'tag_id' => $dupe['tag_id'], + 'list_id' => $dupe['list_id'], + 'user_id' => $dupe['user_id'], + ] + ); + // getDuplicates returns the minimum id in the set, so we want to + // delete all of the duplicates with a higher id value. + $select->where->greaterThan('id', $dupe['id']); + }; + $this->delete($callback); + } + } } diff --git a/module/VuFind/src/VuFind/Db/Table/UserResource.php b/module/VuFind/src/VuFind/Db/Table/UserResource.php index ce1ef8a8cb2d724b60677f509e47bd9a69d6c9f5..a59afaa4757d121985afa40a0bcca1f86c41d16e 100644 --- a/module/VuFind/src/VuFind/Db/Table/UserResource.php +++ b/module/VuFind/src/VuFind/Db/Table/UserResource.php @@ -210,4 +210,82 @@ class UserResource extends Gateway $result = $statement->execute(); return (array)$result->current(); } + + /** + * Get a list of duplicate rows (this sometimes happens after merging IDs, + * for example after a Summon resource ID changes). + * + * @return mixed + */ + public function getDuplicates() + { + $callback = function ($select) { + $select->columns( + [ + 'resource_id' => new Expression( + 'MIN(?)', ['resource_id'], [Expression::TYPE_IDENTIFIER] + ), + 'list_id' => new Expression( + 'MIN(?)', ['list_id'], [Expression::TYPE_IDENTIFIER] + ), + 'user_id' => new Expression( + 'MIN(?)', ['user_id'], [Expression::TYPE_IDENTIFIER] + ), + 'cnt' => new Expression( + 'COUNT(?)', ['resource_id'], [Expression::TYPE_IDENTIFIER] + ), + 'id' => new Expression( + 'MIN(?)', ['id'], [Expression::TYPE_IDENTIFIER] + ) + ] + ); + $select->group(['resource_id', 'list_id', 'user_id']); + $select->having('COUNT(resource_id) > 1'); + }; + return $this->select($callback); + } + + /** + * Deduplicate rows (sometimes necessary after merging foreign key IDs). + * + * @return void + */ + public function deduplicate() + { + foreach ($this->getDuplicates() as $dupe) { + // Do this as a transaction to prevent odd behavior: + $connection = $this->getAdapter()->getDriver()->getConnection(); + $connection->beginTransaction(); + + // Merge notes together... + $mainCriteria = [ + 'resource_id' => $dupe['resource_id'], + 'list_id' => $dupe['list_id'], + 'user_id' => $dupe['user_id'], + ]; + $dupeRows = $this->select($mainCriteria); + $notes = []; + foreach ($dupeRows as $row) { + if (!empty($row['notes'])) { + $notes[] = $row['notes']; + } + } + $this->update( + ['notes' => implode(' ', $notes)], + ['id' => $dupe['id']] + ); + // Now delete extra rows... + $callback = function ($select) use ($dupe, $mainCriteria) { + // match on all relevant IDs in duplicate group + $select->where($mainCriteria); + // getDuplicates returns the minimum id in the set, so we want to + // delete all of the duplicates with a higher id value. + $select->where->greaterThan('id', $dupe['id']); + }; + $this->delete($callback); + + // Done -- commit the transaction: + $connection->commit(); + } + } } diff --git a/module/VuFind/src/VuFind/DoiLinker/BrowZine.php b/module/VuFind/src/VuFind/DoiLinker/BrowZine.php new file mode 100644 index 0000000000000000000000000000000000000000..1366466a2f68312c31deb9ecdc806ecefca01896 --- /dev/null +++ b/module/VuFind/src/VuFind/DoiLinker/BrowZine.php @@ -0,0 +1,98 @@ +<?php +/** + * BrowZine DOI linker + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\DoiLinker; + +use VuFind\I18n\Translator\TranslatorAwareInterface; +use VuFindSearch\Backend\BrowZine\Connector; + +/** + * BrowZine DOI linker + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +class BrowZine implements DoiLinkerInterface, TranslatorAwareInterface +{ + use \VuFind\I18n\Translator\TranslatorAwareTrait; + + /** + * BrowZine connector + * + * @var Connector + */ + protected $connector; + + /** + * Constructor + * + * @param Connector $connector Connector + */ + public function __construct(Connector $connector) + { + $this->connector = $connector; + } + + /** + * Given an array of DOIs, perform a lookup and return an associative array + * of arrays, keyed by DOI. Each array contains one or more associative arrays + * with required 'link' (URL to related resource) and 'label' (display text) + * keys and an optional 'icon' (URL to icon graphic) key. + * + * @param array $doiArray DOIs to look up + * + * @return array + */ + public function getLinks(array $doiArray) + { + $baseIconUrl = 'https://assets.thirdiron.com/images/integrations/'; + $response = []; + foreach ($doiArray as $doi) { + $data = $this->connector->lookupDoi($doi)['data'] ?? null; + if (!empty($data['browzineWebLink'])) { + $response[$doi][] = [ + 'link' => $data['browzineWebLink'], + 'label' => $this->translate('View Complete Issue'), + 'icon' => $baseIconUrl . 'browzine-open-book-icon.svg', + 'data' => $data, + ]; + } + if (!empty($data['fullTextFile'])) { + $response[$doi][] = [ + 'link' => $data['fullTextFile'], + 'label' => $this->translate('PDF Full Text'), + 'icon' => $baseIconUrl . 'browzine-pdf-download-icon.svg', + 'data' => $data, + ]; + } + } + return $response; + } +} diff --git a/module/VuFind/src/VuFind/DoiLinker/BrowZineFactory.php b/module/VuFind/src/VuFind/DoiLinker/BrowZineFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..4256b24dae4502e1b6201709904053ac8117fe62 --- /dev/null +++ b/module/VuFind/src/VuFind/DoiLinker/BrowZineFactory.php @@ -0,0 +1,68 @@ +<?php +/** + * BrowZine DOI linker factory + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\DoiLinker; + +use Interop\Container\ContainerInterface; + +/** + * BrowZine DOI linker factory + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +class BrowZineFactory implements \Zend\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $backend = $container->get('VuFind\Search\BackendManager')->get('BrowZine'); + return new $requestedName($backend->getConnector()); + } +} diff --git a/module/VuFind/src/VuFind/DoiLinker/DoiLinkerInterface.php b/module/VuFind/src/VuFind/DoiLinker/DoiLinkerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a4c6d4063bfefce51307ae64c05768841bd3d209 --- /dev/null +++ b/module/VuFind/src/VuFind/DoiLinker/DoiLinkerInterface.php @@ -0,0 +1,52 @@ +<?php +/** + * DOI linker interface + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\DoiLinker; + +/** + * DOI linker interface + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +interface DoiLinkerInterface +{ + /** + * Given an array of DOIs, perform a lookup and return an associative array + * of arrays, keyed by DOI. Each array contains one or more associative arrays + * with required 'link' (URL to related resource) and 'label' (display text) + * keys and an optional 'icon' (URL to icon graphic) key. + * + * @param array $doiArray DOIs to look up + * + * @return array + */ + public function getLinks(array $doiArray); +} diff --git a/module/VuFind/src/VuFind/DoiLinker/PluginManager.php b/module/VuFind/src/VuFind/DoiLinker/PluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..38dd88ccfcf10b9064dee8d80f6bf6eeba8c1832 --- /dev/null +++ b/module/VuFind/src/VuFind/DoiLinker/PluginManager.php @@ -0,0 +1,69 @@ +<?php +/** + * DOI linker plugin manager + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\DoiLinker; + +/** + * DOI linker plugin manager + * + * @category VuFind + * @package DOI + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager +{ + /** + * Default plugin aliases. + * + * @var array + */ + protected $aliases = [ + 'browzine' => 'VuFind\DoiLinker\BrowZine', + ]; + + /** + * Default plugin factories. + * + * @var array + */ + protected $factories = [ + 'VuFind\DoiLinker\BrowZine' => 'VuFind\DoiLinker\BrowZineFactory', + ]; + + /** + * Return the name of the base class or interface that plug-ins must conform + * to. + * + * @return string + */ + protected function getExpectedInterface() + { + return 'VuFind\DoiLinker\DoiLinkerInterface'; + } +} diff --git a/module/VuFind/src/VuFind/Form/Form.php b/module/VuFind/src/VuFind/Form/Form.php new file mode 100644 index 0000000000000000000000000000000000000000..7da118a665772730fbd2ee36b2936df1a96aea24 --- /dev/null +++ b/module/VuFind/src/VuFind/Form/Form.php @@ -0,0 +1,633 @@ +<?php +/** + * Configurable form. + * + * PHP version 7 + * + * Copyright (C) The National Library of Finland 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind + * @package Form + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:controllers Wiki + */ +namespace VuFind\Form; + +use VuFind\Config\YamlReader; +use Zend\InputFilter\InputFilter; +use Zend\Validator\EmailAddress; +use Zend\Validator\NotEmpty; + +/** + * Configurable form. + * + * @category VuFind + * @package Form + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:controllers Wiki + */ +class Form extends \Zend\Form\Form implements + \VuFind\I18n\Translator\TranslatorAwareInterface +{ + use \VuFind\I18n\Translator\TranslatorAwareTrait; + + /** + * Input filter + * + * @var InputFilter + */ + protected $inputFilter; + + /** + * Validation messages + * + * @var array + */ + protected $messages; + + /** + * Default form config (from config.ini > Feedback) + * + * @var array + */ + protected $defaultFormConfig; + + /** + * Form config + * + * @var array + */ + protected $formElementConfig = []; + + /** + * Form config + * + * @var array + */ + protected $formConfig; + + /** + * YAML reader + * + * @var YamlReader + */ + protected $yamlReader; + + /** + * Constructor + * + * @param YamlReader $yamlReader YAML reader + * @param array $defaultConfig Default Feedback configuration (optional) + * + * @throws \Exception + */ + public function __construct(YamlReader $yamlReader, array $defaultConfig = null) + { + parent::__construct(); + + $this->defaultFormConfig = $defaultConfig; + $this->yamlReader = $yamlReader; + } + + /** + * Set form id + * + * @param string $formId Form id + * + * @return void + * @throws Exception + */ + public function setFormId($formId) + { + if (!$config = $this->getFormConfig($formId)) { + throw new \VuFind\Exception\RecordMissing("Form '$formId' not found"); + } + + $this->messages = []; + $this->messages['empty'] + = $this->translate('This field is required'); + + $this->messages['invalid_email'] + = $this->translate('Email address is invalid'); + + $this->formElementConfig + = $this->parseConfig($formId, $config); + + $this->buildForm($this->formElementConfig); + } + + /** + * Get form configuration + * + * @param string $formId Form id + * + * @return mixed null|array + * @throws Exception + */ + protected function getFormConfig($formId = null) + { + $confName = 'FeedbackForms.yaml'; + $localConfig = $parentConfig = $config = null; + + $config = $this->yamlReader->get($confName, false, true); + $localConfig = $this->yamlReader->get($confName, true, true); + + if (!$formId) { + $formId = $localConfig['default'] ?? $config['default'] ?? null; + if (!$formId) { + return null; + } + } + + $config = $config['forms'][$formId] ?? null; + $localConfig = $localConfig['forms'][$formId] ?? null; + + return $this->mergeLocalConfig($config, $localConfig); + } + + /** + * Merge local configuration into default configuration. + * + * @param array $config Default configuration + * @param array $localConfig Local configuration + * + * @return array + */ + protected function mergeLocalConfig($config, $localConfig) + { + return $localConfig ?? $config; + } + + /** + * Parse form configuration. + * + * @param string $formId Form id + * @param array $config Configuration + * + * @return array + */ + protected function parseConfig($formId, $config) + { + $formConfig = [ + 'id' => $formId, + 'title' => !empty($config['name']) ?: $formId + ]; + + foreach ($this->getFormSettingFields() as $key) { + if (isset($config[$key])) { + $formConfig[$key] = $config[$key]; + } + } + + $this->formConfig = $formConfig; + + $elements = []; + $configuredElements = $this->getFormElements($config); + + // Add sender contact name & email fields + $senderName = [ + 'name' => 'name', 'type' => 'text', 'label' => 'feedback_name', + 'group' => '__sender__' + ]; + $senderEmail = [ + 'name' => 'email', 'type' => 'email', 'label' => 'feedback_email', + 'group' => '__sender__' + ]; + if ($formConfig['senderInfoRequired'] ?? false) { + $senderEmail['required'] = $senderEmail['aria-required'] + = $senderName['required'] = $senderName['aria-required'] = true; + } + + $configuredElements[] = $senderName; + $configuredElements[] = $senderEmail; + + foreach ($configuredElements as $el) { + $element = []; + + $required = ['type', 'name']; + $optional = ['required', 'help','value', 'inputType', 'group']; + foreach (array_merge($required, $optional) as $field + ) { + if (!isset($el[$field])) { + continue; + } + $value = $el[$field]; + $element[$field] = $value; + } + $element['label'] = $this->translate($el['label']); + + $elementType = $element['type']; + if ($elementType === 'select') { + if (empty($el['options']) && empty($el['optionGroups'])) { + continue; + } + if (isset($el['options'])) { + $options = []; + foreach ($el['options'] as $option) { + $options[$option] = $this->translate($option); + } + $element['options'] = $options; + } elseif (isset($el['optionGroups'])) { + $groups = []; + foreach ($el['optionGroups'] as $group) { + if (empty($group['options'])) { + continue; + } + $options = []; + foreach ($group['options'] as $option) { + $options[$option] = $this->translate($option); + } + $label = $this->translate($group['label']); + $groups[$label] = ['label' => $label, 'options' => $options]; + } + $element['optionGroups'] = $groups; + } + } + + $settings = []; + if (isset($el['settings'])) { + foreach ($el['settings'] as list($settingId, $settingVal)) { + $settings[trim($settingId)] = trim($settingVal); + } + $element['settings'] = $settings; + } + + if (in_array($elementType, ['text', 'url', 'email']) + && !isset($element['settings']['size']) + ) { + $element['settings']['size'] = 50; + } + + if ($elementType == 'textarea') { + if (!isset($element['settings']['cols'])) { + $element['settings']['cols'] = 50; + } + if (!isset($element['settings']['rows'])) { + $element['settings']['rows'] = 8; + } + } + $elements[] = $element; + } + + $elements[]= [ + 'type' => 'submit', + 'name' => 'submit', + 'label' => $this->translate('Send') + ]; + + return $elements; + } + + /** + * Return a list of field names to read from settings file. + * + * @return array + */ + protected function getFormSettingFields() + { + return [ + 'recipient', 'title', 'help', 'submit', 'response', 'useCaptcha', + 'enabled', 'onlyForLoggedUsers', 'emailSubject', 'senderInfoRequired' + ]; + } + + /** + * Build form. + * + * @param array $elements Parsed configuration elements + * + * @return void + */ + protected function buildForm($elements) + { + foreach ($elements as $el) { + if ($element = $this->getFormElement($el)) { + $this->add($element); + } + } + } + + /** + * Get form element attributes. + * + * @param array $el Element configuration + * + * @return array + */ + protected function getFormElement($el) + { + $type = $el['type']; + if (!$class = $this->getFormElementClass($type)) { + return null; + } + + $conf = []; + $conf['name'] = $el['name']; + + $conf['type'] = $class; + $conf['options'] = []; + + $attributes = $el['settings'] ?? []; + + $attributes = [ + 'id' => $el['name'], + 'class' => [$el['settings']['class'] ?? null] + ]; + + if ($type !== 'submit') { + $attributes['class'][] = 'form-control'; + } + + if (!empty($el['required'])) { + $attributes['required'] = true; + $attributes['aria-required'] = "true"; + } elseif ($type !== 'submit') { + $attributes['aria-required'] = "false"; + } + if (!empty($el['settings'])) { + $attributes += $el['settings']; + } + if (!empty($el['label'])) { + $attributes['aria-label'] = $el['label']; + } + + switch ($type) { + case 'select': + if (isset($el['options'])) { + $conf['options'] = ['value_options' => $el['options']]; + } elseif (isset($el['optionGroups'])) { + $conf['options'] = ['value_options' => $el['optionGroups']]; + } + break; + case 'submit': + $attributes['value'] = $el['label']; + $attributes['class'][] = 'btn'; + $attributes['class'][] = 'btn-primary'; + break; + } + + $attributes['class'] = trim(implode(' ', $attributes['class'])); + $conf['attributes'] = $attributes; + + return $conf; + } + + /** + * Get form element class. + * + * @param string $type Element type + * + * @return string|null + */ + protected function getFormElementClass($type) + { + $map = [ + 'text' => '\Zend\Form\Element\Text', + 'url' => '\Zend\Form\Element\Url', + 'email' => '\Zend\Form\Element\Email', + 'textarea' => '\Zend\Form\Element\Textarea', + 'select' => '\Zend\Form\Element\Select', + 'submit' => '\Zend\Form\Element\Submit' + ]; + + return $map[$type] ?? null; + } + + /** + * Check if form enabled. + * + * @return bool + */ + public function isEnabled() + { + // Enabled unless explicitly disabled + return ($this->formConfig['enabled'] ?? true) === true; + } + + /** + * Check if the form should use Captcha validation (if supported) + * + * @return bool + */ + public function useCaptcha() + { + return (bool)($this->formConfig['useCaptcha'] ?? true); + } + + /** + * Check if form is available only for logged users. + * + * @return bool + */ + public function showOnlyForLoggedUsers() + { + return !empty($this->formConfig['onlyForLoggedUsers']); + } + + /** + * Return form element configuration. + * + * @return array + */ + public function getElements() + { + return $this->formElementConfig; + } + + /** + * Return form recipient. + * + * @return array with name, email or null if not configured + */ + public function getRecipient() + { + $recipient = $this->formConfig['recipient'] ?? null; + + $recipientEmail = $recipient['email'] + ?? $this->defaultFormConfig['recipient_email'] ?? null; + + $recipientName = $recipient['name'] + ?? $this->defaultFormConfig['recipient_name'] ?? null; + + return [ + $recipientName, + $recipientEmail, + ]; + } + + /** + * Return form title. + * + * @return string + */ + public function getTitle() + { + return $this->formConfig['title'] ?? null; + } + + /** + * Return form help text. + * + * @return string|null + */ + public function getHelp() + { + return $this->formConfig['help'] ?? null; + } + + /** + * Return form email message subject. + * + * @param array $postParams Posted form data + * + * @return string + */ + public function getEmailSubject($postParams) + { + $subject = 'VuFind Feedback'; + + if (!empty($this->formConfig['emailSubject'])) { + $subject = $this->formConfig['emailSubject']; + } elseif (!empty($this->defaultFormConfig['email_subject'])) { + $subject = $this->defaultFormConfig['email_subject']; + } + + $translated = []; + foreach ($postParams as $key => $val) { + $translated["%%{$key}%%"] = $this->translate($val); + } + + return str_replace( + array_keys($translated), array_values($translated), $subject + ); + } + + /** + * Return reponse that is shown after successful form submit. + * + * @return string + */ + public function getSubmitResponse() + { + return !empty($this->formConfig['response']) + ? $this->formConfig['response'] + : 'Thank you for your feedback.'; + } + + /** + * Format email message. + * + * @param array $requestParams Request parameters + * + * @return array Array with template parameters and template name. + */ + public function formatEmailMessage(array $requestParams = []) + { + $params = []; + foreach ($this->getElements() as $el) { + $type = $el['type']; + $name = $el['name']; + if ($type === 'submit') { + continue; + } + $value = $requestParams[$el['name']] ?? null; + + if ($type === 'select') { + $value = $this->translate($value); + } + + $label = $this->translate($el['label']); + + $params[$label] = ['type' => $type, 'value' => $value]; + } + + return [$params, 'Email/form.phtml']; + } + + /** + * Retrieve input filter used by this form + * + * @return \Zend\InputFilter\InputFilterInterface + */ + public function getInputFilter() + { + if ($this->inputFilter) { + return $this->inputFilter; + } + + $inputFilter = new InputFilter(); + + $validators = [ + 'email' => [ + 'name' => EmailAddress::class, + 'options' => [ + 'message' => $this->messages['invalid_email'] + ] + ], + 'notEmpty' => [ + 'name' => NotEmpty::class, + 'options' => [ + 'message' => [ + NotEmpty::IS_EMPTY => $this->messages['empty'] + ] + ] + ] + ]; + + foreach ($this->getElements() as $el) { + $required = ($el['required'] ?? false) === true; + $fieldValidators = []; + if ($required) { + $fieldValidators[] = $validators['notEmpty']; + } + if ($el['type'] === 'email') { + $fieldValidators[] = $validators['email']; + } + + $inputFilter->add( + [ + 'name' => $el['name'], + 'required' => $required, + 'validators' => $fieldValidators + ] + ); + } + + $this->inputFilter = $inputFilter; + return $this->inputFilter; + } + + /** + * Get form elements + * + * @param array $config Form configuration + * + * @return array + */ + protected function getFormElements($config) + { + $elements = []; + foreach ($config['fields'] as $field) { + if (!isset($field['type'])) { + continue; + } + $elements[] = $field; + } + return $elements; + } +} diff --git a/module/VuFind/src/VuFind/Form/FormFactory.php b/module/VuFind/src/VuFind/Form/FormFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..f50cad21a09c7c76c685b9d556cb7212cd3e3ad1 --- /dev/null +++ b/module/VuFind/src/VuFind/Form/FormFactory.php @@ -0,0 +1,73 @@ +<?php +/** + * Factory for configurable forms. + * + * PHP version 7 + * + * Copyright (C) The National Library of Finland 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Config + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\Form; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * Factory for configurable forms. + * + * @category VuFind + * @package Config + * @author Samuli Sillanpää <samuli.sillanpaa@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class FormFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + + $config = $container->get('VuFind\Config\PluginManager') + ->get('config')->toArray(); + $yamlReader = $container->get('VuFind\Config\YamlReader'); + + return new $requestedName( + $yamlReader, $config['Feedback'] ?? null + ); + } +} diff --git a/module/VuFind/src/VuFind/GeoFeatures/MapTabConfig.php b/module/VuFind/src/VuFind/GeoFeatures/MapTabConfig.php index ab4b93f7c3fcd4875ed7c279706f57100f1f9a2f..f83ba6c9db92fc273e1b4b7b6cc42ee392ec9421 100644 --- a/module/VuFind/src/VuFind/GeoFeatures/MapTabConfig.php +++ b/module/VuFind/src/VuFind/GeoFeatures/MapTabConfig.php @@ -46,10 +46,10 @@ class MapTabConfig extends AbstractConfig protected function getDefaultOptions() { return [ - 'recordMap' => 'false', - 'displayCoords' => 'false', + 'recordMap' => false, + 'displayCoords' => false, 'mapLabels' => null, - 'graticule' => 'false' + 'graticule' => false ]; } diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php index d51686756fbd59189963e2ef656c7705c26cf506..c1fb104367c8cab650f04a9ebef94495003e6aba 100644 --- a/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php +++ b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php @@ -251,7 +251,7 @@ class JSTree extends AbstractBase ]; $cache[$route] = $this->router->fromRoute($route, $params, $options); } - return str_replace('__record_id__', $id, $cache[$route]); + return str_replace('__record_id__', urlencode($id), $cache[$route]); } /** diff --git a/module/VuFind/src/VuFind/ILS/Connection.php b/module/VuFind/src/VuFind/ILS/Connection.php index a121275de8b1e5e1f8e47960d26c84e03c839042..db0de12f09c386e9b064f174f35ecdec33071ac2 100644 --- a/module/VuFind/src/VuFind/ILS/Connection.php +++ b/module/VuFind/src/VuFind/ILS/Connection.php @@ -612,6 +612,29 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface return false; } + /** + * Check Current Loans + * + * A support method for checkFunction(). This is responsible for checking + * the driver configuration to determine if the system supports current + * loans. + * + * @param array $functionConfig Function configuration + * @param array $params Patron data + * + * @return mixed On success, an associative array with specific function keys + * and values; on failure, false. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function checkMethodgetMyTransactions($functionConfig, $params) + { + if ($this->checkCapability('getMyTransactions', [$params ?: []])) { + return $functionConfig; + } + return false; + } + /** * Check Historic Loans * @@ -924,6 +947,32 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface : false; } + /** + * Get Patron Transactions + * + * This is responsible for retrieving all transactions (i.e. checked out items) + * by a specific patron. + * + * @param array $patron The patron array from patronLogin + * @param array $params Parameters + * + * @return mixed Array of the patron's transactions + */ + public function getMyTransactions($patron, $params = []) + { + $result = $this->__call('getMyTransactions', [$patron, $params]); + + // Support also older driver return value: + if (!isset($result['count'])) { + $result = [ + 'count' => count($result), + 'records' => $result + ]; + } + + return $result; + } + /** * Default method -- pass along calls to the driver if available; return * false otherwise. This allows custom functions to be implemented in diff --git a/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php b/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php new file mode 100644 index 0000000000000000000000000000000000000000..65811acf2c97cc35da63fc7c1f5d7b1d7caa8c05 --- /dev/null +++ b/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php @@ -0,0 +1,134 @@ +<?php +/** + * Abstract Driver for API-based ILS drivers + * + * PHP version 5 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind + * @package ILS_Drivers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +namespace VuFind\ILS\Driver; + +use VuFind\Exception\BadRequest as BadRequest; +use VuFind\Exception\Forbidden as Forbidden; +use VuFind\Exception\ILS as ILSException; +use VuFind\Exception\RecordMissing as RecordMissing; +use VuFindHttp\HttpServiceAwareInterface; +use Zend\Log\LoggerAwareInterface; + +/** + * Abstract Driver for API-based ILS drivers + * + * @category VuFind + * @package ILS_Drivers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +abstract class AbstractAPI extends AbstractBase implements HttpServiceAwareInterface, + LoggerAwareInterface +{ + use \VuFind\Log\LoggerAwareTrait { + logError as error; + } + use \VuFindHttp\HttpServiceAwareTrait; + + /** + * Allow default corrections to all requests + * + * @param \Zend\Http\Headers $headers the request headers + * @param array $params the parameters object + * + * @return array + */ + protected function preRequest(\Zend\Http\Headers $headers, $params) + { + return [$headers, $params]; + } + + /** + * Make requests + * + * @param string $method GET/POST/PUT/DELETE/etc + * @param string $path API path (with a leading /) + * @param array $params Parameters object to be sent as data + * @param array $headers Additional headers + * + * @return \Zend\Http\Response + */ + public function makeRequest($method = "GET", $path = "/", $params = [], + $headers = [] + ) { + $client = $this->httpService->createClient( + $this->config['API']['base_url'] . $path, + $method, + 120 + ); + // error_log($method . ' ' . $this->config['API']['base_url'] . $path); + + // Add default headers and parameters + $req_headers = $client->getRequest()->getHeaders(); + $req_headers->addHeaders($headers); + list($req_headers, $params) = $this->preRequest($req_headers, $params); + + // Add params + if ($method == 'GET') { + $client->setParameterGet($params); + } else { + if (is_string($params)) { + $client->getRequest()->setContent($params); + } else { + $client->setParameterPost($params); + } + } + $response = $client->send(); + switch ($response->getStatusCode()) { + case 400: + throw new BadRequest($response->getBody()); + case 401: + case 403: + throw new Forbidden($response->getBody()); + case 404: + throw new RecordMissing($response->getBody()); + case 500: + throw new ILSException("500: Internal Server Error"); + } + return $response; + } + + /** + * Set the configuration for the driver. + * + * @param array $config Configuration array (usually loaded from a VuFind .ini + * file whose name corresponds with the driver class name). + * + * @throws ILSException if base url excluded + * @return void + */ + public function setConfig($config) + { + parent::setConfig($config); + // Base URL required for API drivers + if (!isset($config['API']['base_url'])) { + throw new ILSException('API Driver configured without base url.'); + } + } +} diff --git a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php index 527c3792e982794e983b06bf4083c35ec0d8a3a1..681fa50488a0b8cf5e72c03c30bf4071a78d0d98 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php @@ -318,7 +318,7 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, * * @var AlephTranslator */ - protected $translator = false; + protected $alephTranslator = false; /** * Cache manager @@ -334,6 +334,13 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, */ protected $dateConverter = null; + /** + * The base URL, where the REST DLF API is running + * + * @var string + */ + protected $dlfbaseurl = null; + /** * Constructor * @@ -388,6 +395,9 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, $this->xserver_enabled = false; } $this->dlfport = $this->config['Catalog']['dlfport']; + if (isset($this->config['Catalog']['dlfbaseurl'])) { + $this->dlfbaseurl = $this->config['Catalog']['dlfbaseurl']; + } $this->sublibadm = $this->config['sublibadm']; if (isset($this->config['duedates'])) { $this->duedates = $this->config['duedates']; @@ -408,12 +418,12 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, ) { $cache = $this->cacheManager ->getCache($this->config['Cache']['type']); - $this->translator = $cache->getItem('alephTranslator'); + $this->alephTranslator = $cache->getItem('alephTranslator'); } - if ($this->translator == false) { - $this->translator = new AlephTranslator($this->config); + if ($this->alephTranslator == false) { + $this->alephTranslator = new AlephTranslator($this->config); if (isset($cache)) { - $cache->setItem('alephTranslator', $this->translator); + $cache->setItem('alephTranslator', $this->alephTranslator); } } } @@ -479,11 +489,12 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, protected function doRestDLFRequest($path_elements, $params = null, $method = 'GET', $body = null ) { - $path = ''; - foreach ($path_elements as $path_element) { - $path .= $path_element . "/"; + $path = implode('/', $path_elements); + if ($this->dlfbaseurl === null) { + $url = "http://$this->host:$this->dlfport/rest-dlf/" . $path; + } else { + $url = $this->dlfbaseurl . $path; } - $url = "http://$this->host:$this->dlfport/rest-dlf/" . $path; $url = $this->appendQueryString($url, $params); $result = $this->doHTTPRequest($url, $method, $body); $replyCode = (string)$result->{'reply-code'}; @@ -578,10 +589,17 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, protected function parseId($id) { if (count($this->bib) == 1) { - return [$this->bib[0], $id]; + $retval = [$this->bib[0], $id]; } else { - return explode('-', $id); + $retval = explode('-', $id); + } + if (count($retval) != 2) { + throw new \Exception("The resulting array has incorrect size"); } + if (!in_array($retval[0], $this->bib)) { + throw new \Exception("The resulting array contains unknown library ID"); + } + return $retval; } /** @@ -737,14 +755,19 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, $params['patron'] = $this->defaultPatronId; } $xml = $this->doRestDLFRequest(['record', $resource, 'items'], $params); - foreach ($xml->{'items'}->{'item'} as $item) { + if (!empty($xml->{'items'})) { + $items = $xml->{'items'}->{'item'}; + } else { + $items = []; + } + foreach ($items as $item) { $item_status = (string)$item->{'z30-item-status-code'}; // $isc // $ipsc: $item_process_status = (string)$item->{'z30-item-process-status-code'}; $sub_library_code = (string)$item->{'z30-sub-library-code'}; // $slc $z30 = $item->z30; - if ($this->translator) { - $item_status = $this->translator->tab15Translate( + if ($this->alephTranslator) { + $item_status = $this->alephTranslator->tab15Translate( $sub_library_code, $item_status, $item_process_status ); } else { @@ -762,9 +785,9 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, //$reserve = ($item_status['request'] == 'C')?'N':'Y'; $collection = (string)$z30->{'z30-collection'}; $collection_desc = ['desc' => $collection]; - if ($this->translator) { + if ($this->alephTranslator) { $collection_code = (string)$item->{'z30-collection-code'}; - $collection_desc = $this->translator->tab40Translate( + $collection_desc = $this->alephTranslator->tab40Translate( $collection_code, $sub_library_code ); } @@ -1031,7 +1054,7 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, * Renew My Items * * Function for attempting to renew a patron's items. The data in - * $renewDetails['details'] is determined by getRenewDetails(). + * $details['details'] is determined by getRenewDetails(). * * @param array $details An array of data required for renewing items * including the Patron ID and an array of renewal IDS @@ -1748,21 +1771,27 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface, */ public function getPickUpLocations($patron, $holdInfo = null) { + $pickupLocations = []; if ($holdInfo != null) { $details = $this->getHoldingInfoForItem( $patron['id'], $holdInfo['id'], $holdInfo['item_id'] ); - $pickupLocations = []; foreach ($details['pickup-locations'] as $key => $value) { $pickupLocations[] = [ - "locationID" => $key, "locationDisplay" => $value + "locationID" => $key, + "locationDisplay" => $value, ]; } - return $pickupLocations; } else { $default = $this->getDefaultPickUpLocation($patron); - return empty($default) ? [] : [$default]; + if (!empty($default)) { + $pickupLocations[] = [ + "locationID" => $default, + "locationDisplay" => $default, + ]; + } } + return $pickupLocations; } /** diff --git a/module/VuFind/src/VuFind/ILS/Driver/Alma.php b/module/VuFind/src/VuFind/ILS/Driver/Alma.php index 2e4c4a9e53ab5f6ad43f3b5205e0650ae3c6d50f..a662c471337dbc41e949b98192afda88c932c005 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Alma.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Alma.php @@ -806,7 +806,7 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface * * @return array Associative array containing with keys 'count' * (number of items successfully cancelled) and - * 'items' (array of successfull cancellations). + * 'items' (array of successful cancellations). */ public function cancelHolds($cancelDetails) { diff --git a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php index c66ef8702a19af76accd33369df3f1ad71351805..387986a68e6f5af76cc6656f2bc04f991bccc9b1 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php +++ b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php @@ -1061,7 +1061,7 @@ class DAIA extends AbstractBase implements } /** - * Helper function to determine the holdtype availble for current item. + * Helper function to determine the holdtype available for current item. * DAIA does not genuinly allow distinguishing between holdable and recallable * items. This could be achieved by usage of limitations but this would not be * shared functionality between different DAIA implementations (thus should be diff --git a/module/VuFind/src/VuFind/ILS/Driver/Demo.php b/module/VuFind/src/VuFind/ILS/Driver/Demo.php index eda909acabe9dc60e4f83f5af0971be9d2c6d24c..003e2757bb19709fe4a3cbe53922abaca9e9819f 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Demo.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Demo.php @@ -273,6 +273,17 @@ class Demo extends AbstractBase * @return string */ protected function getRandomBibId() + { + list($id) = $this->getRandomBibIdAndTitle(); + return $id; + } + + /** + * Get a random ID and title from the Solr index. + * + * @return array [id, title] + */ + protected function getRandomBibIdAndTitle() { $source = $this->getRecordSource(); $query = isset($this->config['Records']['query']) @@ -281,7 +292,8 @@ class Demo extends AbstractBase if (count($result) === 0) { throw new \Exception('Problem retrieving random record from $source.'); } - return current($result->getRecords())->getUniqueId(); + $record = current($result->getRecords()); + return [$record->getUniqueId(), $record->getTitle()]; } /** @@ -450,7 +462,8 @@ class Demo extends AbstractBase $currentItem['institution_dbkey'] = 'ill_institution'; } else { if ($this->idsInMyResearch) { - $currentItem['id'] = $this->getRandomBibId(); + list($currentItem['id'], $currentItem['title']) + = $this->getRandomBibIdAndtitle(); $currentItem['source'] = $this->getRecordSource(); } else { $currentItem['title'] = 'Demo Title ' . $i; @@ -463,6 +476,11 @@ class Demo extends AbstractBase $currentItem['position'] = $pos; } else { $currentItem['available'] = true; + if (rand() % 3 != 1) { + $lastDate = strtotime('now + 3 days'); + $currentItem['last_pickup_date'] = $this->dateConverter + ->convertToDisplayDate('U', $lastDate); + } } $pos = rand(0, count($requestGroups) - 1); $currentItem['requestGroup'] = $requestGroups[$pos]['name']; @@ -767,9 +785,10 @@ class Demo extends AbstractBase $fineList[] = [ "amount" => $fine * 100, - "checkout" => $this->dateConverter->convertToDisplayDate( - 'U', $checkout - ), + "checkout" => $this->dateConverter + ->convertToDisplayDate('U', $checkout), + 'createdate' => $this->dateConverter + ->convertToDisplayDate('U', time()), // After 20 days it becomes 'Long Overdue' "fine" => $day_overdue > 20 ? "Long Overdue" : "Overdue", // 50% chance they've paid half of it @@ -781,7 +800,8 @@ class Demo extends AbstractBase // Some fines will have no id or title: if (rand() % 3 != 1) { if ($this->idsInMyResearch) { - $fineList[$i]['id'] = $this->getRandomBibId(); + list($fineList[$i]['id'], $fineList[$i]['title']) + = $this->getRandomBibIdAndTitle(); $fineList[$i]['source'] = $this->getRecordSource(); } else { $fineList[$i]['title'] = 'Demo Title ' . $i; @@ -945,7 +965,8 @@ class Demo extends AbstractBase } else { $transList[$i]['borrowingLocation'] = $this->getFakeLoc(); if ($this->idsInMyResearch) { - $transList[$i]['id'] = $this->getRandomBibId(); + list($transList[$i]['id'], $transList[$i]['title']) + = $this->getRandomBibIdAndTitle(); $transList[$i]['source'] = $this->getRecordSource(); } else { $transList[$i]['title'] = 'Demo Title ' . $i; @@ -962,19 +983,51 @@ class Demo extends AbstractBase * by a specific patron. * * @param array $patron The patron array from patronLogin + * @param array $params Parameters * * @return mixed Array of the patron's transactions on success. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function getMyTransactions($patron) + public function getMyTransactions($patron, $params = []) { $this->checkIntermittentFailure(); $session = $this->getSession(); if (!isset($session->transactions)) { $session->transactions = $this->getTransactionList(); } - return $session->transactions; + // Order + $transactions = $session->transactions; + if (!empty($params['sort'])) { + $sort = explode( + ' ', !empty($params['sort']) ? $params['sort'] : 'date_due desc', 2 + ); + + $descending = isset($sort[1]) && 'desc' === $sort[1]; + + usort( + $transactions, + function ($a, $b) use ($sort, $descending) { + if ('title' === $sort[0]) { + $cmp = strcmp($a['title'] ?? '', $b['title'] ?? ''); + } else { + $cmp = $a['rawduedate'] - $b['rawduedate']; + } + return $descending ? -$cmp : $cmp; + } + ); + } + + if (isset($params['limit'])) { + $limit = $params['limit'] ?? 50; + $offset = isset($params['page']) ? ($params['page'] - 1) * $limit : 0; + $transactions = array_slice($transactions, $offset, $limit); + } + + return [ + 'count' => count($session->transactions), + 'records' => $transactions + ]; } /** @@ -1035,7 +1088,8 @@ class Demo extends AbstractBase 'item_id' => $i, ]; if ($this->idsInMyResearch) { - $transList[$i]['id'] = $this->getRandomBibId(); + list($transList[$i]['id'], $transList[$i]['title']) + = $this->getRandomBibIdAndTitle(); $transList[$i]['source'] = $this->getRecordSource(); } else { $transList[$i]['title'] = 'Demo Title ' . $i; @@ -2184,8 +2238,7 @@ class Demo extends AbstractBase if (empty($this->config['TransactionHistory']['enabled'])) { return false; } - return [ - 'max_results' => 100, + $config = [ 'sort' => [ 'checkout desc' => 'sort_checkout_date_desc', 'checkout asc' => 'sort_checkout_date_asc', @@ -2196,7 +2249,27 @@ class Demo extends AbstractBase ], 'default_sort' => 'checkout desc' ]; + if ($this->config['Loans']['paging'] ?? false) { + $config['max_results'] + = $this->config['Loans']['max_page_size'] ?? 100; + } + return $config; + } + if ('getMyTransactions' === $function) { + if (empty($this->config['Loans']['paging'])) { + return []; + } + return [ + 'max_results' => $this->config['Loans']['max_page_size'] ?? 100, + 'sort' => [ + 'due desc' => 'sort_due_date_desc', + 'due asc' => 'sort_due_date_asc', + 'title asc' => 'sort_title' + ], + 'default_sort' => 'due asc' + ]; } + return []; } diff --git a/module/VuFind/src/VuFind/ILS/Driver/Folio.php b/module/VuFind/src/VuFind/ILS/Driver/Folio.php new file mode 100644 index 0000000000000000000000000000000000000000..356334a88d88f2e14f04d2fe5fe4b18ba435caef --- /dev/null +++ b/module/VuFind/src/VuFind/ILS/Driver/Folio.php @@ -0,0 +1,803 @@ +<?php +/** + * FOLIO REST API driver + * + * PHP version 5 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind + * @package ILS_Drivers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +namespace VuFind\ILS\Driver; + +use VuFind\Exception\ILS as ILSException; +use VuFind\I18n\Translator\TranslatorAwareInterface; +use VuFindHttp\HttpServiceAwareInterface as HttpServiceAwareInterface; + +/** + * FOLIO REST API driver + * + * @category VuFind + * @package ILS_Drivers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +class Folio extends AbstractAPI implements + HttpServiceAwareInterface, TranslatorAwareInterface +{ + use \VuFindHttp\HttpServiceAwareTrait; + use \VuFind\I18n\Translator\TranslatorAwareTrait; + + /** + * Authentication tenant (X-Okapi-Tenant) + * + * @var string + */ + protected $tenant = null; + + /** + * Authentication token (X-Okapi-Token) + * + * @var string + */ + protected $token = null; + + /** + * Factory function for constructing the SessionContainer. + * + * @var Callable + */ + protected $sessionFactory; + + /** + * Session cache + * + * @var \Zend\Session\Container + */ + protected $sessionCache; + + /** + * Constructor + * + * @param \VuFind\Date\Converter $dateConverter Date converter object + * @param Callable $sessionFactory Factory function returning + * SessionContainer object + */ + public function __construct(\VuFind\Date\Converter $dateConverter, + $sessionFactory + ) { + $this->dateConverter = $dateConverter; + $this->sessionFactory = $sessionFactory; + } + + /** + * Set the configuration for the driver. + * + * @param array $config Configuration array (usually loaded from a VuFind .ini + * file whose name corresponds with the driver class name). + * + * @throws ILSException if base url excluded + * @return void + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->tenant = $this->config['API']['tenant']; + } + + /** + * (From AbstractAPI) Allow default corrections to all requests + * + * Add X-Okapi headers and Content-Type to every request + * + * @param \Zend\Http\Headers $headers the request headers + * @param object $params the parameters object + * + * @return array + */ + public function preRequest(\Zend\Http\Headers $headers, $params) + { + $headers->addHeaderLine('Accept', 'application/json'); + if (!$headers->has('Content-Type')) { + $headers->addHeaderLine('Content-Type', 'application/json'); + } + $headers->addHeaderLine('X-Okapi-Tenant', $this->tenant); + if ($this->token != null) { + $headers->addHeaderLine('X-Okapi-Token', $this->token); + } + return [$headers, $params]; + } + + /** + * Login and receive a new token + * + * @return void + */ + protected function renewTenantToken() + { + $this->token = null; + $auth = [ + 'username' => $this->config['API']['username'], + 'password' => $this->config['API']['password'], + ]; + $response = $this->makeRequest('POST', '/authn/login', json_encode($auth)); + if ($response->getStatusCode() >= 400) { + throw new ILSException($response->getBody()); + } + $this->token = $response->getHeaders()->get('X-Okapi-Token') + ->getFieldValue(); + $this->sessionCache->folio_token = $this->token; + } + + /** + * Check if our token is still valid + * + * Method taken from Stripes JS (loginServices.js:validateUser) + * + * @return void + */ + protected function checkTenantToken() + { + $response = $this->makeRequest('GET', '/users'); + if ($response->getStatusCode() >= 400) { + $this->token = null; + $this->renewTenantToken(); + } + } + + /** + * Initialize the driver. + * + * Check or renew our auth token + * + * @return void + */ + public function init() + { + $factory = $this->sessionFactory; + $this->sessionCache = $factory($this->tenant); + if ($this->sessionCache->folio_token ?? false) { + $this->token = $this->sessionCache->folio_token; + } + if ($this->token == null) { + $this->renewTenantToken(); + } else { + $this->checkTenantToken(); + } + } + + /** + * Get local bib id from inventory by following parents up the tree + * + * @param string $instanceId Instance-level id (lowest level) + * @param string $holdingId Holding-level id (looked up from instance if null) + * @param string $itemId Item-level id (looked up from holding if null) + * + * @return string Local bib id retrieved from Folio identifiers + */ + protected function getBibId($instanceId, $holdingId = null, $itemId = null) + { + if ($instanceId == null) { + if ($holdingId == null) { + $response = $this->makeRequest( + 'GET', + '/item-storage/items/' . $itemId + ); + $item = json_decode($response->getBody()); + $holdingId = $item->holdingsRecordId; + } + $response = $this->makeRequest( + 'GET', '/holdings-storage/holdings/' . $holdingId + ); + $holding = json_decode($response->getBody()); + $instanceId = $holding->instanceId; + } + $response = $this->makeRequest( + 'GET', '/inventory/instances/' . $instanceId + ); + $instance = json_decode($response->getBody()); + return $instance->identifiers[0]->value; + } + + /** + * Get raw object of item from inventory/items/ + * + * @param string $bibId Bib-level id + * + * @throw + * @return array + */ + protected function getInstance($bibId) + { + $escaped = str_replace('"', '\"', str_replace('&', '%26', $bibId)); + $query = [ + 'query' => '(id="' . $escaped . '" or identifiers="' . $escaped . '")' + ]; + $response = $this->makeRequest('GET', '/instance-storage/instances', $query); + $instances = json_decode($response->getBody()); + if (count($instances->instances) == 0) { + throw new ILSException("Item Not Found"); + } + return $instances->instances[0]; + } + + /** + * Get raw object of item from inventory/items/ + * + * @param string $itemId Item-level id + * + * @return array + */ + public function getStatus($itemId) + { + return $this->getHolding($itemId); + } + + /** + * This method calls getStatus for an array of records or implement a bulk method + * + * @param array $idList Item-level ids + * + * @return array values from getStatus + */ + public function getStatuses($idList) + { + $status = []; + foreach ($idList as $id) { + $status[] = $this->getStatus($id); + } + return $status; + } + + /** + * Retrieves renew, hold and cancel settings from the driver ini file. + * + * @param string $function The name of the feature to be checked + * @param array $params Optional feature-specific parameters (array) + * + * @return array An array with key-value pairs. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getConfig($function, $params = null) + { + return $this->config[$function] ?? false; + } + + /** + * This method queries the ILS for holding information. + * + * @param string $bibId Bib-level id + * @param array $patron Patron login information from $this->patronLogin + * + * @return array An array of associative holding arrays + */ + public function getHolding($bibId, array $patron = null) + { + $instance = $this->getInstance($bibId); + $query = ['query' => '(instanceId="' . $instance->id . '")']; + $holdingResponse = $this->makeRequest( + 'GET', + '/holdings-storage/holdings', + $query + ); + $holdingBody = json_decode($holdingResponse->getBody()); + $items = []; + for ($i = 0; $i < count($holdingBody->holdingsRecords); $i++) { + $holding = $holdingBody->holdingsRecords[$i]; + $locationName = ''; + if (!empty($holding->permanentLocationId)) { + $locationResponse = $this->makeRequest( + 'GET', + '/locations/' . $holding->permanentLocationId + ); + $location = json_decode($locationResponse->getBody()); + $locationName = $location->name; + } + + $query = ['query' => '(holdingsRecordId="' . $holding->id . '")']; + $itemResponse = $this->makeRequest('GET', '/item-storage/items', $query); + $itemBody = json_decode($itemResponse->getBody()); + for ($j = 0; $j < count($itemBody->items); $j++) { + $item = $itemBody->items[$j]; + $items[] = [ + 'id' => $bibId, + 'item_id' => $instance->id, + 'holding_id' => $holding->id, + 'number' => count($items), + 'barcode' => $item->barcode ?? '', + 'status' => $item->status->name, + 'availability' => $item->status->name == 'Available', + 'notes' => $item->notes ?? [], + 'callnumber' => $holding->callNumber, + 'location' => $locationName, + 'reserve' => 'TODO', + 'addLink' => true + ]; + } + } + return $items; + } + + /** + * Patron Login + * + * This is responsible for authenticating a patron against the catalog. + * + * @param string $username The patron username + * @param string $password The patron password + * + * @return mixed Associative array of patron info on successful login, + * null on unsuccessful login. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function patronLogin($username, $password) + { + // Get user id + $query = ['query' => 'username == ' . $username]; + $response = $this->makeRequest('GET', '/users', $query); + $json = json_decode($response->getBody()); + if (count($json->users) == 0) { + throw new ILSException("User not found"); + } + $profile = $json->users[0]; + $credentials = [ + 'userId' => $profile->id, + 'username' => $username, + 'password' => $password, + ]; + // Get token + try { + $response = $this->makeRequest( + 'POST', + '/authn/login', + json_encode($credentials) + ); + // Replace admin with user as tenant + $this->token = $response->getHeaders()->get('X-Okapi-Token') + ->getFieldValue(); + return [ + 'id' => $profile->id, + 'username' => $username, + 'cat_username' => $username, + 'cat_password' => $password, + 'firstname' => $profile->personal->firstName ?? null, + 'lastname' => $profile->personal->lastName ?? null, + 'email' => $profile->personal->email ?? null, + ]; + } catch (Exception $e) { + return null; + } + } + + /** + * This method queries the ILS for a patron's current profile information + * + * @param array $patron Patron login information from $this->patronLogin + * + * @return array Profile data in associative array + */ + public function getMyProfile($patron) + { + $query = ['query' => 'username == "' . $patron['username'] . '"']; + $response = $this->makeRequest('GET', '/users', $query); + $users = json_decode($response->getBody()); + $profile = $users->users[0]; + return [ + 'id' => $profile->id, + 'firstname' => $profile->personal->firstName ?? null, + 'lastname' => $profile->personal->lastName ?? null, + 'address1' => $profile->personal->addresses[0]->addressLine1 ?? null, + 'city' => $profile->personal->addresses[0]->city ?? null, + 'country' => $profile->personal->addresses[0]->countryId ?? null, + 'zip' => $profile->personal->addresses[0]->postalCode ?? null, + 'phone' => $profile->personal->phone ?? null, + 'mobile_phone' => $profile->personal->mobilePhone ?? null, + 'expiration_date' => $profile->expirationDate ?? null, + ]; + } + + /** + * This method queries the ILS for a patron's current checked out items + * + * Input: Patron array returned by patronLogin method + * Output: Returns an array of associative arrays. + * Each associative array contains these keys: + * duedate - The item's due date (a string). + * dueTime - The item's due time (a string, optional). + * dueStatus - A special status – may be 'due' (for items due very soon) + * or 'overdue' (for overdue items). (optional). + * id - The bibliographic ID of the checked out item. + * source - The search backend from which the record may be retrieved + * (optional - defaults to Solr). Introduced in VuFind 2.4. + * barcode - The barcode of the item (optional). + * renew - The number of times the item has been renewed (optional). + * renewLimit - The maximum number of renewals allowed + * (optional - introduced in VuFind 2.3). + * request - The number of pending requests for the item (optional). + * volume – The volume number of the item (optional). + * publication_year – The publication year of the item (optional). + * renewable – Whether or not an item is renewable + * (required for renewals). + * message – A message regarding the item (optional). + * title - The title of the item (optional – only used if the record + * cannot be found in VuFind's index). + * item_id - this is used to match up renew responses and must match + * the item_id in the renew response. + * institution_name - Display name of the institution that owns the item. + * isbn - An ISBN for use in cover image loading + * (optional – introduced in release 2.3) + * issn - An ISSN for use in cover image loading + * (optional – introduced in release 2.3) + * oclc - An OCLC number for use in cover image loading + * (optional – introduced in release 2.3) + * upc - A UPC for use in cover image loading + * (optional – introduced in release 2.3) + * borrowingLocation - A string describing the location where the item + * was checked out (optional – introduced in release 2.4) + * + * @param array $patron Patron login information from $this->patronLogin + * + * @return array Transactions associative arrays + */ + public function getMyTransactions($patron) + { + $query = ['query' => 'userId==' . $patron['username']]; + $response = $this->makeRequest("GET", '/circulation/loans', $query); + $json = json_decode($response->getBody()); + if (count($json->loans) == 0) { + return []; + } + $transactions = []; + foreach ($json->loans as $trans) { + $dueDate = date_create($trans['dueDate']); + $transactions[] = [ + 'duedate' => date_format($date, "j M Y"), + 'dueTime' => date_format($date, "g:i:s a"), + // TODO: Due Status + // 'dueStatus' => $trans['itemId'], + 'id' => $trans['itemId'], + 'barcode' => $trans['item']['barcode'], + 'title' => $trans['item']['title'], + ]; + } + return $transactions; + } + + /** + * Get Pick Up Locations + * + * This is responsible get a list of valid locations for holds / recall + * retrieval + * + * @param array $patron Patron information returned by $this->patronLogin + * + * @return array An array of associative arrays with locationID and + * locationDisplay keys + */ + public function getPickupLocations($patron) + { + $response = $this->makeRequest('GET', '/locations'); + $json = json_decode($response->getBody()); + $locations = []; + foreach ($json->locations as $location) { + $locations[] = [ + 'locationID' => $location->id, + 'locationDisplay' => $location->name + ]; + } + return $locations; + } + + /** + * This method queries the ILS for a patron's current holds + * + * Input: Patron array returned by patronLogin method + * Output: Returns an array of associative arrays, one for each hold associated + * with the specified account. Each associative array contains these keys: + * type - A string describing the type of hold – i.e. hold vs. recall + * (optional). + * id - The bibliographic record ID associated with the hold (optional). + * source - The search backend from which the record may be retrieved + * (optional - defaults to Solr). Introduced in VuFind 2.4. + * location - A string describing the pickup location for the held item + * (optional). In VuFind 1.2, this should correspond with a locationID value from + * getPickUpLocations. In VuFind 1.3 and later, it may be either + * a locationID value or a raw ready-to-display string. + * reqnum - A control number for the request (optional). + * expire - The expiration date of the hold (a string). + * create - The creation date of the hold (a string). + * position – The position of the user in the holds queue (optional) + * available – Whether or not the hold is available (true/false) (optional) + * item_id – The item id the request item (optional). + * volume – The volume number of the item (optional) + * publication_year – The publication year of the item (optional) + * title - The title of the item + * (optional – only used if the record cannot be found in VuFind's index). + * isbn - An ISBN for use in cover image loading (optional) + * issn - An ISSN for use in cover image loading (optional) + * oclc - An OCLC number for use in cover image loading (optional) + * upc - A UPC for use in cover image loading (optional) + * cancel_details - The cancel token, or a blank string if cancel is illegal + * for this hold; if omitted, this will be dynamically generated using + * getCancelHoldDetails(). You should only fill this in if it is more efficient + * to calculate the value up front; if it is an expensive calculation, you should + * omit the value entirely and let getCancelHoldDetails() do its job on demand. + * This optional feature was introduced in release 3.1. + * + * @param array $patron Patron login information from $this->patronLogin + * + * @return array Associative array of holds information + */ + public function getMyHolds($patron) + { + // Get user id + $query = ['query' => 'username == "' . $patron['username'] . '"']; + $response = $this->makeRequest('GET', '/users', $query); + $users = json_decode($response->getBody()); + $query = [ + 'query' => 'requesterId == "' . $users->users[0]->id . '"' . + ' and requestType == "Hold"' + ]; + // Request HOLDS + $response = $this->makeRequest('GET', '/request-storage/requests', $query); + $json = json_decode($response->getBody()); + $holds = []; + foreach ($json->requests as $hold) { + $holds[] = [ + 'type' => 'Hold', + 'create' => $hold->requestDate, + 'expire' => $hold->requestExpirationDate, + 'id' => $this->getBibId(null, null, $hold->itemId), + ]; + } + return $holds; + } + + /** + * Place Hold + * + * Attempts to place a hold or recall on a particular item and returns + * an array with result details. + * + * @param array $holdDetails An array of item and patron data + * + * @return mixed An array of data on the request including + * whether or not it was successful and a system message (if available) + */ + public function placeHold($holdDetails) + { + try { + $requiredBy = date_create_from_format( + 'm-d-Y', + $holdDetails['requiredBy'] + ); + } catch (Exception $e) { + throw new ILSException('hold_date_invalid'); + } + // Get status to separate Holds (on checked out items) and Pages on a + $status = $this->getStatus($holdDetails['item_id']); + $requestBody = [ + 'requestType' => $item->status->name == 'Available' ? 'Page' : 'Hold', + 'requestDate' => date('c'), + 'requesterId' => $holdDetails['patron']['id'], + 'requester' => [ + 'firstName' => $holdDetails['patron']['firstname'] ?? '', + 'lastName' => $holdDetails['patron']['lastname'] ?? '' + ], + 'itemId' => $holdDetails['item_id'], + 'fulfilmentPreference' => 'Hold Shelf', + 'requestExpirationDate' => date_format($requiredBy, 'Y-m-d'), + ]; + $response = $this->makeRequest( + 'POST', + '/request-storage/requests', + json_encode($requestBody) + ); + if ($response->isSuccess()) { + return [ + 'success' => true, + 'status' => $response->getBody() + ]; + } else { + throw new ILSException($response->getBody()); + } + } + + // @codingStandardsIgnoreStart + /** NOT FINISHED BELOW THIS LINE **/ + + /** + * Check for request blocks. + * + * @param array $patron The patron array with username and password + * + * @return array|boolean An array of block messages or false if there are no + * blocks + * @author Michael Birkner + */ + public function getRequestBlocks($patron) + { + return false; + } + + /** + * This method returns information on recently received issues of a serial. + * + * Input: Bibliographic record ID + * Output: Array of associative arrays, each with a single key: + * issue - String describing the issue + * + * Currently, most drivers do not implement this method, instead always returning + * an empty array. It is only necessary to implement this in more detail if you + * want to populate the “Most Recent Received Issues†section of the record + * holdings tab. + */ + public function getPurchaseHistory($bibID) + { + return []; + } + + /** + * This method returns items that are on reserve for the specified course, + * instructor and/or department. + * + * Input: CourseID, InstructorID, DepartmentID (these values come from the + * corresponding getCourses, getInstructors and getDepartments methods; any of + * these three filters may be set to a blank string to skip) + * Output: An array of associative arrays representing reserve items. Keys: + * BIB_ID - The record ID of the current reserve item. + * COURSE_ID - The course ID associated with the + * current reserve item, if any (required when using Solr-based reserves). + * DEPARTMENT_ID - The department ID associated with the current + * reserve item, if any (required when using Solr-based reserves). + * INSTRUCTOR_ID - The instructor ID associated with the current + * reserve item, if any (required when using Solr-based reserves). + * + */ + public function findReserves($courseID, $instructorID, $departmentID) + { + } + + /** + * This method queries the ILS for a patron's current fines + * + * Input: Patron array returned by patronLogin method + * Output: Returns an array of associative arrays, one for each fine + * associated with the specified account. Each associative array contains + * these keys: + * amount - The total amount of the fine IN PENNIES. Be sure to adjust + * decimal points appropriately (i.e. for a $1.00 fine, amount should be 100). + * checkout - A string representing the date when the item was + * checked out. + * fine - A string describing the reason for the fine + * (i.e. “Overdueâ€, “Long Overdueâ€). + * balance - The unpaid portion of the fine IN PENNIES. + * createdate – A string representing the date when the fine was accrued + * (optional) + * duedate - A string representing the date when the item was due. + * id - The bibliographic ID of the record involved in the fine. + * source - The search backend from which the record may be retrieved + * (optional - defaults to Solr). Introduced in VuFind 2.4. + * + */ + public function getMyFines($patron) + { + return []; + } + + /** + * Get a list of funds that can be used to limit the “new item†search. Note that + * “fund†may be a misnomer – if funds are not an appropriate way to limit your + * new item results, you can return a different set of values from this function. + * For example, you might just make this a wrapper for getDepartments(). The + * important thing is that whatever you return from this function, the IDs can be + * used as a limiter to the getNewItems() function, and the names are appropriate + * for display on the new item search screen. If you do not want or support such + * limits, just return an empty array here and the limit control on the new item + * search screen will disappear. + * + * Output: An associative array with key = fund ID, value = fund name. + * + * IMPORTANT: The return value for this method changed in r2184. If you are using + * VuFind 1.0RC2 or earlier, this function returns a flat array of options + * (no ID-based keys), and empty return values may cause problems. It is + * recommended that you update to newer code before implementing the new item + * feature in your driver. + */ + public function getFunds() + { + return []; + } + + /** + * This method retrieves a patron's historic transactions + * (previously checked out items). + * + * :!: The getConfig method must return a non-false value for this feature to be + * enabled. For privacy reasons, the entire feature should be disabled by default + * unless explicitly turned on in the driver's .ini file. + * + * This feature was added in VuFind 5.0. + * + * getConfig may return the following keys if the service supports paging on + * the ILS side: + * max_results - Maximum number of results that can be requested at once. + * Overrides the config.ini Catalog section setting historic_loan_page_size. + * page_size - An array of allowed page sizes + * (number of records per page) + * default_page_size - Default number of records per page + * getConfig may return the following keys if the service supports sorting: + * sort - An associative array where each key is a sort key and its + * value is a translation key + * default_sort - Default sort key + * Input: Patron array returned by patronLogin method and an array of + * optional parameters (keys = 'limit', 'page', 'sort'). + * Output: Returns an array of associative arrays containing some or all of + * these keys: + * title - item title + * checkoutDate - date checked out + * dueDate - date due + * id - bibliographic ID + * barcode - item barcode + * returnDate - date returned + * publication_year - publication year + * volume - item volume + * institution_name - owning institution + * borrowingLocation - checkout location + * message - message about the transaction + * + */ + public function getMyTransactionHistory($patron) + { + return[]; + } + + /** + * This method queries the ILS for new items + * + * Input: getNewItems takes the following parameters: + * page - page number of results to retrieve (counting starts at 1) + * limit - the size of each page of results to retrieve + * daysOld - the maximum age of records to retrieve in days (maximum 30) + * fundID - optional fund ID to use for limiting results (use a value + * returned by getFunds, or exclude for no limit); note that “fund†may be a + * misnomer – if funds are not an appropriate way to limit your new item results, + * you can return a different set of values from getFunds. The important thing is + * that this parameter supports an ID returned by getFunds, whatever that may + * mean. + * Output: An associative array with two keys: 'count' (the number of items + * in the 'results' array) and 'results' (an array of associative arrays, each + * with a single key: 'id', a record ID). + * + * IMPORTANT: The fundID parameter changed behavior in r2184. In VuFind 1.0RC2 + * and earlier versions, it receives one of the VALUES returned by getFunds(); + * in more recent code, it receives one of the KEYS from getFunds(). See getFunds + * for additional notes. + */ + public function getNewItems($page = 1, $limit, $daysOld = 30, $fundID = null) + { + return []; + } + + // @codingStandardsIgnoreEnd +} diff --git a/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php b/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..a37d4b6a1a5f2adce682bce1ad586d1b33534d6f --- /dev/null +++ b/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php @@ -0,0 +1,69 @@ +<?php +/** + * Factory for Folio ILS driver. + * + * PHP version 5 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package ILS_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\ILS\Driver; + +use Interop\Container\ContainerInterface; + +/** + * Factory for Folio ILS driver. + * + * @category VuFind + * @package ILS_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class FolioFactory extends DriverWithDateConverterFactory +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $sessionFactory = function ($namespace) use ($container) { + $manager = $container->get('Zend\Session\SessionManager'); + return new \Zend\Session\Container("Folio_$namespace", $manager); + }; + return parent::__invoke($container, $requestedName, [$sessionFactory]); + } +} diff --git a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php index 268745b5e041d71b6a29a7935dfbd13b23f90ed8..49c0bb9c8d6d04821baf48ba2ac867bb81f09c3c 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php +++ b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php @@ -32,7 +32,6 @@ use PDO; use PDOException; use VuFind\Date\DateException; use VuFind\Exception\ILS as ILSException; -use Zend\Log\LoggerInterface; /** * VuFind Driver for Koha, using web APIs (ILSDI) @@ -106,13 +105,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements */ protected $db; - /** - * Logger Status - * - * @var LoggerInterface - */ - protected $logger = false; - /** * Date converter object * @@ -408,17 +400,17 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements * Makes a request to the Koha ILSDI API * * @param string $service Called function (GetAvailability, - * GetRecords, - * GetAuthorityRecords, - * LookupPatron, - * AuthenticatePatron, - * GetPatronInfo, - * GetPatronStatus, - * GetServices, - * RenewLoan, - * HoldTitle, - * HoldItem, - * CancelHold) + * GetRecords, + * GetAuthorityRecords, + * LookupPatron, + * AuthenticatePatron, + * GetPatronInfo, + * GetPatronStatus, + * GetServices, + * RenewLoan, + * HoldTitle, + * HoldItem, + * CancelHold) * @param array $params Key is parameter name, value is parameter value * @param string $http_method HTTP method (default = GET) * @@ -1205,7 +1197,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements $this->debug("ID: " . $rsp->{'borrowernumber'}); $this->debug("Chrgs: " . $rsp->{'charges'}); - foreach ($rsp->{'fines'}->{'fine'} as $fine) { + foreach ($rsp->{'fines'}->{'fine'} ?? [] as $fine) { $fineLst[] = [ 'amount' => 100 * $this->getField($fine->{'amount'}), // FIXME: require accountlines.itemnumber -> issues.issuedate data @@ -1244,7 +1236,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements $this->debug("ID: " . $rsp->{'borrowernumber'}); - foreach ($rsp->{'holds'}->{'hold'} as $hold) { + foreach ($rsp->{'holds'}->{'hold'} ?? [] as $hold) { $holdLst[] = [ 'id' => $this->getField($hold->{'biblionumber'}), 'location' => $this->getField($hold->{'branchname'}), @@ -1511,7 +1503,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements $this->debug("ID: " . $rsp->{'borrowernumber'}); - foreach ($rsp->{'loans'}->{'loan'} as $loan) { + foreach ($rsp->{'loans'}->{'loan'} ?? [] as $loan) { $start = microtime(true); $rsp2 = $this->makeIlsdiRequest( "GetServices", [ @@ -1522,7 +1514,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements $end = microtime(true); $requestTimes[] = $end - $start; $renewable = false; - foreach ($rsp2->{'AvailableFor'} as $service) { + foreach ($rsp2->{'AvailableFor'} ?? [] as $service) { if ($this->getField((string)$service) == "loan renewal") { $renewable = true; } @@ -1848,12 +1840,12 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements $bindParams[':dept'] = $dept; } $reserveWhere = empty($reserveWhere) ? - "" : "where (" . implode(' AND ', $reserveWhere) . ")"; + "" : "HAVING (" . implode(' AND ', $reserveWhere) . ")"; $sql = "SELECT biblionumber AS `BIB_ID`, - courses.course_id AS COURSE_ID, - course_instructors.borrowernumber as INSTRUCTOR_ID, - courses.department AS DEPARTMENT_ID + courses.course_id AS `COURSE_ID`, + course_instructors.borrowernumber as `INSTRUCTOR_ID`, + courses.department AS `DEPARTMENT_ID` FROM courses INNER JOIN `authorised_values` ON courses.department = `authorised_values`.`authorised_value` @@ -1862,11 +1854,14 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements INNER JOIN `items` USING (itemnumber) INNER JOIN `course_instructors` USING (course_id) INNER JOIN `borrowers` USING (borrowernumber) - WHERE courses.enabled = 'yes'" . $reserveWhere; + WHERE courses.enabled = 'yes' " . $reserveWhere; try { - $sqlStmt = $this->db->prepare($sql, $bindParams); - $sqlStmt->execute(); + if (!$this->db) { + $this->initDb(); + } + $sqlStmt = $this->db->prepare($sql); + $sqlStmt->execute($bindParams); $result = []; foreach ($sqlStmt->fetchAll() as $rowItem) { $result[] = $rowItem; @@ -1926,6 +1921,49 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements } } + /** + * Change Password + * + * This method changes patron's password + * + * @param array $detail An associative array with three keys + * patron - The patron array from patronLogin + * oldPassword - Old password + * newPassword - New password + * + * @return array An associative array with keys: + * success - boolean, true if change was made + * status - string, A status message - subject to translation + */ + public function changePassword($detail) + { + if (!$this->db) { + $this->initDb(); + } + $sql = "UPDATE borrowers SET password = ? WHERE borrowernumber = ?"; + $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $max = mb_strlen($keyspace, '8bit') - 1; + $salt = ''; + for ($i = 0; $i < 16; ++$i) { // 16 is length of salt + $salt .= $keyspace[random_int(0, $max)]; + } + $salt = base64_encode($salt); + $newPassword_hashed = crypt($detail['newPassword'], '$2a$08$' . $salt); + try { + $stmt = $this->db->prepare($sql); + $result = $stmt->execute( + [ $newPassword_hashed, $detail['patron']['id'] ] + ); + } catch (Exception $e) { + return [ 'success' => false, 'status' => $e->getMessage() ]; + } + return [ + 'success' => $result, + 'status' => $result ? 'new_password_success' + : 'password_error_not_unique' + ]; + } + /** * Convert a database date to a displayable date. * diff --git a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php index db2d4bac3ccfcf7d91817885e76a6d73f6a4d0ef..db1a3ec4684bb40c3dadf2c3c26c037a8d7b1d59 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php +++ b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php @@ -190,20 +190,53 @@ class MultiBackend extends AbstractBase implements \Zend\Log\LoggerAwareInterfac */ public function getStatuses($ids) { - $items = []; + // Group records by source and request statuses from the drivers + $grouped = []; foreach ($ids as $id) { - try { - $items[] = $this->getStatus($id); - } catch (ILSException $e) { - $items[] = [ - [ - 'id' => $id, - 'error' => 'An error has occurred' - ] + $source = $this->getSource($id); + if (!isset($grouped[$source])) { + $driver = $this->getDriver($source); + $grouped[$source] = [ + 'driver' => $driver, + 'ids' => [] ]; } + $grouped[$source]['ids'][] = $id; + } + + // Process each group + $results = []; + foreach ($grouped as $source => $current) { + // Get statuses only if a driver is configured for this source + if ($current['driver']) { + $localIds = array_map( + function ($id) { + return $this->getLocalId($id); + }, + $current['ids'] + ); + try { + $statuses = $current['driver']->getStatuses($localIds); + } catch (ILSException $e) { + $statuses = array_map( + function ($id) { + return [ + ['id' => $id, 'error' => 'An error has occurred'] + ]; + }, + $localIds + ); + } + $statuses = array_map( + function ($status) use ($source) { + return $this->addIdPrefixes($status, $source); + }, + $statuses + ); + $results = array_merge($results, $statuses); + } } - return $items; + return $results; } /** @@ -448,16 +481,17 @@ class MultiBackend extends AbstractBase implements \Zend\Log\LoggerAwareInterfac * by a specific patron. * * @param array $patron The patron array from patronLogin + * @param array $params Parameters * * @return mixed Array of the patron's transactions */ - public function getMyTransactions($patron) + public function getMyTransactions($patron, $params = []) { $source = $this->getSource($patron['cat_username']); $driver = $this->getDriver($source); if ($driver) { $transactions = $driver->getMyTransactions( - $this->stripIdPrefixes($patron, $source) + $this->stripIdPrefixes($patron, $source), $params ); return $this->addIdPrefixes($transactions, $source); } @@ -1099,7 +1133,7 @@ class MultiBackend extends AbstractBase implements \Zend\Log\LoggerAwareInterfac $source = $this->getSource($details['id']); $driver = $this->getDriver($source); if ($driver - && $this->methodSupported($driver, 'placeILLRequest', compact($details)) + && $this->methodSupported($driver, 'placeILLRequest', compact('details')) ) { // Patron is not stripped so that the correct library can be determined $details = $this->stripIdPrefixes($details, $source, ['id'], ['patron']); diff --git a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php index f707850f54f41277e70ecc129faf93b76861fae5..15972e22ac091dc229ac1d0567546652f9d44984 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php +++ b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php @@ -284,17 +284,13 @@ class NoILS extends AbstractBase implements TranslatorAwareInterface */ public function hasHoldings($id) { - // If the ILS is disabled, there will never be holdings: - if ($this->getOfflineMode() == 'ils-none') { - return false; - } - // If the ILS is offline, we should if we can look up details: $useHoldings = $this->config['settings']['useHoldings'] ?? ''; // "none" will be processed differently in the config depending // on whether it's in or out of quotes; handle both cases. - return $useHoldings != 'none' && !empty($useHoldings); + return $useHoldings != 'none' && !empty($useHoldings) + && !empty($this->getHolding($id)); } /** diff --git a/module/VuFind/src/VuFind/ILS/Driver/PAIA.php b/module/VuFind/src/VuFind/ILS/Driver/PAIA.php index d1c3a5e09a9128faf762029af2abeef4c30e8a34..d5abc56d15384e7ff7ce70073e3131f66855b1ab 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/PAIA.php +++ b/module/VuFind/src/VuFind/ILS/Driver/PAIA.php @@ -281,7 +281,7 @@ class PAIA extends DAIA } // If caching is enabled for PAIA clear the cache as at least for one - // item cancel was successfull and therefore the status changed. + // item cancel was successful and therefore the status changed. // Otherwise the changed status will not be shown before the cache // expires. if ($this->paiaCacheEnabled) { @@ -1069,7 +1069,7 @@ class PAIA extends DAIA } // If caching is enabled for PAIA clear the cache as at least for one - // item renew was successfull and therefore the status changed. Otherwise + // item renew was successful and therefore the status changed. Otherwise // the changed status will not be shown before the cache expires. if ($this->paiaCacheEnabled) { $this->removeCachedData($patron['cat_username']); diff --git a/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php b/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php index 020df9446d6be9b4faedbb65917ee780841bed14..0382cdc0b012b1c9c73941fc1b54d2d70e088487 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php +++ b/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php @@ -50,6 +50,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'daia' => 'VuFind\ILS\Driver\DAIA', 'demo' => 'VuFind\ILS\Driver\Demo', 'evergreen' => 'VuFind\ILS\Driver\Evergreen', + 'folio' => 'VuFind\ILS\Driver\Folio', 'horizon' => 'VuFind\ILS\Driver\Horizon', 'horizonxmlapi' => 'VuFind\ILS\Driver\HorizonXMLAPI', 'innovative' => 'VuFind\ILS\Driver\Innovative', @@ -86,6 +87,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'VuFind\ILS\Driver\Demo' => 'VuFind\ILS\Driver\DemoFactory', 'VuFind\ILS\Driver\Evergreen' => 'Zend\ServiceManager\Factory\InvokableFactory', + 'VuFind\ILS\Driver\Folio' => 'VuFind\ILS\Driver\FolioFactory', 'VuFind\ILS\Driver\Horizon' => 'VuFind\ILS\Driver\DriverWithDateConverterFactory', 'VuFind\ILS\Driver\HorizonXMLAPI' => diff --git a/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php b/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php index 88a50fde628f49e6d4b786b01ac5499a1897bcfd..8dc0282d8c030fe9b32c4da539e792d1a4e407f4 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php +++ b/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php @@ -4,7 +4,7 @@ * * PHP version 7 * - * Copyright (C) The National Library of Finland 2016-2017. + * Copyright (C) The National Library of Finland 2016-2018. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -141,6 +141,13 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, 'd' => 'In Process' ]; + /** + * Available API version + * + * @var int + */ + protected $apiVersion = 5; + /** * Constructor * @@ -222,6 +229,10 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, ); } + if (isset($this->config['Catalog']['api_version'])) { + $this->apiVersion = $this->config['Catalog']['api_version']; + } + // Init session cache for session-specific data $namespace = md5( $this->config['Catalog']['host'] . '|' @@ -393,7 +404,9 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, $lastname = ''; if (!empty($result['names'])) { $name = $result['names'][0]; - list($lastname, $firstname) = explode(', ', $name, 2); + $parts = explode(', ', $name, 2); + $lastname = $parts[0]; + $firstname = $parts[1] ?? ''; } return [ 'id' => $result['id'], @@ -501,18 +514,22 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, * by a specific patron. * * @param array $patron The patron array from patronLogin + * @param array $params Parameters * * @throws DateException * @throws ILSException * @return array Array of the patron's transactions on success. */ - public function getMyTransactions($patron) + public function getMyTransactions($patron, $params = []) { + $pageSize = $params['limit'] ?? 50; + $offset = isset($params['page']) ? ($params['page'] - 1) * $pageSize : 0; + $result = $this->makeRequest( ['v3', 'patrons', $patron['id'], 'checkouts'], [ - 'limit' => 10000, - 'offset' => 0, + 'limit' => $pageSize, + 'offset' => $offset, 'fields' => 'item,dueDate,numberOfRenewals,outDate,recallDate' . ',callNumber,barcode' ], @@ -520,7 +537,10 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, $patron ); if (empty($result['entries'])) { - return []; + return [ + 'count' => $result['total'], + 'records' => [] + ]; } $transactions = []; foreach ($result['entries'] as $entry) { @@ -567,7 +587,10 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, $transactions[] = $transaction; } - return $transactions; + return [ + 'count' => $result['total'], + 'records' => $transactions + ]; } /** @@ -720,12 +743,16 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, */ public function getMyHolds($patron) { + $fields = 'id,record,frozen,placed,location,pickupLocation,status' + . ',recordType,priority,priorityQueueLength'; + if ($this->apiVersion >= 5) { + $fields .= ',pickupByDate'; + } $result = $this->makeRequest( ['v3', 'patrons', $patron['id'], 'holds'], [ 'limit' => 10000, - 'fields' => 'id,record,frozen,placed,location,pickupLocation' - . ',status,recordType,priority,priorityQueueLength' + 'fields' => $fields ], 'GET', $patron @@ -768,17 +795,24 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, $position = $entry['priorityQueueLength'] . ' / ' . $entry['priorityQueueLength']; } else { - $position = ($entry['priority'] + 1) . ' / ' + $position = $entry['priority'] . ' / ' . $entry['priorityQueueLength']; } + $lastPickup = !empty($entry['pickupByDate']) + ? $this->dateConverter->convertToDisplayDate( + 'Y-m-d', $entry['pickupByDate'] + ) : ''; $holds[] = [ 'id' => $bibId, 'requestId' => $this->extractId($entry['id']), 'item_id' => $itemId ? $itemId : $this->extractId($entry['id']), - 'location' => $entry['pickupLocation']['name'], + // note that $entry['pickupLocation']['name'] may contain misleading + // text, so we instead use the code here: + 'location' => $entry['pickupLocation']['code'], 'create' => $this->dateConverter->convertToDisplayDate( 'Y-m-d', $entry['placed'] ), + 'last_pickup_date' => $lastPickup, 'position' => $position, 'available' => $available, 'in_transit' => $entry['status']['code'] == 't', @@ -804,7 +838,7 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, public function getCancelHoldDetails($holdDetails) { return $holdDetails['available'] || $holdDetails['in_transit'] ? '' - : $holdDetails['item_id']; + : $holdDetails['requestId']; } /** @@ -827,7 +861,7 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, foreach ($details as $holdId) { $result = $this->makeRequest( - ['v5', 'patrons', 'holds', $holdId], [], 'DELETE', $patron + ['v5', 'patrons', 'holds', $holdId], '', 'DELETE', $patron ); if (!empty($result['code'])) { @@ -1206,6 +1240,11 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, */ public function getConfig($function, $params = null) { + if ('getMyTransactions' === $function) { + return [ + 'max_results' => 100 + ]; + } if ('getMyTransactionHistory' === $function) { if (empty($this->config['TransactionHistory']['enabled'])) { return false; @@ -1399,14 +1438,8 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface, protected function renewAccessToken($patron = false) { $patronCode = false; - if ($patron) { + if ($patron && !empty($this->config['Catalog']['redirect_uri'])) { // Do a patron login and then perform an authorization grant request - if (empty($this->config['Catalog']['redirect_uri'])) { - $this->error( - 'Catalog/redirect_uri is required for patron authentication' - ); - throw new ILSException('Problem with Sierra REST driver config.'); - } $params = [ 'client_id' => $this->config['Catalog']['client_key'], 'redirect_uri' => $this->config['Catalog']['redirect_uri'], diff --git a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php index 153fb4691b4b3d6324f988adb538677880aaf8ef..3fb4b127f2215505960a99df0acf61d547da3706 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php @@ -270,13 +270,10 @@ class Symphony extends AbstractBase implements LoggerAwareInterface * @param string $operation the SymWS operation name * @param array $parameters the request parameters for the operation * @param array $options An associative array of additional options: - * - 'login': login to use for the operation; - * omit for configured default - * credentials or anonymous - * - 'password': password associated with login; - * omit for no password - * - 'header': SoapHeader to use for the request; - * omit to handle automatically + * - 'login': login to use for the operation; omit for configured default + * credentials or anonymous + * - 'password': password associated with login; omit for no password + * - 'header': SoapHeader to use for the request; omit to handle automatically * * @return mixed the result of the SOAP call */ diff --git a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php index b51e8ea1cc2115f2c41b2255b51b19e75bd68329..e5964b720e9f545689c38bc44cc1d2f43c3ee9ab 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php @@ -1280,7 +1280,7 @@ class Unicorn extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterf /** * Given a location field, return the values relevant to VuFind. * - * This method is meant to be overriden in inheriting classes to + * This method is meant to be overridden in inheriting classes to * reflect local policies regarding interpretation of the a, b and * c subfields of 852. * diff --git a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php index 409095d5755cd250d992196b74e87f894891ad6e..b70e2ccc58a81604d1625d1fc40114b6ca37a9de 100644 --- a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php +++ b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php @@ -1581,7 +1581,7 @@ EOT; } return ['amount' => $sqlRow['FINE_FEE_AMOUNT'], - 'fine' => $sqlRow['FINE_FEE_DESC'], + 'fine' => utf8_encode($sqlRow['FINE_FEE_DESC']), 'balance' => $sqlRow['FINE_FEE_BALANCE'], 'createdate' => $createDate, 'checkout' => $chargeDate, diff --git a/module/VuFind/src/VuFind/ILS/Logic/Holds.php b/module/VuFind/src/VuFind/ILS/Logic/Holds.php index c5d4c6bc1f3f92826ac49a472bfe59eedadffc74..7455a0960876e9f4b41c1b621124e93484b102e6 100644 --- a/module/VuFind/src/VuFind/ILS/Logic/Holds.php +++ b/module/VuFind/src/VuFind/ILS/Logic/Holds.php @@ -209,7 +209,7 @@ class Holds $grb = 'getRequestBlocks'; // use variable to shorten line below: $blocks - = $patron && $this->catalog->checkCapability($grb, compact($patron)) + = $patron && $this->catalog->checkCapability($grb, compact('patron')) ? $this->catalog->getRequestBlocks($patron) : false; $mode = $this->catalog->getHoldsMode(); diff --git a/module/VuFind/src/VuFind/ILS/PaginationHelper.php b/module/VuFind/src/VuFind/ILS/PaginationHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..ef675efef4233061719cf24448c8c6982ce9d17f --- /dev/null +++ b/module/VuFind/src/VuFind/ILS/PaginationHelper.php @@ -0,0 +1,163 @@ +<?php +/** + * ILS Pagination Helper + * + * This class helps build paginators for ILS-provided data. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package ILS_Drivers + * @author Andrew S. Nagy <vufind-tech@lists.sourceforge.net> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +namespace VuFind\ILS; + +/** + * ILS Pagination Helper + * + * This class helps build paginators for ILS-provided data. + * + * @category VuFind + * @package ILS_Drivers + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:ils_drivers Wiki + */ +class PaginationHelper +{ + /** + * Support method for getPagingSetup() -- validate the active sort option, + * returning either a valid sort method or false. + * + * @param array $functionConfig Function config returned from the ILS + * @param string $sort The unvalidated user sort parameter + * + * @return string|bool + */ + protected function validateSort($functionConfig, $sort) + { + // If sort is disabled, all settings are invalid... + if (empty($functionConfig['sort'])) { + return false; + } + // If provided setting is valid, use it... + if (isset($functionConfig['sort'][$sort])) { + return $sort; + } + // At this point, we need to find a reasonable value, either the configured + // default or the first valid sort value... + if (isset($functionConfig['default_sort'])) { + return $functionConfig['default_sort']; + } + reset($functionConfig['sort']); + return key($functionConfig['sort']); + } + + /** + * Support method for getPagingSetup() -- determine the list of sort options. + * + * @param array $functionConfig Function config returned from the ILS + * @param string $sort Currently active sort option + * + * @return array + */ + protected function getSortList($functionConfig, $sort) + { + $sortList = []; + if (!empty($functionConfig['sort'])) { + foreach ($functionConfig['sort'] as $key => $value) { + $sortList[$key] = [ + 'desc' => $value, + 'url' => '?sort=' . urlencode($key), + 'selected' => $sort == $key + ]; + } + } + return $sortList; + } + + /** + * Get paging settings and request data for paged ILS requests. + * + * @param int $page Current page (1-based) + * @param string $sort Current sort setting (null for none) + * @param int $defaultPageSize Default page size + * @param array $functionConfig Function config returned from the ILS + * + * @return array + */ + public function getOptions($page, $sort, $defaultPageSize, + $functionConfig + ) { + // Get page and page size: + $limit = $defaultPageSize; + $ilsPaging = true; + if (isset($functionConfig['max_results'])) { + $limit = min([$functionConfig['max_results'], $limit]); + } elseif (isset($functionConfig['page_size'])) { + if (!in_array($limit, $functionConfig['page_size'])) { + $limit = $functionConfig['default_page_size'] + ?? $functionConfig['page_size'][0]; + } + } else { + $ilsPaging = false; + } + // Collect ILS call params + $ilsParams = ['sort' => $this->validateSort($functionConfig, $sort)]; + if ($ilsPaging) { + $ilsParams['page'] = $page >= 1 ? $page : 1; + $ilsParams['limit'] = $limit; + } + $sortList = $this->getSortList($functionConfig, $ilsParams['sort']); + return compact('page', 'limit', 'ilsPaging', 'ilsParams', 'sortList'); + } + + /** + * Build a paginator with the paging options and ILS results if necessary + * + * @param array $pageOptions Paging options and parameters (returned by the + * getOptions method) + * @param int $count Result count + * @param array $records Result records + * + * @return false|\Zend\Paginator\Paginator + */ + public function getPaginator($pageOptions, $count, $records) + { + $limit = $pageOptions['limit']; + $page = $pageOptions['page']; + if (($page - 1) * $limit >= $count && $page > 1) { + throw new \VuFind\Exception\BadRequest('Page number out of range.'); + } + if ($pageOptions['ilsPaging'] && $limit < $count) { + $adapter = new \Zend\Paginator\Adapter\NullFill($count); + } elseif ($limit > 0 && $limit < $count) { + $adapter = new \Zend\Paginator\Adapter\ArrayAdapter($records); + } else { + return false; + } + $paginator = new \Zend\Paginator\Paginator($adapter); + $paginator->setItemCountPerPage($limit); + $paginator->setCurrentPageNumber($page); + return $paginator; + } +} diff --git a/module/VuFind/src/VuFind/Log/LoggerFactory.php b/module/VuFind/src/VuFind/Log/LoggerFactory.php index d35bb6f83c367fbf9f8a342c944454a0a0bae76d..bf828b45e96136e1d46a175ecf4c270214aceb24 100644 --- a/module/VuFind/src/VuFind/Log/LoggerFactory.php +++ b/module/VuFind/src/VuFind/Log/LoggerFactory.php @@ -299,8 +299,10 @@ class LoggerFactory implements FactoryInterface $max = Logger::EMERG; // Emergency: system is unusable $min = Logger::ALERT; // Alert: action must be taken immediately break; - default: // INVALID FILTER - continue; + default: + // INVALID FILTER, so skip it. We must continue 2 levels, so we + // continue the foreach loop instead of just breaking the switch. + continue 2; } // Clone the submitted writer since we'll need a separate instance of the diff --git a/module/VuFind/src/VuFind/OAI/Server.php b/module/VuFind/src/VuFind/OAI/Server.php index db808589a5fe22ab4db0bf16b4317f43a1ca12aa..4afb1af989acbd33e7f8218c0e932920bf6bd7af 100644 --- a/module/VuFind/src/VuFind/OAI/Server.php +++ b/module/VuFind/src/VuFind/OAI/Server.php @@ -30,6 +30,7 @@ namespace VuFind\OAI; use SimpleXMLElement; use VuFind\Exception\RecordMissing as RecordMissingException; use VuFind\SimpleXML; +use VuFindApi\Formatter\RecordFormatter; /** * OAI Server class @@ -170,6 +171,21 @@ class Server */ protected $setQueries = []; + /** + * Record formatter + * + * @var RecordFormatter + */ + protected $recordFormatter = null; + + /** + * Fields to return when the 'vufind' format is requested. Empty array means the + * format is disabled. + * + * @var array + */ + protected $vufindApiFields = []; + /** * Constructor * @@ -197,7 +213,6 @@ class Server $this->baseHostURL .= $parts['port']; } $this->params = isset($params) && is_array($params) ? $params : []; - $this->initializeMetadataFormats(); // Load details on supported formats $this->initializeSettings($config); // Load config.ini settings } @@ -214,6 +229,22 @@ class Server $this->recordLinkHelper = $helper; } + /** + * Add a record formatter (optional -- allows the vufind record format to be + * returned). + * + * @param RecordFormatter $formatter Record formatter + * + * @return void + */ + public function setRecordFormatter($formatter) + { + $this->recordFormatter = $formatter; + // Reset metadata formats so they can be reinitialized; the formatter + // may enable additional options. + $this->metadataFormats = []; + } + /** * Respond to the OAI-PMH request. * @@ -290,6 +321,56 @@ class Server } } + /** + * Support method for attachNonDeleted() to build the VuFind metadata for + * a record driver. + * + * @param object $record A record driver object + * + * @return string + */ + protected function getVuFindMetadata($record) + { + // Root node + $recordDoc = new \DOMDocument(); + $vufindFormat = $this->getMetadataFormats()['oai_vufind_json']; + $rootNode = $recordDoc->createElementNS( + $vufindFormat['namespace'], 'oai_vufind_json:record' + ); + $rootNode->setAttribute( + 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' + ); + $rootNode->setAttribute( + 'xsi:schemaLocation', + $vufindFormat['namespace'] . ' ' . $vufindFormat['schema'] + ); + $recordDoc->appendChild($rootNode); + + // Add oai_dc part + $oaiDc = new \DOMDocument(); + $oaiDc->loadXML( + $record->getXML('oai_dc', $this->baseHostURL, $this->recordLinkHelper) + ); + $rootNode->appendChild( + $recordDoc->importNode($oaiDc->documentElement, true) + ); + + // Add VuFind metadata + $records = $this->recordFormatter->format( + [$record], $this->vufindApiFields + ); + $metadataNode = $recordDoc->createElementNS( + $vufindFormat['namespace'], 'oai_vufind_json:metadata' + ); + $metadataNode->setAttribute('type', 'application/json'); + $metadataNode->appendChild( + $recordDoc->createCDATASection(json_encode($records[0])) + ); + $rootNode->appendChild($metadataNode); + + return $recordDoc->saveXML(); + } + /** * Attach a non-deleted record to an XML document. * @@ -307,6 +388,8 @@ class Server // Get the XML (and display an error if it is unsupported): if ($format === false) { $xml = ''; // no metadata if in header-only mode! + } elseif ('oai_vufind_json' === $format && $this->supportsVuFindMetadata()) { + $xml = $this->getVuFindMetadata($record); // special case } else { $xml = $record ->getXML($format, $this->baseHostURL, $this->recordLinkHelper); @@ -448,8 +531,19 @@ class Server } /** - * Load data about metadata formats. (This is called by the constructor - * and is only a separate method to allow easy override by child classes). + * Does the current configuration support the VuFind metadata format (using + * the API's record formatter. + * + * @return bool + */ + protected function supportsVuFindMetadata() + { + return !empty($this->vufindApiFields) && null !== $this->recordFormatter; + } + + /** + * Initialize data about metadata formats. (This is called on demand and is + * defined as a separate method to allow easy override by child classes). * * @return void */ @@ -461,6 +555,28 @@ class Server $this->metadataFormats['marc21'] = [ 'schema' => 'http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd', 'namespace' => 'http://www.loc.gov/MARC21/slim']; + + if ($this->supportsVuFindMetadata()) { + $this->metadataFormats['oai_vufind_json'] = [ + 'schema' => 'https://vufind.org/xsd/oai_vufind_json-1.0.xsd', + 'namespace' => 'http://vufind.org/oai_vufind_json-1.0' + ]; + } else { + unset($this->metadataFormats['oai_vufind_json']); + } + } + + /** + * Get metadata formats; initialize the list if necessary. + * + * @return array + */ + protected function getMetadataFormats() + { + if (empty($this->metadataFormats)) { + $this->initializeMetadataFormats(); + } + return $this->metadataFormats; } /** @@ -497,6 +613,13 @@ class Server if (isset($config->OAI->set_query)) { $this->setQueries = $config->OAI->set_query->toArray(); } + + // Initialize VuFind API format fields: + $this->vufindApiFields = array_filter( + explode( + ',', $config->OAI->vufind_api_format_fields ?? '' + ) + ); } /** @@ -521,9 +644,10 @@ class Server // means that no specific record ID was requested; otherwise, they only // apply if the current record driver supports them): $xml = new SimpleXMLElement('<ListMetadataFormats />'); - foreach ($this->metadataFormats as $prefix => $details) { + foreach ($this->getMetadataFormats() as $prefix => $details) { if ($record === false || $record->getXML($prefix) !== false + || ('oai_vufind_json' === $prefix && $this->supportsVuFindMetadata()) ) { $node = $xml->addChild('metadataFormat'); $node->metadataPrefix = $prefix; @@ -814,7 +938,7 @@ class Server } // Validate requested metadata format: - $prefixes = array_keys($this->metadataFormats); + $prefixes = array_keys($this->getMetadataFormats()); if (!in_array($params['metadataPrefix'], $prefixes)) { throw new \Exception('cannotDisseminateFormat:Unknown Format'); } diff --git a/module/VuFind/src/VuFind/Recommend/Factory.php b/module/VuFind/src/VuFind/Recommend/Factory.php index 8027246e0c331978c840b02fe5b659e43022e45a..de419acea35f3e801dc421f75be7e11a3340b3f9 100644 --- a/module/VuFind/src/VuFind/Recommend/Factory.php +++ b/module/VuFind/src/VuFind/Recommend/Factory.php @@ -233,6 +233,18 @@ class Factory ); } + /** + * Factory for SideFacetsDeferred module. + * + * @param ServiceManager $sm Service manager. + * + * @return SideFacets + */ + public static function getSideFacetsDeferred(ServiceManager $sm) + { + return new SideFacetsDeferred($sm->get('VuFind\Config\PluginManager')); + } + /** * Factory for SummonBestBets module. * diff --git a/module/VuFind/src/VuFind/Recommend/PluginManager.php b/module/VuFind/src/VuFind/Recommend/PluginManager.php index c357e7c906e21f64c5188c6d2a2c395cc6441db0..3a4cdee15c61bc94793c94a1747915d0773a2928 100644 --- a/module/VuFind/src/VuFind/Recommend/PluginManager.php +++ b/module/VuFind/src/VuFind/Recommend/PluginManager.php @@ -61,6 +61,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'libraryh3lp' => 'VuFind\Recommend\Libraryh3lp', 'mapselection' => 'VuFind\Recommend\MapSelection', 'sidefacets' => 'VuFind\Recommend\SideFacets', + 'sidefacetsdeferred' => 'VuFind\Recommend\SideFacetsDeferred', 'openlibrarysubjects' => 'VuFind\Recommend\OpenLibrarySubjects', 'openlibrarysubjectsdeferred' => 'VuFind\Recommend\OpenLibrarySubjectsDeferred', @@ -123,6 +124,8 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'VuFind\Recommend\MapSelection' => 'VuFind\Recommend\Factory::getMapSelection', 'VuFind\Recommend\SideFacets' => 'VuFind\Recommend\Factory::getSideFacets', + 'VuFind\Recommend\SideFacetsDeferred' + => 'VuFind\Recommend\Factory::getSideFacetsDeferred', 'VuFind\Recommend\OpenLibrarySubjects' => 'Zend\ServiceManager\Factory\InvokableFactory', 'VuFind\Recommend\OpenLibrarySubjectsDeferred' => diff --git a/module/VuFind/src/VuFind/Recommend/SideFacets.php b/module/VuFind/src/VuFind/Recommend/SideFacets.php index f6cca916b799a9fe2be1a7ff02aea615ca47cc99..58471426d6cd073b1e8875f2ae184953e6effd17 100644 --- a/module/VuFind/src/VuFind/Recommend/SideFacets.php +++ b/module/VuFind/src/VuFind/Recommend/SideFacets.php @@ -268,9 +268,9 @@ class SideFacets extends AbstractFacets $facetArray = $this->hierarchicalFacetHelper->buildFacetArray( $hierarchicalFacet, $facetSet[$hierarchicalFacet]['list'] ); - $facetSet[$hierarchicalFacet]['list'] - = $this->hierarchicalFacetHelper - ->flattenFacetHierarchy($facetArray); + $facetSet[$hierarchicalFacet]['list'] = $this + ->hierarchicalFacetHelper + ->flattenFacetHierarchy($facetArray); } } diff --git a/module/VuFind/src/VuFind/Recommend/SideFacetsDeferred.php b/module/VuFind/src/VuFind/Recommend/SideFacetsDeferred.php new file mode 100644 index 0000000000000000000000000000000000000000..f8eb2cd2c6c752d6f5db75e4e3d16feef6b82747 --- /dev/null +++ b/module/VuFind/src/VuFind/Recommend/SideFacetsDeferred.php @@ -0,0 +1,85 @@ +<?php +/** + * SideFacetsDeferred Recommendations Module + * + * PHP version 7 + * + * Copyright (C) The National Library of Finland 2016-2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Recommendations + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/vufind2:recommendation_modules Wiki + */ +namespace VuFind\Recommend; + +/** + * SideFacetsDeferred Recommendations Module + * + * This class provides recommendations displaying facets beside search results + * after the search results have been displayed + * + * @category VuFind + * @package Recommendations + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/vufind2:recommendation_modules Wiki + */ +class SideFacetsDeferred extends SideFacets +{ + /** + * Get results stored in the object. + * + * @return \VuFind\Search\Base\Results + */ + public function getResults() + { + // Since we didn't add facets in init, do it now so that the config is + // available for e.g. $this->results->getParams()->getFilterList(). + parent::init($this->results->getParams(), null); + return $this->results; + } + + /** + * Get active facets (key => display string) + * + * @return array + */ + public function getActiveFacets() + { + return $this->mainFacets; + } + + /** + * Called at the end of the Search Params objects' initFromRequest() method. + * This method is responsible for setting search parameters needed by the + * recommendation module and for reading any existing search parameters that may + * be needed. + * + * We'll not do anything here since we want to defer the whole process until the + * search is done. + * + * @param \VuFind\Search\Base\Params $params Search parameter object + * @param \Zend\StdLib\Parameters $request Parameter object representing user + * request. + * + * @return void + */ + public function init($params, $request) + { + } +} diff --git a/module/VuFind/src/VuFind/Record/Checklist.php b/module/VuFind/src/VuFind/Record/Checklist.php new file mode 100644 index 0000000000000000000000000000000000000000..3728f31f98254867ecdb86ff4582bbc82d6b1e33 --- /dev/null +++ b/module/VuFind/src/VuFind/Record/Checklist.php @@ -0,0 +1,142 @@ +<?php +/** + * Checklist class (used for checking off a list of values) + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Record; + +/** + * Checklist class (used for checking off a list of values) + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class Checklist +{ + /** + * Unchecked values + * + * @var array + */ + protected $unchecked; + + /** + * Checked values + * + * @var array + */ + protected $checked = []; + + /** + * Constructor + * + * @param array $values Values for list (all begin unchecked) + */ + public function __construct($values) + { + $this->unchecked = array_unique($values); + } + + /** + * Get list of checked values. + * + * @return array + */ + public function getChecked() + { + return array_values($this->checked); + } + + /** + * Get list of unchecked values. + * + * @return array + */ + public function getUnchecked() + { + return array_values($this->unchecked); + } + + /** + * Are there checked items? + * + * @return bool + */ + public function hasChecked() + { + return count($this->checked) > 0; + } + + /** + * Are there unchecked items? + * + * @return bool + */ + public function hasUnchecked() + { + return count($this->unchecked) > 0; + } + + /** + * Check off a value, returning true if the value was found in the unchecked + * list and false if it was not. + * + * @param mixed $value Value to check + * + * @return bool + */ + public function check($value) + { + $key = array_search($value, $this->unchecked); + if ($key !== false) { + unset($this->unchecked[$key]); + $this->checked[$key] = $value; + return true; + } + return false; + } + + /** + * Uncheck a value, returning true if the value was found in the checked + * list and false if it was not. + * + * @param mixed $value Value to uncheck + * + * @return bool + */ + public function uncheck($value) + { + $key = array_search($value, $this->checked); + if ($key !== false) { + unset($this->checked[$key]); + $this->unchecked[$key] = $value; + return true; + } + return false; + } +} diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/FallbackLoaderInterface.php b/module/VuFind/src/VuFind/Record/FallbackLoader/FallbackLoaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..707e1930d22024b64d1ecedbf6022fd0649ac8cf --- /dev/null +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/FallbackLoaderInterface.php @@ -0,0 +1,50 @@ +<?php +/** + * Record fallback loader interface + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Record\FallbackLoader; + +/** + * Record fallback loader interface + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +interface FallbackLoaderInterface +{ + /** + * Given an array of IDs that failed to load, try to find them using a + * fallback mechanism. + * + * @param array $ids IDs to load + * + * @return array + */ + public function load($ids); +} diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/PluginManager.php b/module/VuFind/src/VuFind/Record/FallbackLoader/PluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..eb9db19b3bb96506ef35aa943ef5f8ed5e94ee97 --- /dev/null +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/PluginManager.php @@ -0,0 +1,70 @@ +<?php +/** + * Record fallback loader plugin manager + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +namespace VuFind\Record\FallbackLoader; + +/** + * Record fallback loader plugin manager + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki + */ +class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager +{ + /** + * Default plugin aliases. + * + * @var array + */ + protected $aliases = [ + 'summon' => 'VuFind\Record\FallbackLoader\Summon', + ]; + + /** + * Default plugin factories. + * + * @var array + */ + protected $factories = [ + 'VuFind\Record\FallbackLoader\Summon' => + 'VuFind\Record\FallbackLoader\SummonFactory', + ]; + + /** + * Return the name of the base class or interface that plug-ins must conform + * to. + * + * @return string + */ + protected function getExpectedInterface() + { + return 'VuFind\Record\FallbackLoader\FallbackLoaderInterface'; + } +} diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php b/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php new file mode 100644 index 0000000000000000000000000000000000000000..599a541cc0fd3e8ffb52a1b615a3b5a69dfef750 --- /dev/null +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php @@ -0,0 +1,131 @@ +<?php +/** + * Summon record fallback loader + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Record\FallbackLoader; + +use SerialsSolutions\Summon\Zend2 as Connector; +use VuFind\Db\Table\Resource; +use VuFindSearch\Backend\Summon\Backend; +use VuFindSearch\ParamBag; + +/** + * Summon record fallback loader + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class Summon implements FallbackLoaderInterface +{ + /** + * Resource table + * + * @var Resource + */ + protected $table; + + /** + * Summon backend + * + * @var Backend + */ + protected $backend; + + /** + * Constructor + * + * @param Resource $table Resource database table object + * @param Backend $backend Summon search backend + */ + public function __construct(Resource $table, Backend $backend) + { + $this->table = $table; + $this->backend = $backend; + } + + /** + * Given an array of IDs that failed to load, try to find them using a + * fallback mechanism. + * + * @param array $ids IDs to load + * + * @return array + */ + public function load($ids) + { + $retVal = []; + foreach ($ids as $id) { + foreach ($this->fetchSingleRecord($id) as $record) { + $this->updateRecord($record, $id); + $retVal[] = $record; + } + } + return $retVal; + } + + /** + * Fetch a single record (null if not found). + * + * @param string $id ID to load + * + * @return \VuFindSearch\Response\RecordCollectionInterface + */ + protected function fetchSingleRecord($id) + { + $resource = $this->table->findResource($id, 'Summon'); + if ($resource && ($extra = json_decode($resource->extra_metadata, true))) { + $bookmark = $extra['bookmark'] ?? ''; + if (strlen($bookmark) > 0) { + $params = new ParamBag( + ['summonIdType' => Connector::IDENTIFIER_BOOKMARK] + ); + return $this->backend->retrieve($bookmark, $params); + } + } + return new \VuFindSearch\Backend\Summon\Response\RecordCollection([]); + } + + /** + * When a record ID has changed, update the record driver and database to + * reflect the changes. + * + * @param \VuFind\RecordDriver\AbstractBase $record Record to update + * @param string $previousId Old ID of record + * + * @return void + */ + protected function updateRecord($record, $previousId) + { + // Update the record driver with knowledge of the previous identifier... + $record->setPreviousUniqueId($previousId); + + // Update the database to replace the obsolete identifier... + $this->table->updateRecordId($previousId, $record->getUniqueId(), 'Summon'); + } +} diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/SummonFactory.php b/module/VuFind/src/VuFind/Record/FallbackLoader/SummonFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..c3d0d04930cd0577b56c03c0fc2722f4a12ef0dc --- /dev/null +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/SummonFactory.php @@ -0,0 +1,70 @@ +<?php +/** + * Summon record fallback loader factory + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Record\FallbackLoader; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * Summon record fallback loader factory + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class SummonFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + $backendManager = $container->get('VuFind\Search\BackendManager'); + return new $requestedName( + $container->get('VuFind\Db\Table\PluginManager')->get('resource'), + $backendManager->get('Summon') + ); + } +} diff --git a/module/VuFind/src/VuFind/Record/Loader.php b/module/VuFind/src/VuFind/Record/Loader.php index 40ac9e504ab95fc329532bcb32ad86e9de0fd36b..106588a3fceee6a8ae303af5d1d5428459b5fc97 100644 --- a/module/VuFind/src/VuFind/Record/Loader.php +++ b/module/VuFind/src/VuFind/Record/Loader.php @@ -30,6 +30,7 @@ namespace VuFind\Record; use VuFind\Exception\RecordMissing as RecordMissingException; +use VuFind\Record\FallbackLoader\PluginManager as FallbackLoader; use VuFind\RecordDriver\PluginManager as RecordFactory; use VuFindSearch\Service as SearchService; @@ -68,19 +69,29 @@ class Loader implements \Zend\Log\LoggerAwareInterface */ protected $recordCache; + /** + * Fallback record loader + * + * @var FallbackLoader + */ + protected $fallbackLoader; + /** * Constructor * - * @param SearchService $searchService Search service - * @param RecordFactory $recordFactory Record loader - * @param Cache $recordCache Record Cache + * @param SearchService $searchService Search service + * @param RecordFactory $recordFactory Record loader + * @param Cache $recordCache Record Cache + * @param FallbackLoader $fallbackLoader Fallback record loader */ public function __construct(SearchService $searchService, - RecordFactory $recordFactory, Cache $recordCache = null + RecordFactory $recordFactory, Cache $recordCache = null, + FallbackLoader $fallbackLoader = null ) { $this->searchService = $searchService; $this->recordFactory = $recordFactory; $this->recordCache = $recordCache; + $this->fallbackLoader = $fallbackLoader; } /** @@ -145,25 +156,23 @@ class Loader implements \Zend\Log\LoggerAwareInterface public function loadBatchForSource($ids, $source = DEFAULT_SEARCH_BACKEND, $tolerateBackendExceptions = false ) { + $list = new Checklist($ids); $cachedRecords = []; if (null !== $this->recordCache && $this->recordCache->isPrimary($source)) { // Try to load records from cache if source is cachable $cachedRecords = $this->recordCache->lookupBatch($ids, $source); // Check which records could not be loaded from the record cache foreach ($cachedRecords as $cachedRecord) { - $key = array_search($cachedRecord->getUniqueId(), $ids); - if ($key !== false) { - unset($ids[$key]); - } + $list->check($cachedRecord->getUniqueId()); } } // Try to load the uncached records from the original $source $genuineRecords = []; - if (!empty($ids)) { + if ($list->hasUnchecked()) { try { - $genuineRecords = $this->searchService->retrieveBatch($source, $ids) - ->getRecords(); + $genuineRecords = $this->searchService + ->retrieveBatch($source, $list->getUnchecked())->getRecords(); } catch (\VuFindSearch\Backend\Exception\BackendException $e) { if (!$tolerateBackendExceptions) { throw $e; @@ -175,22 +184,33 @@ class Loader implements \Zend\Log\LoggerAwareInterface } foreach ($genuineRecords as $genuineRecord) { - $key = array_search($genuineRecord->getUniqueId(), $ids); - if ($key !== false) { - unset($ids[$key]); + $list->check($genuineRecord->getUniqueId()); + } + } + + $retVal = $genuineRecords; + if ($list->hasUnchecked() && $this->fallbackLoader + && $this->fallbackLoader->has($source) + ) { + $fallbackRecords = $this->fallbackLoader->get($source) + ->load($list->getUnchecked()); + foreach ($fallbackRecords as $record) { + $retVal[] = $record; + if (!$list->check($record->getUniqueId())) { + $list->check($record->tryMethod('getPreviousUniqueId')); } } } - if (!empty($ids) && null !== $this->recordCache + if ($list->hasUnchecked() && null !== $this->recordCache && $this->recordCache->isFallback($source) ) { // Try to load missing records from cache if source is cachable - $cachedRecords = $this->recordCache->lookupBatch($ids, $source); + $cachedRecords = $this->recordCache + ->lookupBatch($list->getUnchecked(), $source); } // Merge records found in cache and records loaded from original $source - $retVal = $genuineRecords; foreach ($cachedRecords as $cachedRecord) { $retVal[] = $cachedRecord; } @@ -198,6 +218,24 @@ class Loader implements \Zend\Log\LoggerAwareInterface return $retVal; } + /** + * Build a "missing record" driver. + * + * @param array $details Associative array of record details (from a + * SourceAndIdList) + * + * @return \VuFind\RecordDriver\Missing + */ + protected function buildMissingRecord($details) + { + $fields = $details['extra_fields'] ?? []; + $fields['id'] = $details['id']; + $record = $this->recordFactory->get('Missing'); + $record->setRawData($fields); + $record->setSourceIdentifier($details['source']); + return $record; + } + /** * Given an array of associative arrays with id and source keys (or pipe- * separated source|id strings), load all of the requested records in the @@ -217,48 +255,28 @@ class Loader implements \Zend\Log\LoggerAwareInterface */ public function loadBatch($ids, $tolerateBackendExceptions = false) { - // Sort the IDs by source -- we'll create an associative array indexed by - // source and record ID which points to the desired position of the indexed - // record in the final return array: - $idBySource = []; - foreach ($ids as $i => $details) { - // Convert source|id string to array if necessary: - if (!is_array($details)) { - $parts = explode('|', $details, 2); - $ids[$i] = $details = [ - 'source' => $parts[0], 'id' => $parts[1] - ]; - } - $idBySource[$details['source']][$details['id']] = $i; - } + // Create a SourceAndIdList object to help sort the IDs by source: + $list = new SourceAndIdList($ids); // Retrieve the records and put them back in order: $retVal = []; - foreach ($idBySource as $source => $details) { + foreach ($list->getIdsBySource() as $source => $currentIds) { $records = $this->loadBatchForSource( - array_keys($details), $source, $tolerateBackendExceptions + $currentIds, $source, $tolerateBackendExceptions ); foreach ($records as $current) { - $id = $current->getUniqueId(); - // In theory, we should be able to assume that $details[$id] is - // set... but in practice, we can't make that assumption. In some - // cases, Summon IDs will change, and requests for an old ID value - // will return a record with a different ID. - if (isset($details[$id])) { - $retVal[$details[$id]] = $current; + $position = $list->getRecordPosition($current); + if ($position !== false) { + $retVal[$position] = $current; } } } // Check for missing records and fill gaps with \VuFind\RecordDriver\Missing // objects: - foreach ($ids as $i => $details) { + foreach ($list->getAll() as $i => $details) { if (!isset($retVal[$i]) || !is_object($retVal[$i])) { - $fields = $details['extra_fields'] ?? []; - $fields['id'] = $details['id']; - $retVal[$i] = $this->recordFactory->get('Missing'); - $retVal[$i]->setRawData($fields); - $retVal[$i]->setSourceIdentifier($details['source']); + $retVal[$i] = $this->buildMissingRecord($details); } } diff --git a/module/VuFind/src/VuFind/Record/LoaderFactory.php b/module/VuFind/src/VuFind/Record/LoaderFactory.php index 7d508f7f72d6b225f885da11eaed61ba76bb2f35..8adb957982c8644f1e96cd00f564b0b2063e1088 100644 --- a/module/VuFind/src/VuFind/Record/LoaderFactory.php +++ b/module/VuFind/src/VuFind/Record/LoaderFactory.php @@ -64,7 +64,8 @@ class LoaderFactory implements FactoryInterface return new $requestedName( $container->get('VuFindSearch\Service'), $container->get('VuFind\RecordDriver\PluginManager'), - $container->get('VuFind\Record\Cache') + $container->get('VuFind\Record\Cache'), + $container->get('VuFind\Record\FallbackLoader\PluginManager') ); } } diff --git a/module/VuFind/src/VuFind/Record/SourceAndIdList.php b/module/VuFind/src/VuFind/Record/SourceAndIdList.php new file mode 100644 index 0000000000000000000000000000000000000000..361dcaf406dfe0608e7cf58ebccdeef657d3935c --- /dev/null +++ b/module/VuFind/src/VuFind/Record/SourceAndIdList.php @@ -0,0 +1,133 @@ +<?php +/** + * Record ID list (support class for Loader) + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Record; + +use VuFind\RecordDriver\AbstractBase as Record; + +/** + * Record ID list (support class for Loader) + * + * @category VuFind + * @package Record + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class SourceAndIdList +{ + /** + * Processed ID data. + * + * @var array + */ + protected $ids = []; + + /** + * Record positions in the original list, indexed by source and ID. + * + * @var array + */ + protected $bySource = []; + + /** + * Constructor + * + * @param array $ids Array of associative arrays with id/source keys or strings + * in source|id format. In associative array formats, there is also an optional + * "extra_fields" key which can be used to pass in data formatted as if it + * belongs to the Solr schema; this is used to create a mock driver object if + * the real data source is unavailable. + */ + public function __construct($ids) + { + // Sort the IDs by source -- we'll create an associative array indexed by + // source and record ID which points to the desired position of the indexed + // record in the final return array: + foreach ($ids as $i => $details) { + // Convert source|id string to array if necessary: + if (!is_array($details)) { + $parts = explode('|', $details, 2); + $ids[$i] = $details = [ + 'source' => $parts[0], 'id' => $parts[1] + ]; + } + $this->bySource[$details['source']][$details['id']] = $i; + } + $this->ids = $ids; + } + + /** + * Get the full list of IDs sent to the constructor, normalized to array + * format. + * + * @return array + */ + public function getAll() + { + return $this->ids; + } + + /** + * Get an associative source => id list array. + * + * @return array + */ + public function getIdsBySource() + { + return array_map('array_keys', $this->bySource); + } + + /** + * If the provided record driver corresponds with an ID in the list, return + * the associated position in the list. Otherwise, return false. + * + * @param Record $record Record + * + * @return int|bool + */ + public function getRecordPosition(Record $record) + { + $id = $record->getUniqueId(); + $source = $record->getSourceIdentifier(); + + // In some cases (e.g. Summon), the ID may have changed, so also check the + // prior ID if available. We should do this BEFORE checking the primary ID + // to ensure that we match the correct record in the edge case where a list + // contains both an OLD record ID and the NEW record ID that it has been + // replaced with. Checking the old ID first ensures that we don't match the + // same position twice for two different records. + $oldId = $record->tryMethod('getPreviousUniqueId'); + if ($oldId !== null && isset($this->bySource[$source][$oldId])) { + return $this->bySource[$source][$oldId]; + } + if (isset($this->bySource[$source][$id])) { + return $this->bySource[$source][$id]; + } + return false; + } +} diff --git a/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php b/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php index d6afe45a08b9090d5dff1ae03c988f850d29f6f9..a470005933dbc05a523d39888aef80c78642a74f 100644 --- a/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php +++ b/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php @@ -853,11 +853,15 @@ trait MarcAdvancedTrait { // Special case for MARC: if ($format == 'marc21') { - $xml = $this->getMarcRecord()->toXML(); - $xml = str_replace( - [chr(27), chr(28), chr(29), chr(30), chr(31)], ' ', $xml + $sanitizeXmlRegEx + = '[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+'; + $xml = simplexml_load_string( + trim( + preg_replace( + "/$sanitizeXmlRegEx/u", ' ', $this->getMarcRecord()->toXML() + ) + ) ); - $xml = simplexml_load_string($xml); if (!$xml || !isset($xml->record)) { return false; } diff --git a/module/VuFind/src/VuFind/RecordDriver/MarcReaderTrait.php b/module/VuFind/src/VuFind/RecordDriver/MarcReaderTrait.php index 57c06afaac0743c1ba7b40a440cbc908adc1f642..cacff566cc57481281c4085c58bf0ab50a8b4b3e 100644 --- a/module/VuFind/src/VuFind/RecordDriver/MarcReaderTrait.php +++ b/module/VuFind/src/VuFind/RecordDriver/MarcReaderTrait.php @@ -53,7 +53,7 @@ trait MarcReaderTrait /** * Get access to the raw File_MARC object. * - * @return \File_MARCBASE + * @return \File_MARC_Record */ public function getMarcRecord() { diff --git a/module/VuFind/src/VuFind/RecordDriver/Summon.php b/module/VuFind/src/VuFind/RecordDriver/Summon.php index 36b2114463adeeeca39160426c8dcafbb6103d4a..6ce14877bf1614e2389f4b8ba2ba7ea05343256b 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Summon.php +++ b/module/VuFind/src/VuFind/RecordDriver/Summon.php @@ -57,6 +57,35 @@ class Summon extends DefaultRecord */ protected $dateConverter = null; + /** + * Previous unique ID (if applicable). + * + * @var string + */ + protected $previousUniqueId = null; + + /** + * Get previous unique ID (or null if not applicable). + * + * @return string + */ + public function getPreviousUniqueId() + { + return $this->previousUniqueId; + } + + /** + * Set previous unique ID + * + * @param string $id ID to set + * + * @return void + */ + public function setPreviousUniqueId($id) + { + $this->previousUniqueId = $id; + } + /** * Get all subject headings associated with this record. Each heading is * returned as an array of chunks, increasing from least specific to most @@ -137,6 +166,19 @@ class Summon extends DefaultRecord $this->fields['Edition'][0] : ''; } + /** + * Get extra metadata to store in the resource table. In this instance, + * we use the BookMark value so that it can be used to recover expired + * records in favorite lists. + * + * @return string + */ + public function getExtraResourceMetadata() + { + return isset($this->fields['BookMark'][0]) + ? ['bookmark' => $this->fields['BookMark'][0]] : null; + } + /** * Get an array of all the formats associated with the record. * @@ -499,11 +541,9 @@ class Summon extends DefaultRecord public function getURLs() { if (isset($this->fields['link'])) { + $msg = $this->hasFullText() ? 'Get full text' : 'Get more information'; return [ - [ - 'url' => $this->fields['link'], - 'desc' => $this->translate('Get full text') - ] + ['url' => $this->fields['link'], 'desc' => $this->translate($msg)] ]; } $retVal = []; @@ -629,4 +669,24 @@ class Summon extends DefaultRecord } return $str; } + + /** + * Does this record have full text access? + * + * @return bool + */ + public function hasFullText() + { + return (bool)($this->fields['hasFullText'] ?? false); + } + + /** + * Is this an open access record? + * + * @return bool + */ + public function isOpenAccess() + { + return (bool)($this->fields['IsOpenAccess'] ?? false); + } } diff --git a/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php index cdff08a703a7f8818b751ce39561c8b8383c2209..9119a8fd6d26631ec3ea4c53ce2deddbefc05103 100644 --- a/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php +++ b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php @@ -68,7 +68,10 @@ abstract class AbstractBase implements DriverInterface */ public function getResolverUrl($openURL) { - return $this->baseUrl . '?' . $openURL; + $url = $this->baseUrl; + $url .= strpos($url, '?') === false ? '?' : '&'; + $url .= $openURL; + return $url; } /** diff --git a/module/VuFind/src/VuFind/Resolver/Driver/AbstractBaseFactory.php b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBaseFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..0b20abfada74d49920ba914c11425c5b214a07ff --- /dev/null +++ b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBaseFactory.php @@ -0,0 +1,67 @@ +<?php +/** + * Generic factory suitable for most resolver drivers. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Resolver_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\Resolver\Driver; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * Generic factory suitable for most resolver drivers. + * + * @category VuFind + * @package Resolver_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class AbstractBaseFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + $config = $container->get('VuFind\Config\PluginManager')->get('config'); + return new $requestedName( + $config->OpenURL->url, + ...($options ?: []) + ); + } +} diff --git a/module/VuFind/src/VuFind/Resolver/Driver/DriverWithHttpClientFactory.php b/module/VuFind/src/VuFind/Resolver/Driver/DriverWithHttpClientFactory.php index f9afb1ead8903020d64afc12bdfaca2c89009451..ecd7e14b920dfebc230a9c06231d0a6466bde1ef 100644 --- a/module/VuFind/src/VuFind/Resolver/Driver/DriverWithHttpClientFactory.php +++ b/module/VuFind/src/VuFind/Resolver/Driver/DriverWithHttpClientFactory.php @@ -28,7 +28,6 @@ namespace VuFind\Resolver\Driver; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; /** * Generic factory suitable for most resolver drivers. @@ -39,7 +38,7 @@ use Zend\ServiceManager\Factory\FactoryInterface; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ -class DriverWithHttpClientFactory implements FactoryInterface +class DriverWithHttpClientFactory extends AbstractBaseFactory { /** * Create an object @@ -58,11 +57,12 @@ class DriverWithHttpClientFactory implements FactoryInterface public function __invoke(ContainerInterface $container, $requestedName, array $options = null ) { - $config = $container->get('VuFind\Config\PluginManager')->get('config'); - return new $requestedName( - $config->OpenURL->url, - $container->get('VuFindHttp\HttpService')->createClient(), - ...($options ?: []) - ); + $client = $container->get('VuFindHttp\HttpService')->createClient(); + if ($options) { + array_unshift($options, $client); + } else { + $options = [$client]; + } + return parent::__invoke($container, $requestedName, $options); } } diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Generic.php b/module/VuFind/src/VuFind/Resolver/Driver/Generic.php new file mode 100644 index 0000000000000000000000000000000000000000..dc356d9a48794ae0fbc3a767c2037880ebfa27ab --- /dev/null +++ b/module/VuFind/src/VuFind/Resolver/Driver/Generic.php @@ -0,0 +1,69 @@ +<?php +/** + * Generic Link Resolver Driver + * + * PHP version 7 + * + * Copyright (C) The National Library of Finland 2018 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Resolver_Drivers + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki + */ +namespace VuFind\Resolver\Driver; + +/** + * Generic Link Resolver Driver + * + * @category VuFind + * @package Resolver_Drivers + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki + */ +class Generic extends AbstractBase +{ + /** + * Fetch Links + * + * Fetches a set of links corresponding to an OpenURL + * + * @param string $openURL openURL (url-encoded) + * + * @return string raw data returned by resolver + */ + public function fetchLinks($openURL) + { + return ''; + } + + /** + * Parse Links + * + * Parses an XML file returned by a link resolver + * and converts it to a standardised format for display + * + * @param string $url Data returned by fetchLinks + * + * @return array Array of values + */ + public function parseLinks($url) + { + return []; + } +} diff --git a/module/VuFind/src/VuFind/Resolver/Driver/PluginManager.php b/module/VuFind/src/VuFind/Resolver/Driver/PluginManager.php index dc9f1167f5043c707608dec3b9ba9cc675d60179..44380f9bfc67dce98a6efdbcec7343e973b0f496 100644 --- a/module/VuFind/src/VuFind/Resolver/Driver/PluginManager.php +++ b/module/VuFind/src/VuFind/Resolver/Driver/PluginManager.php @@ -50,6 +50,8 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'sfx' => 'VuFind\Resolver\Driver\Sfx', 'redi' => 'VuFind\Resolver\Driver\Redi', 'threesixtylink' => 'VuFind\Resolver\Driver\Threesixtylink', + 'generic' => 'VuFind\Resolver\Driver\Generic', + 'other' => 'generic' ]; /** @@ -68,6 +70,8 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'VuFind\Resolver\Driver\DriverWithHttpClientFactory', 'VuFind\Resolver\Driver\Redi' => 'VuFind\Resolver\Driver\DriverWithHttpClientFactory', + 'VuFind\Resolver\Driver\Generic' => + 'VuFind\Resolver\Driver\AbstractBaseFactory', ]; /** diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Redi.php b/module/VuFind/src/VuFind/Resolver/Driver/Redi.php index 6d4290d152500743375bef7ba781ae51ddae75a5..f240f5cbe41ef848dcba44e55a6f06f45e5a5fe4 100644 --- a/module/VuFind/src/VuFind/Resolver/Driver/Redi.php +++ b/module/VuFind/src/VuFind/Resolver/Driver/Redi.php @@ -81,7 +81,7 @@ class Redi extends AbstractBase */ public function fetchLinks($openURL) { - $url = $this->baseUrl . '?' . $openURL; + $url = $this->getResolverUrl($openURL); $feed = $this->httpClient->setUri($url)->send()->getBody(); return $feed; } diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php b/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php index 8d89d6d8f3f86fb8de131e2649a9f430a59b22dd..c1995c9dd8d091a65d2c9bf9ddf41e654cc83561 100644 --- a/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php +++ b/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php @@ -72,8 +72,9 @@ class Sfx extends AbstractBase public function fetchLinks($openURL) { // Make the call to SFX and load results - $url = $this->baseUrl . - '?sfx.response_type=multi_obj_detailed_xml&svc.fulltext=yes&' . $openURL; + $url = $this->getResolverUrl( + 'sfx.response_type=multi_obj_detailed_xml&svc.fulltext=yes&' . $openURL + ); $feed = $this->httpClient->setUri($url)->send()->getBody(); return $feed; } diff --git a/module/VuFind/src/VuFind/Search/Base/Options.php b/module/VuFind/src/VuFind/Search/Base/Options.php index 9e30bf8e117dcb271d21d8ead18bdfae22004d98..882024b6624c991d1a5d89a161d355216ea6742e 100644 --- a/module/VuFind/src/VuFind/Search/Base/Options.php +++ b/module/VuFind/src/VuFind/Search/Base/Options.php @@ -226,6 +226,13 @@ abstract class Options implements TranslatorAwareInterface */ protected $autocompleteEnabled = false; + /** + * Autocomplete auto submit setting + * + * @var bool + */ + protected $autocompleteAutoSubmit = true; + /** * Configuration file to read global settings from * @@ -709,6 +716,16 @@ abstract class Options implements TranslatorAwareInterface return $this->autocompleteEnabled; } + /** + * Should autocomplete auto submit? + * + * @return bool + */ + public function autocompleteAutoSubmit() + { + return $this->autocompleteAutoSubmit; + } + /** * Get a string of the listviewOption (full or tab). * diff --git a/module/VuFind/src/VuFind/Search/EDS/Options.php b/module/VuFind/src/VuFind/Search/EDS/Options.php index b14e00526eb0542f71e8767caa12c4b90722739d..5756231ac6be1159e4816f1cc62cdb9cdf5ce908 100644 --- a/module/VuFind/src/VuFind/Search/EDS/Options.php +++ b/module/VuFind/src/VuFind/Search/EDS/Options.php @@ -137,10 +137,14 @@ class Options extends \VuFind\Search\Base\Options $facetConf->Advanced_Facet_Settings->translated_facets->toArray() ); } - // Load autocomplete preference: + // Load autocomplete preferences: if (isset($searchSettings->Autocomplete->enabled)) { $this->autocompleteEnabled = $searchSettings->Autocomplete->enabled; } + if (isset($searchSettings->Autocomplete->auto_submit)) { + $this->autocompleteAutoSubmit + = $searchSettings->Autocomplete->auto_submit; + } } /** diff --git a/module/VuFind/src/VuFind/Search/EDS/Results.php b/module/VuFind/src/VuFind/Search/EDS/Results.php index 9d41785c130c01a51ab6a690d2d852abbc421722..2207f8773a71736571de995bf86e0458d7371fc5 100644 --- a/module/VuFind/src/VuFind/Search/EDS/Results.php +++ b/module/VuFind/src/VuFind/Search/EDS/Results.php @@ -57,12 +57,12 @@ class Results extends \VuFind\Search\Base\Results $this->responseFacets = $collection->getFacets(); $this->resultTotal = $collection->getTotal(); - //Add a publication date facet + // Add a publication date facet $this->responseFacets[] = [ - 'fieldName' => 'PublicationDate', - 'displayName' => 'PublicationDate', - 'displayText' => 'Publication Date', - 'counts' => [] + 'fieldName' => 'PublicationDate', + 'displayName' => 'PublicationDate', + 'displayText' => 'Publication Date', + 'counts' => [] ]; // Construct record drivers for all the items in the response: diff --git a/module/VuFind/src/VuFind/Search/Factory/LibGuidesBackendFactory.php b/module/VuFind/src/VuFind/Search/Factory/LibGuidesBackendFactory.php index 40437ccd5e1c1559e67b7851edf8d2fe974df5e4..e5cdf06beb824bce8061d06491ef5e076abd3477 100644 --- a/module/VuFind/src/VuFind/Search/Factory/LibGuidesBackendFactory.php +++ b/module/VuFind/src/VuFind/Search/Factory/LibGuidesBackendFactory.php @@ -102,8 +102,7 @@ class LibGuidesBackendFactory implements FactoryInterface */ protected function createBackend(Connector $connector) { - $defaultSearch = isset($this->libGuidesConfig->General->defaultSearch) - ? $this->libGuidesConfig->General->defaultSearch : null; + $defaultSearch = $this->libGuidesConfig->General->defaultSearch ?? null; $backend = new Backend( $connector, $this->createRecordCollectionFactory(), $defaultSearch ); @@ -120,20 +119,20 @@ class LibGuidesBackendFactory implements FactoryInterface protected function createConnector() { // Load credentials: - $iid = isset($this->libGuidesConfig->General->iid) - ? $this->libGuidesConfig->General->iid : null; + $iid = $this->libGuidesConfig->General->iid ?? null; // Pick version: - $ver = isset($this->libGuidesConfig->General->version) - ? $this->libGuidesConfig->General->version : 1; + $ver = $this->libGuidesConfig->General->version ?? 1; + + // Get base URI, if available: + $baseUrl = $this->libGuidesConfig->General->baseUrl ?? null; // Build HTTP client: $client = $this->serviceLocator->get('VuFindHttp\HttpService') - ->createClient(); - $timeout = isset($this->libGuidesConfig->General->timeout) - ? $this->libGuidesConfig->General->timeout : 30; + ->createClient($baseUrl); + $timeout = $this->libGuidesConfig->General->timeout ?? 30; $client->setOptions(['timeout' => $timeout]); - $connector = new Connector($iid, $client, $ver); + $connector = new Connector($iid, $client, $ver, $baseUrl); $connector->setLogger($this->logger); return $connector; } diff --git a/module/VuFind/src/VuFind/Search/Params/FacetLimitTrait.php b/module/VuFind/src/VuFind/Search/Params/FacetLimitTrait.php index e432d14469daf1d53d4485227c37caab729ed954..1e4e2727103e77c3da550bd15953bb77e53862d0 100644 --- a/module/VuFind/src/VuFind/Search/Params/FacetLimitTrait.php +++ b/module/VuFind/src/VuFind/Search/Params/FacetLimitTrait.php @@ -54,6 +54,13 @@ trait FacetLimitTrait */ protected $facetLimitByField = []; + /** + * Hierarchical facet limit when facets are requested. + * + * @var int|null + */ + protected $hierarchicalFacetLimit = null; + /** * Initialize facet limit from a Config object. * @@ -95,6 +102,28 @@ trait FacetLimitTrait $this->facetLimitByField = $new; } + /** + * Get current limit for hierarchical facets + * + * @return int + */ + public function getHierarchicalFacetLimit() + { + return $this->hierarchicalFacetLimit; + } + + /** + * Set limit for hierarchical facets + * + * @param int $limit New limit + * + * @return void + */ + public function setHierarchicalFacetLimit($limit) + { + $this->hierarchicalFacetLimit = $limit; + } + /** * Get the facet limit for the specified field. * @@ -104,6 +133,19 @@ trait FacetLimitTrait */ protected function getFacetLimitForField($field) { - return $this->facetLimitByField[$field] ?? $this->facetLimit; + $limit = $this->facetLimitByField[$field] ?? $this->facetLimit; + + // Check for a different limit for hierarchical facets: + if (null !== $this->hierarchicalFacetLimit + && $limit !== $this->hierarchicalFacetLimit + && is_callable([$this->getOptions(), 'getHierarchicalFacets']) + ) { + $hierarchicalFacets = $this->getOptions()->getHierarchicalFacets(); + if (in_array($field, $hierarchicalFacets)) { + $limit = $this->hierarchicalFacetLimit; + } + } + + return $limit; } } diff --git a/module/VuFind/src/VuFind/Search/Solr/Options.php b/module/VuFind/src/VuFind/Search/Solr/Options.php index 760b81e44b2d62026cd2f4ae58b7591697df8870..1a1bfc43f276c73ea7ff8c4cb9ea202205d88efe 100644 --- a/module/VuFind/src/VuFind/Search/Solr/Options.php +++ b/module/VuFind/src/VuFind/Search/Solr/Options.php @@ -208,10 +208,14 @@ class Options extends \VuFind\Search\Base\Options $this->highlight = true; } - // Load autocomplete preference: + // Load autocomplete preferences: if (isset($searchSettings->Autocomplete->enabled)) { $this->autocompleteEnabled = $searchSettings->Autocomplete->enabled; } + if (isset($searchSettings->Autocomplete->auto_submit)) { + $this->autocompleteAutoSubmit + = $searchSettings->Autocomplete->auto_submit; + } // Load shard settings if (isset($searchSettings->IndexShards) diff --git a/module/VuFind/src/VuFind/Session/ManagerFactory.php b/module/VuFind/src/VuFind/Session/ManagerFactory.php index 302aec1bf00b37e052f1a0188b587db7a9dd2b27..10757084262fd18370bbbf4e8645d144c01fd70c 100644 --- a/module/VuFind/src/VuFind/Session/ManagerFactory.php +++ b/module/VuFind/src/VuFind/Session/ManagerFactory.php @@ -54,10 +54,12 @@ class ManagerFactory implements FactoryInterface protected function getOptions(ContainerInterface $container) { $cookieManager = $container->get('VuFind\Cookie\CookieManager'); - $options = [ + // Set options only if we are not running from CLI + $options = 'cli' !== PHP_SAPI ? [ + 'cookie_httponly' => $cookieManager->isHttpOnly(), 'cookie_path' => $cookieManager->getPath(), 'cookie_secure' => $cookieManager->isSecure() - ]; + ] : []; $domain = $cookieManager->getDomain(); if (!empty($domain)) { diff --git a/module/VuFind/src/VuFind/Sitemap/Generator.php b/module/VuFind/src/VuFind/Sitemap/Generator.php index c891288689075b18b417133c41129d3f0472ee81..a04068cdd9536140a5a2a80ff08f43d5e56b8d31 100644 --- a/module/VuFind/src/VuFind/Sitemap/Generator.php +++ b/module/VuFind/src/VuFind/Sitemap/Generator.php @@ -31,6 +31,7 @@ use VuFind\Search\BackendManager; use VuFindSearch\Backend\Solr\Backend; use VuFindSearch\ParamBag; use Zend\Config\Config; +use Zend\Console\Console; /** * Class for generating sitemaps @@ -106,12 +107,19 @@ class Generator */ protected $warnings = []; + /** + * Verbose mode + * + * @var bool + */ + protected $verbose = false; + /** * Mode of retrieving IDs from the index (may be 'terms' or 'search') * * @var string */ - protected $retrievalMode = 'terms'; + protected $retrievalMode = 'search'; /** * Constructor @@ -152,6 +160,32 @@ class Generator } } + /** + * Get/set verbose mode + * + * @param bool $newMode New verbose mode + * + * @return bool Current or new verbose mode + */ + public function setVerbose($newMode = null) + { + if (null !== $newMode) { + $this->verbose = $newMode; + } + return $this->verbose; + } + + /** + * Get the current microtime, formatted to a number. + * + * @return float + */ + protected function getTime() + { + $time = explode(" ", microtime()); + return $time[1] + $time[0]; + } + /** * Generate the sitemaps based on settings established by the constructor. * @@ -159,6 +193,9 @@ class Generator */ public function generate() { + // Start timer: + $startTime = $this->getTime(); + // Initialize variable $currentPage = 1; @@ -175,6 +212,13 @@ class Generator // Set-up Sitemap Index $this->buildIndex($currentPage - 1); + + // Display total elapsed time in verbose mode: + if ($this->verbose) { + Console::writeLine( + 'Elapsed time (in seconds): ' . ($this->getTime() - $startTime) + ); + } } /** @@ -198,33 +242,40 @@ class Generator */ protected function generateForBackend(Backend $backend, $recordUrl, $currentPage) { - $lastTerm = ''; - $count = 0; + // Starting offset varies depending on retrieval mode: + $currentOffset = ($this->retrievalMode === 'terms') ? '' : '*'; + $recordCount = 0; while (true) { // Get IDs and break out of the loop if we've run out: - $ids = $this->getIdsFromBackend($backend, $lastTerm, $count); - if (empty($ids)) { + $result = $this->getIdsFromBackend($backend, $currentOffset); + if (empty($result['ids'])) { break; } + $currentOffset = $result['nextOffset']; // Write the current entry: $smf = $this->getNewSitemap(); - foreach ($ids as $item) { + foreach ($result['ids'] as $item) { $loc = htmlspecialchars($recordUrl . urlencode($item)); if (strpos($loc, 'http') === false) { $loc = 'http://' . $loc; } $smf->addUrl($loc); - $lastTerm = $item; } $filename = $this->getFilenameForPage($currentPage); if (false === $smf->write($filename)) { throw new \Exception("Problem writing $filename."); } - // Update counters: - $count += $this->countPerPage; + // Update total record count: + $recordCount += count($result['ids']); + + if ($this->verbose) { + Console::writeLine("Page $currentPage, $recordCount processed"); + } + + // Update counter: $currentPage++; } return $currentPage; @@ -233,18 +284,16 @@ class Generator /** * Retrieve a batch of IDs. * - * @param Backend $backend Search backend - * @param string $lastTerm Last term retrieved - * @param int $offset Number of terms previously retrieved + * @param Backend $backend Search backend + * @param string $currentOffset String representing progress through set * * @return array */ - protected function getIdsFromBackend(Backend $backend, $lastTerm, $offset) + protected function getIdsFromBackend(Backend $backend, $currentOffset) { - if ($this->retrievalMode == 'terms') { - return $this->getIdsFromBackendUsingTerms($backend, $lastTerm); - } - return $this->getIdsFromBackendUsingSearch($backend, $offset); + $method = $this->retrievalMode == 'terms' + ? 'getIdsFromBackendUsingTerms' : 'getIdsFromBackendUsingCursorMark'; + return $this->$method($backend, $currentOffset); } /** @@ -260,19 +309,28 @@ class Generator $key = $backend->getConnector()->getUniqueKey(); $info = $backend->terms($key, $lastTerm, $this->countPerPage) ->getFieldTerms($key); - return null === $info ? [] : array_keys($info->toArray()); + $ids = null === $info ? [] : array_keys($info->toArray()); + $nextOffset = empty($ids) ? null : $ids[count($ids) - 1]; + return compact('ids', 'nextOffset'); } /** - * Retrieve a batch of IDs using regular search. + * Retrieve a batch of IDs using a cursorMark. * - * @param Backend $backend Search backend - * @param int $offset Number of terms previously retrieved + * @param Backend $backend Search backend + * @param string $cursorMark cursorMark * * @return array */ - protected function getIdsFromBackendUsingSearch(Backend $backend, $offset) - { + protected function getIdsFromBackendUsingCursorMark(Backend $backend, $cursorMark + ) { + // If the previous cursor mark matches the current one, we're finished! + static $prevCursorMark = ''; + if ($cursorMark === $prevCursorMark) { + return ['ids' => [], 'cursorMark' => $cursorMark]; + } + $prevCursorMark = $cursorMark; + $connector = $backend->getConnector(); $key = $connector->getUniqueKey(); $params = new ParamBag( @@ -280,20 +338,23 @@ class Generator 'q' => '*:*', 'fl' => $key, 'rows' => $this->countPerPage, - 'start' => $offset, + 'start' => 0, // Always 0 when using a cursorMark 'wt' => 'json', 'sort' => $key . ' asc', + // Override any default timeAllowed since it cannot be used with + // cursorMark + 'timeAllowed' => -1, + 'cursorMark' => $cursorMark ] ); $raw = $connector->search($params); $result = json_decode($raw); $ids = []; - if (isset($result->response->docs)) { - foreach ($result->response->docs as $doc) { - $ids[] = $doc->$key; - } + $nextOffset = $result->nextCursorMark; + foreach ($result->response->docs ?? [] as $doc) { + $ids[] = $doc->$key; } - return $ids; + return compact('ids', 'nextOffset'); } /** @@ -382,11 +443,7 @@ class Generator protected function getBaseSitemapIndexUrl() { // Pick the appropriate base URL based on the configuration files: - if (!isset($this->config->SitemapIndex->baseSitemapUrl) - || empty($this->config->SitemapIndex->baseSitemapUrl) - ) { - return $this->baseUrl; - } - return $this->config->SitemapIndex->baseSitemapUrl; + return empty($this->config->SitemapIndex->baseSitemapUrl) + ? $this->baseUrl : $this->config->SitemapIndex->baseSitemapUrl; } } diff --git a/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php b/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php index b8eca57de70a06051c0ebcb40c116c20a2548832..00d20f359860aabfd1061a682581124979166194 100644 --- a/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php +++ b/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php @@ -83,10 +83,10 @@ abstract class AbstractSearch extends AbstractHelper if ($i++ > 0) { $html .= ', '; } - $html .= '<a href="' - . $results->getUrlQuery() - ->replaceTerm($term, $data['new_term'])->getParams() - . '">' . $view->escapeHtml($word) . '</a>'; + $href = $results->getUrlQuery() + ->replaceTerm($term, $data['new_term'])->getParams(); + $html .= '<a href="' . $href . '">' . $view->escapeHtml($word) + . '</a>'; if (isset($data['expand_term']) && !empty($data['expand_term'])) { $url = $results->getUrlQuery() ->replaceTerm($term, $data['expand_term'])->getParams(); diff --git a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php index 7859fd1460a390c6b0bc556f57e3cb020735719f..fdffed064ed0ae98bc22d7bb87c2dfa775e79758 100644 --- a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php +++ b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php @@ -65,8 +65,8 @@ class LayoutClass extends \VuFind\View\Helper\AbstractLayoutClass return ""; } return $this->sidebarOnLeft - ? 'offcanvas offcanvas-left flip' - : 'offcanvas offcanvas-right flip'; + ? 'offcanvas offcanvas-left' + : 'offcanvas offcanvas-right'; } } } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php index e13fdbd6ffa2ac0a485618bc4bdd7f94379534b7..f3e960898083197064752e0aadfa1bebd0019bb1 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php @@ -71,19 +71,12 @@ class AlphaBrowse extends \Zend\View\Helper\AbstractHelper return null; } - // Linking using bib ids is generally more reliable than doing searches for - // headings, but headings give shorter queries and don't look as strange. - if ($item['count'] < 5) { - $safeIds = array_map([$this, 'escapeForSolr'], $item['ids']); - $query = ['type' => 'ids', 'lookfor' => implode(' ', $safeIds)]; - if ($item['count'] == 1) { - $query['jumpto'] = 1; - } - } else { - $query = [ - 'type' => ucwords($source) . 'Browse', - 'lookfor' => $this->escapeForSolr($item['heading']), - ]; + $query = [ + 'type' => ucwords($source) . 'Browse', + 'lookfor' => $this->escapeForSolr($item['heading']), + ]; + if ($item['count'] == 1) { + $query['jumpto'] = 1; } return $this->url->__invoke('search-results', [], ['query' => $query]); } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Doi.php b/module/VuFind/src/VuFind/View/Helper/Root/Doi.php new file mode 100644 index 0000000000000000000000000000000000000000..de56f1c67342e93d980196deb5d8dc614d802886 --- /dev/null +++ b/module/VuFind/src/VuFind/View/Helper/Root/Doi.php @@ -0,0 +1,151 @@ +<?php +/** + * DOI view helper + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\View\Helper\Root; + +/** + * DOI view helper + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class Doi extends \Zend\View\Helper\AbstractHelper +{ + /** + * Context helper + * + * @var \VuFind\View\Helper\Root\Context + */ + protected $context; + + /** + * VuFind OpenURL configuration + * + * @var \Zend\Config\Config + */ + protected $config; + + /** + * Current RecordDriver + * + * @var \VuFind\RecordDriver + */ + protected $recordDriver; + + /** + * OpenURL context ('results', 'record' or 'holdings') + * + * @var string + */ + protected $area; + + /** + * Constructor + * + * @param Context $context Context helper + * @param \Zend\Config\Config $config VuFind OpenURL config + */ + public function __construct(Context $context, $config = null) + { + $this->context = $context; + $this->config = $config; + } + + /** + * Set up context for helper + * + * @param \VuFind\RecordDriver $driver The current record driver + * @param string $area DOI context ('results', 'record' + * or 'holdings' + * + * @return object + */ + public function __invoke($driver, $area) + { + $this->recordDriver = $driver; + $this->area = $area; + return $this; + } + + /** + * Public method to render the OpenURL template + * + * @param bool $imagebased Indicates if an image based link + * should be displayed or not (null for system default) + * + * @return string + */ + public function renderTemplate($imagebased = null) + { + // Build parameters needed to display the control: + $doi = $this->recordDriver->tryMethod('getCleanDOI'); + $params = compact('doi'); + + // Render the subtemplate: + return $this->context->__invoke($this->getView())->renderInContext( + 'Helpers/doi.phtml', $params + ); + } + + /** + * Does the configuration indicate that we should display DOI links in + * the specified context? + * + * @return bool + */ + protected function checkContext() + { + // Doesn't matter the target area if no resolver is specified: + if (empty($this->config->resolver)) { + return false; + } + + // If a setting exists, return that: + $key = 'show_in_' . $this->area; + if (isset($this->config->$key)) { + return $this->config->$key; + } + + // If we got this far, use the defaults -- true for results, false for + // everywhere else. + return $this->area == 'results'; + } + + /** + * Public method to check whether OpenURLs are active for current record + * + * @return bool + */ + public function isActive() + { + $doi = $this->recordDriver->tryMethod('getCleanDOI'); + return !empty($doi) && $this->checkContext(); + } +} diff --git a/module/VuFind/src/VuFind/View/Helper/Root/DoiFactory.php b/module/VuFind/src/VuFind/View/Helper/Root/DoiFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..b552966621c6510f2febe6326c08058b3ae9f7ea --- /dev/null +++ b/module/VuFind/src/VuFind/View/Helper/Root/DoiFactory.php @@ -0,0 +1,68 @@ +<?php +/** + * DOI helper factory. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\View\Helper\Root; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * DOI helper factory. + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class DoiFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + $config = $container->get('VuFind\Config\PluginManager')->get('config'); + $helpers = $container->get('ViewHelperManager'); + return new $requestedName($helpers->get('context'), $config->DOI ?? null); + } +} diff --git a/module/VuFind/src/VuFind/View/Helper/Root/GoogleAnalytics.php b/module/VuFind/src/VuFind/View/Helper/Root/GoogleAnalytics.php index e5e2daed54b841e19107a317633c1a3173d0c34a..fdd8f92e92983cb0d9389d7e5d2402df84fae764 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/GoogleAnalytics.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/GoogleAnalytics.php @@ -65,36 +65,17 @@ class GoogleAnalytics extends \Zend\View\Helper\AbstractHelper } /** - * Returns GA code (if active) or empty string if not. + * Returns GA Javascript code. * * @param string $customUrl override URL to send to Google Analytics * * @return string */ - public function __invoke($customUrl = false) + protected function getRawJavascript($customUrl = false) { - if (!$this->key) { - return ''; - } - if (!$this->universal) { - $code = 'var key = "' . $this->key . '";' . "\n" - . "var _gaq = _gaq || [];\n" - . "_gaq.push(['_setAccount', key]);\n"; - if ($customUrl) { - $code .= "_gaq.push(['_trackPageview', '" . $customUrl . "']);\n"; - } else { - $code .= "_gaq.push(['_trackPageview']);\n"; - } - $code .= "(function() {\n" - . "var ga = document.createElement('script'); " - . "ga.type = 'text/javascript'; ga.async = true;\n" - . "ga.src = ('https:' == document.location.protocol ? " - . "'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n" - . "var s = document.getElementsByTagName('script')[0]; " - . "s.parentNode.insertBefore(ga, s);\n" - . "})();"; - } else { - $code = '(function(i,s,o,g,r,a,m){' + // Simple case: Universal + if ($this->universal) { + return '(function(i,s,o,g,r,a,m){' . "i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){" . '(i[r].q=i[r].q||[]).push(arguments)},' . 'i[r].l=1*new Date();a=s.createElement(o),' @@ -105,6 +86,40 @@ class GoogleAnalytics extends \Zend\View\Helper\AbstractHelper . "ga('create', '{$this->key}', 'auto');" . "ga('send', 'pageview');"; } + + // Alternate (legacy) case: + $code = 'var key = "' . $this->key . '";' . "\n" + . "var _gaq = _gaq || [];\n" + . "_gaq.push(['_setAccount', key]);\n"; + if ($customUrl) { + $code .= "_gaq.push(['_trackPageview', '" . $customUrl . "']);\n"; + } else { + $code .= "_gaq.push(['_trackPageview']);\n"; + } + $code .= "(function() {\n" + . "var ga = document.createElement('script'); " + . "ga.type = 'text/javascript'; ga.async = true;\n" + . "ga.src = ('https:' == document.location.protocol ? " + . "'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n" + . "var s = document.getElementsByTagName('script')[0]; " + . "s.parentNode.insertBefore(ga, s);\n" + . "})();"; + return $code; + } + + /** + * Returns GA code (if active) or empty string if not. + * + * @param string $customUrl override URL to send to Google Analytics + * + * @return string + */ + public function __invoke($customUrl = false) + { + if (!$this->key) { + return ''; + } + $code = $this->getRawJavascript($customUrl); $inlineScript = $this->getView()->plugin('inlinescript'); return $inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $code, 'SET'); } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php b/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php index 1b3ff016cb21e29bfb3d4c626b1367091724fdee..26b32688a7eda2d997322ccf3fa5088d5e338827 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php @@ -85,13 +85,13 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper /** * Constructor * - * @param \VuFind\View\Helper\Root\Context $context Context helper - * @param array $openUrlRules VuFind OpenURL rules - * @param PluginManager $pluginManager Resolver plugin manager - * @param \Zend\Config\Config $config VuFind OpenURL config + * @param Context $context Context helper + * @param array $openUrlRules VuFind OpenURL rules + * @param PluginManager $pluginManager Resolver plugin manager + * @param \Zend\Config\Config $config VuFind OpenURL config */ - public function __construct(\VuFind\View\Helper\Root\Context $context, - $openUrlRules, PluginManager $pluginManager, $config = null + public function __construct(Context $context, $openUrlRules, + PluginManager $pluginManager, $config = null ) { $this->context = $context; $this->openUrlRules = $openUrlRules; @@ -100,9 +100,9 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper } /** - * Render appropriate UI controls for an OpenURL link. + * Set up context for helper * - * @param \VuFind\RecordDriver $driver The current recorddriver + * @param \VuFind\RecordDriver $driver The current record driver * @param string $area OpenURL context ('results', 'record' * or 'holdings' * diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Recommend.php b/module/VuFind/src/VuFind/View/Helper/Root/Recommend.php index e1f7dd3bf33d23a1f52f136b2bb4e791642b8666..5278cf3638f2e8c7624ebbefc2ab56c1e5a0010c 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/Recommend.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/Recommend.php @@ -27,6 +27,8 @@ */ namespace VuFind\View\Helper\Root; +use VuFind\Recommend\RecommendInterface; + /** * Recommendation module view helper * @@ -41,16 +43,22 @@ class Recommend extends AbstractClassBasedTemplateRenderer /** * Render the output of a recommendation module. * - * @param \VuFind\Recommend\RecommendInterface $recommend The recommendation - * object to render + * @param RecommendInterface $recommend The recommendation object to render + * @param string $location Recommendation location (side, top) + * @param int $index Index of the recommendation configuration * * @return string */ - public function __invoke($recommend) - { + public function __invoke(RecommendInterface $recommend, $location = null, + $index = null + ) { $template = 'Recommend/%s.phtml'; $className = get_class($recommend); - $context = ['recommend' => $recommend]; + $context = [ + 'recommend' => $recommend, + 'location' => $location, + 'configIndex' => $index + ]; return $this->renderClassTemplate($template, $className, $context); } } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Relais.php b/module/VuFind/src/VuFind/View/Helper/Root/Relais.php index f7c062aa925faf01cd8bd71eaa73da9658986f65..a79d6db6145cd95b50b7f80e87b1a8983cd6235a 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/Relais.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/Relais.php @@ -86,9 +86,10 @@ class Relais extends \Zend\View\Helper\AbstractHelper // Assemble and return URL: $separator = strstr($this->loginUrl, '?') === false ? '?' : '&'; $url = $this->loginUrl . $separator . 'query=' - . ($isbn ? 'isbn%3D' . urlencode($isbn) : 'ti%3D' . urlencode($title)); + . ($isbn ? 'isbn%3D' . rawurlencode($isbn) : 'ti%3D' + . rawurlencode($title)); if ($mainAuthor) { - $url .= '%20and%20au%3D' . urlencode($mainAuthor); + $url .= '%20and%20au%3D' . rawurlencode($mainAuthor); } return $url; } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php b/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php index 87f8bcb5d8b90565fd2ddf1408681d44deb5ea92..6e0eb666f4eadfa25121a31b8c0dd3395c6874d4 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php @@ -126,6 +126,19 @@ class SearchBox extends \Zend\View\Helper\AbstractHelper return false; } + /** + * Is autocomplete enabled for the current context? + * + * @param string $activeSearchClass Active search class ID + * + * @return bool + */ + public function autocompleteAutoSubmit($activeSearchClass) + { + $options = $this->optionsManager->get($activeSearchClass); + return $options->autocompleteAutoSubmit(); + } + /** * Are alphabrowse options configured to display in the search options * drop-down? diff --git a/module/VuFind/src/VuFind/XSLT/Processor.php b/module/VuFind/src/VuFind/XSLT/Processor.php index df99053ad84eb9d722cd06370bd1e62cf76a20e6..fd4f47cabdf01b4e5698afb07c2de19f7f385008 100644 --- a/module/VuFind/src/VuFind/XSLT/Processor.php +++ b/module/VuFind/src/VuFind/XSLT/Processor.php @@ -41,6 +41,29 @@ use XSLTProcessor; */ class Processor { + /** + * Locate an XSLT file and return its full path. + * + * @param string $xslt Filename + * + * @return string + * @throws \Exception + */ + protected static function findXslt($xslt) + { + $paths = [ + LOCAL_OVERRIDE_DIR . '/xsl/', + APPLICATION_PATH . '/module/VuFind/xsl/', + APPLICATION_PATH . '/xsl/', + ]; + foreach ($paths as $path) { + if (file_exists($path . $xslt)) { + return $path . $xslt; + } + } + throw new \Exception('Cannot locate ' . $xslt); + } + /** * Perform an XSLT transformation and return the results. * @@ -53,12 +76,14 @@ class Processor public static function process($xslt, $xml, $params = []) { $style = new DOMDocument(); - // TODO: support local overrides - $style->load(APPLICATION_PATH . '/module/VuFind/xsl/' . $xslt); + $style->load(static::findXslt($xslt)); $xsl = new XSLTProcessor(); $xsl->importStyleSheet($style); $doc = new DOMDocument(); - if ($doc->loadXML($xml)) { + $sanitizeXmlRegEx + = '[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+'; + $cleanXml = trim(preg_replace("/$sanitizeXmlRegEx/u", ' ', $xml)); + if ($doc->loadXML($cleanXml)) { foreach ($params as $key => $value) { $xsl->setParameter('', $key, $value); } diff --git a/module/VuFind/src/VuFindTest/Container/MockContainer.php b/module/VuFind/src/VuFindTest/Container/MockContainer.php new file mode 100644 index 0000000000000000000000000000000000000000..a24fa314c3a0f68c2658d37ac3a5a094392580d4 --- /dev/null +++ b/module/VuFind/src/VuFindTest/Container/MockContainer.php @@ -0,0 +1,150 @@ +<?php +/** + * Container that produces mock objects. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +namespace VuFindTest\Container; + +use Interop\Container\ContainerInterface; +use PHPUnit\Framework\TestCase; + +/** + * Container that produces mock objects. + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +class MockContainer implements ContainerInterface +{ + /** + * Disabled services. + * + * @var string[] + */ + protected $disabled = []; + + /** + * Services + * + * @var array + */ + protected $services = []; + + /** + * Test case (for building mock objects) + * + * @var TestCase + */ + protected $test; + + /** + * Constructor + * + * @param TestCase $test Test using the container + */ + public function __construct(TestCase $test) + { + $this->test = $test; + } + + /** + * Create a mock object. + * + * @param string $id Identifier of the service to mock out. + * @param array $methods Methods to mock. + * + * @return mixed + */ + public function createMock($id, $methods = []) + { + return $this->test->getMockBuilder($id) + ->disableOriginalConstructor() + ->setMethods($methods) + ->getMock(); + } + + /** + * Disable a service + * + * @param string $id Identifier of the entry to disable. + * + * @return MockContainer + */ + public function disable($id) + { + // Don't double-disable a service: + if ($this->has($id)) { + $this->disabled[] = $id; + } + // Fluent interface: + return $this; + } + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * + * @return mixed + */ + public function get($id) + { + if (!isset($this->services[$id])) { + $this->services[$id] = $this->createMock($id); + } + return $this->services[$id]; + } + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * @param string $id Identifier of the entry to look for. + * + * @return bool + */ + public function has($id) + { + // Assume every service exists unless explicitly disabled + return !in_array($id, $this->disabled); + } + + /** + * Explicitly set an entry in the container. + * + * @param string $id Identifier of the entry to set. + * @param mixed $obj The service to set. + * + * @return MockContainer + */ + public function set($id, $obj) + { + $this->services[$id] = $obj; + return $this; + } +} diff --git a/module/VuFind/src/VuFindTest/Unit/AjaxHandlerTest.php b/module/VuFind/src/VuFindTest/Unit/AjaxHandlerTest.php index 997fb9fbe6e359a303dbdd631d602f902422baea..56f87a259c1993aca378846495e1b19387577881 100644 --- a/module/VuFind/src/VuFindTest/Unit/AjaxHandlerTest.php +++ b/module/VuFind/src/VuFindTest/Unit/AjaxHandlerTest.php @@ -29,7 +29,6 @@ namespace VuFindTest\Unit; use Zend\Http\Request; use Zend\Mvc\Controller\Plugin\Params; -use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\Parameters; /** @@ -41,24 +40,8 @@ use Zend\Stdlib\Parameters; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org Main Page */ -abstract class AjaxHandlerTest extends \PHPUnit\Framework\TestCase +abstract class AjaxHandlerTest extends MockContainerTest { - /** - * Create a mock service. - * - * @param string $name Name of class implementing service - * @param array $methods Methods to mock - * - * @return object - */ - protected function getMockService($name, $methods = []) - { - return $this->getMockBuilder($name) - ->disableOriginalConstructor() - ->setMethods($methods) - ->getMock(); - } - /** * Create mock user object. * @@ -66,21 +49,7 @@ abstract class AjaxHandlerTest extends \PHPUnit\Framework\TestCase */ protected function getMockUser() { - return $this->getMockService('VuFind\Db\Row\User'); - } - - /** - * Add a service to a container. - * - * @param ServiceManager $container Container to populate - * @param string $name Name of service to create - * @param mixed $value Value of service (or null to create mock) - * - * @return void - */ - protected function addServiceToContainer($container, $name, $value = null) - { - $container->setService($name, $value ?? $this->getMockService($name)); + return $this->container->get('VuFind\Db\Row\User'); } /** @@ -92,7 +61,9 @@ abstract class AjaxHandlerTest extends \PHPUnit\Framework\TestCase */ protected function getMockAuthManager($user) { - $authManager = $this->getMockService('VuFind\Auth\Manager', ['isLoggedIn']); + $authManager = $this->container->createMock( + 'VuFind\Auth\Manager', ['isLoggedIn'] + ); $authManager->expects($this->any())->method('isLoggedIn') ->will($this->returnValue($user)); return $authManager; @@ -112,7 +83,7 @@ abstract class AjaxHandlerTest extends \PHPUnit\Framework\TestCase $request = new Request(); $request->setQuery(new Parameters($get)); $request->setPost(new Parameters($post)); - $controller = $this->getMockService( + $controller = $this->container->createMock( 'Zend\Mvc\Controller\AbstractActionController', ['getRequest'] ); $controller->expects($this->any())->method('getRequest') diff --git a/module/VuFind/src/VuFindTest/Unit/MockContainerTest.php b/module/VuFind/src/VuFindTest/Unit/MockContainerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..995f5b1073ff8d6d8c64ccffc4b1bf1dc00a081d --- /dev/null +++ b/module/VuFind/src/VuFindTest/Unit/MockContainerTest.php @@ -0,0 +1,59 @@ +<?php +/** + * Base class for tests using a MockContainer. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +namespace VuFindTest\Unit; + +use VuFindTest\Container\MockContainer; + +/** + * Base class for tests using a MockContainer. + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +abstract class MockContainerTest extends \PHPUnit\Framework\TestCase +{ + /** + * Mock container + * + * @var MockContainer + */ + protected $container; + + /** + * Standard setup method. + * + * @return void + */ + public function setUp() + { + $this->container = new MockContainer($this); + } +} diff --git a/module/VuFind/tests/bootstrap.php b/module/VuFind/tests/bootstrap.php index 2940cf01b56056d4031e5fc1567c9eba5fefe1ae..05bef2d6ab8e1119670aaa94d2bdd412d51094fc 100644 --- a/module/VuFind/tests/bootstrap.php +++ b/module/VuFind/tests/bootstrap.php @@ -1,8 +1,5 @@ <?php -// Set flag that we're in test mode -define('VUFIND_PHPUNIT_RUNNING', 1); - // Set path to this module define('VUFIND_PHPUNIT_MODULE_PATH', __DIR__); diff --git a/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json b/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json new file mode 100644 index 0000000000000000000000000000000000000000..e2f94972372797089da292a7e87ac801804aae63 --- /dev/null +++ b/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json @@ -0,0 +1,5 @@ +[ + { "status": 400 }, + { "headers": { "X-Okapi-Token": "x-okapi-token-after-invalid" } }, + { "body": "{ \"locations\": [] }" } +] diff --git a/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json b/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json new file mode 100644 index 0000000000000000000000000000000000000000..91a26fdc14d70cd7e2d63e36b8cd0e0c616cd2af --- /dev/null +++ b/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json @@ -0,0 +1,4 @@ +[ + { "status": 200 }, + { "body": "{ \"loans\": [] }" } +] diff --git a/module/VuFind/tests/fixtures/folio/responses/get-tokens.json b/module/VuFind/tests/fixtures/folio/responses/get-tokens.json new file mode 100644 index 0000000000000000000000000000000000000000..a740982265a3c933179ebdfe8d34d34a70439cfb --- /dev/null +++ b/module/VuFind/tests/fixtures/folio/responses/get-tokens.json @@ -0,0 +1,4 @@ +[ + { "headers": { "X-Okapi-Token": "x-okapi-token-config-tenant" } }, + { "body": "{ \"users\": [ { \"id\": \"id\" } ] }" } +] diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php index 6e9e72d2529fd09198e80913c2a929cb6f28f89e..cd5f254522c48c94868385bd8db826a2077ca2ed 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php @@ -28,7 +28,6 @@ namespace VuFindTest\Auth; use VuFind\Auth\Shibboleth; -use VuFind\Db\Table\User; use Zend\Config\Config; /** diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Connection/SolrTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Connection/SolrTest.php index da9e16a34615c76d1482ea9dd7fc9b2452c1a6b4..a70422d95a8f096bff59ff5f8d10ca3f21c8431b 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Connection/SolrTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Connection/SolrTest.php @@ -27,6 +27,8 @@ */ namespace VuFindTest\Integration\Connection; +use VuFindSearch\ParamBag; + /** * Solr Connection Test Class * @@ -60,11 +62,12 @@ class SolrTest extends \VuFindTest\Unit\TestCase { $solr = $this->getServiceManager()->get('VuFind\Search\BackendManager') ->get('Solr'); - $result = $solr->alphabeticBrowse('author', 'Dublin Society', 0, 1); + $extras = new ParamBag(['extras' => 'id']); + $result = $solr->alphabeticBrowse('author', 'Dublin Society', 0, 1, $extras); $item = $result['Browse']['items'][0]; - $this->assertEquals($item['count'], count($item['ids'])); + $this->assertEquals($item['count'], count($item['extras']['id'])); $this->assertTrue(empty($item['useInstead'])); - $this->assertTrue(in_array('vtls000013187', $item['ids'])); + $this->assertTrue(in_array(['vtls000013187'], $item['extras']['id'])); $this->assertTrue(in_array('Royal Dublin Society', $item['seeAlso'])); $this->assertEquals('Dublin Society', $item['heading']); } @@ -78,10 +81,12 @@ class SolrTest extends \VuFindTest\Unit\TestCase { $solr = $this->getServiceManager()->get('VuFind\Search\BackendManager') ->get('Solr'); - $result = $solr->alphabeticBrowse('author', 'Dublin Society, Royal', 0, 1); + $extras = new ParamBag(['extras' => 'id']); + $result = $solr + ->alphabeticBrowse('author', 'Dublin Society, Royal', 0, 1, $extras); $item = $result['Browse']['items'][0]; $this->assertEquals(0, $item['count']); - $this->assertEquals($item['count'], count($item['ids'])); + $this->assertEquals($item['count'], count($item['extras']['id'])); $this->assertEquals('Dublin Society, Royal', $item['heading']); $this->assertTrue(empty($item['seeAlso'])); $this->assertTrue(in_array('Royal Dublin Society', $item['useInstead'])); @@ -96,15 +101,16 @@ class SolrTest extends \VuFindTest\Unit\TestCase { $solr = $this->getServiceManager()->get('VuFind\Search\BackendManager') ->get('Solr'); - $result = $solr->alphabeticBrowse('dewey', '123.45 .I39', 0, 1); + $extras = new ParamBag(['extras' => 'id']); + $result = $solr->alphabeticBrowse('dewey', '123.45 .I39', 0, 1, $extras); $item = $result['Browse']['items'][0]; $this->assertEquals(1, $item['count']); - $this->assertEquals($item['count'], count($item['ids'])); + $this->assertEquals($item['count'], count($item['extras']['id'])); $this->assertEquals('123.45 .I39', $item['heading']); - $result = $solr->alphabeticBrowse('dewey', '123.46 .Q39', 0, 1); + $result = $solr->alphabeticBrowse('dewey', '123.46 .Q39', 0, 1, $extras); $item = $result['Browse']['items'][0]; $this->assertEquals(1, $item['count']); - $this->assertEquals($item['count'], count($item['ids'])); + $this->assertEquals($item['count'], count($item['extras']['id'])); $this->assertEquals('123.46 .Q39', $item['heading']); } diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FeedbackTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FeedbackTest.php index bda8668755aab33ced0597c696676ee74f56397d..b816448e040ec3804f647f4bcb41a0c89724fdc9 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FeedbackTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FeedbackTest.php @@ -107,7 +107,7 @@ class FeedbackTest extends \VuFindTest\Unit\MinkTestCase $this->findCss($page, '#modal .form-control[name="name"]')->setValue('Me'); $this->findCss($page, '#modal .form-control[name="email"]') ->setValue('test@test.com'); - $this->findCss($page, "#modal #comments")->setValue('test test test'); + $this->findCss($page, "#modal #message")->setValue('test test test'); $this->findCss($page, '#modal input[type="submit"]')->click(); $this->snooze(); $this->assertEquals( diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CheckRequestIsValidTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CheckRequestIsValidTest.php index 17079e4996861705a9310830ca68779294fb03e8..4b3b2938825cce2b05a514bf3d7431c01f7278cc 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CheckRequestIsValidTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CheckRequestIsValidTest.php @@ -30,9 +30,8 @@ namespace VuFindTest\AjaxHandler; use VuFind\AjaxHandler\AbstractIlsAndUserActionFactory; use VuFind\AjaxHandler\CheckRequestIsValid; use VuFind\Auth\ILSAuthenticator; +use VuFind\Auth\Manager; use VuFind\ILS\Connection; -use VuFind\Session\Settings; -use Zend\ServiceManager\ServiceManager; /** * CheckRequestIsValid test class. @@ -48,33 +47,18 @@ class CheckRequestIsValidTest extends \VuFindTest\Unit\AjaxHandlerTest /** * Set up a CheckRequestIsValid handler for testing. * - * @param Settings $ss Session settings (or null for default) - * @param Connection $ils ILS connection (or null for default) - * @param ILSAuthenticator $ilsAuth ILS authenticator (or null for default) - * @param User|bool $user Return value for isLoggedIn() in auth manager + * @param User|bool $user Return value for isLoggedIn() in auth manager * * @return CheckRequestIsValid */ - protected function getHandler($ss = null, $ils = null, $ilsAuth = null, - $user = false - ) { - // Create container - $container = new ServiceManager(); - - // Install or mock up services: - $this->addServiceToContainer($container, 'VuFind\Session\Settings', $ss); - $this->addServiceToContainer($container, 'VuFind\ILS\Connection', $ils); - $this->addServiceToContainer( - $container, 'VuFind\Auth\ILSAuthenticator', $ilsAuth - ); - + protected function getHandler($user = false) + { // Set up auth manager with user: - $authManager = $this->getMockAuthManager($user); - $container->setService('VuFind\Auth\Manager', $authManager); + $this->container->set(Manager::class, $this->getMockAuthManager($user)); // Build the handler: $factory = new AbstractIlsAndUserActionFactory(); - return $factory($container, CheckRequestIsValid::class); + return $factory($this->container, CheckRequestIsValid::class); } /** @@ -98,7 +82,7 @@ class CheckRequestIsValidTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testEmptyQuery() { - $handler = $this->getHandler(null, null, null, $this->getMockUser()); + $handler = $this->getHandler($this->getMockUser()); $this->assertEquals( ['bulk_error_missing', 400], $handler->handleRequest($this->getParamsHelper()) @@ -112,17 +96,17 @@ class CheckRequestIsValidTest extends \VuFindTest\Unit\AjaxHandlerTest */ protected function runSuccessfulTest($ilsMethod, $requestType = null) { - $ilsAuth = $this->getMockService( - 'VuFind\Auth\ILSAuthenticator', ['storedCatalogLogin'] - ); + $ilsAuth = $this->container + ->createMock(ILSAuthenticator::class, ['storedCatalogLogin']); $ilsAuth->expects($this->once())->method('storedCatalogLogin') ->will($this->returnValue([3])); - $ils = $this - ->getMockService('VuFind\ILS\Connection', [$ilsMethod]); + $ils = $this->container->createMock(Connection::class, [$ilsMethod]); $ils->expects($this->once())->method($ilsMethod) ->with($this->equalTo(1), $this->equalTo(2), $this->equalTo([3])) ->will($this->returnValue(true)); - $handler = $this->getHandler(null, $ils, $ilsAuth, $this->getMockUser()); + $this->container->set(Connection::class, $ils); + $this->container->set(ILSAuthenticator::class, $ilsAuth); + $handler = $this->getHandler($this->getMockUser()); $params = ['id' => 1, 'data' => 2, 'requestType' => $requestType]; return $handler->handleRequest($this->getParamsHelper($params)); } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CommentRecordTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CommentRecordTest.php index b2676de64988bab07e3cc74da0fe1c63735a8a66..e30aaf0a0887289ef524b4cf84a4e37cb19c0735 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CommentRecordTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/CommentRecordTest.php @@ -29,11 +29,10 @@ namespace VuFindTest\AjaxHandler; use VuFind\AjaxHandler\CommentRecord; use VuFind\AjaxHandler\CommentRecordFactory; -use VuFind\Controller\Plugin\Recaptcha; +use VuFind\Config\AccountCapabilities; use VuFind\Db\Row\Resource; use VuFind\Db\Row\User; use VuFind\Db\Table\Resource as ResourceTable; -use Zend\ServiceManager\ServiceManager; /** * CommentRecord test class. @@ -49,46 +48,32 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest /** * Set up a CommentRecord handler for testing. * - * @param ResourceTable $table Resource table mock (or null for default) - * @param Recaptcha $recaptcha Recaptcha plugin mock (or null for default) - * @param bool $enabled Are comments enabled? - * @param User|bool $user Return value for isLoggedIn() in auth manager + * @param bool $enabled Are comments enabled? + * @param User|bool $user Return value for isLoggedIn() in auth manager * * @return CommentRecord */ - protected function getHandler($table = null, $recaptcha = null, $enabled = true, - $user = false - ) { - // Create container - $container = new ServiceManager(); - + protected function getHandler($enabled = true, $user = false) + { // For simplicity, let the top-level container stand in for the plugin // managers: - $container->setService('VuFind\Db\Table\PluginManager', $container); - $container->setService('ControllerPluginManager', $container); - - // Install or mock up remaining services: - $this->addServiceToContainer( - $container, 'VuFind\Db\Table\Resource', $table - ); - $this->addServiceToContainer( - $container, 'VuFind\Controller\Plugin\Recaptcha', $recaptcha - ); + $this->container->set('VuFind\Db\Table\PluginManager', $this->container); + $this->container->set('ControllerPluginManager', $this->container); // Set up auth manager with user: $authManager = $this->getMockAuthManager($user); - $container->setService('VuFind\Auth\Manager', $authManager); + $this->container->set('VuFind\Auth\Manager', $authManager); // Set up capability configuration: $cfg = new \Zend\Config\Config( ['Social' => ['comments' => $enabled ? 'enabled' : 'disabled']] ); - $capabilities = new \VuFind\Config\AccountCapabilities($cfg, $authManager); - $container->setService('VuFind\Config\AccountCapabilities', $capabilities); + $capabilities = new AccountCapabilities($cfg, $authManager); + $this->container->set(AccountCapabilities::class, $capabilities); // Build the handler: $factory = new CommentRecordFactory(); - return $factory($container, CommentRecord::class); + return $factory($this->container, CommentRecord::class); } /** @@ -101,7 +86,7 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest */ protected function getMockResource($comment, $user) { - $row = $this->getMockService('VuFind\Db\Row\Resource', ['addComment']); + $row = $this->container->createMock(Resource::class, ['addComment']); $row->expects($this->once())->method('addComment') ->with($this->equalTo($comment), $this->equalTo($user)) ->will($this->returnValue(true)); @@ -115,7 +100,7 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testDisabledResponse() { - $handler = $this->getHandler(null, null, false); + $handler = $this->getHandler(false); $this->assertEquals( ['Comments disabled', 400], $handler->handleRequest($this->getParamsHelper()) @@ -129,7 +114,7 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testLoggedOutUser() { - $handler = $this->getHandler(null, null, true); + $handler = $this->getHandler(true); $this->assertEquals( ['You must be logged in first', 401], $handler->handleRequest($this->getParamsHelper()) @@ -143,7 +128,7 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testEmptyQuery() { - $handler = $this->getHandler(null, null, true, $this->getMockUser()); + $handler = $this->getHandler(true, $this->getMockUser()); $this->assertEquals( ['bulk_error_missing', 400], $handler->handleRequest($this->getParamsHelper()) @@ -158,11 +143,13 @@ class CommentRecordTest extends \VuFindTest\Unit\AjaxHandlerTest public function testSuccessfulTransaction() { $user = $this->getMockUser(); - $table = $this->getMockService('VuFind\Db\Table\Resource', ['findResource']); + $table = $this->container + ->createMock(ResourceTable::class, ['findResource']); $table->expects($this->once())->method('findResource') ->with($this->equalTo('foo'), $this->equalTo('Solr')) ->will($this->returnValue($this->getMockResource('bar', $user))); - $handler = $this->getHandler($table, null, true, $user); + $this->container->set(ResourceTable::class, $table); + $handler = $this->getHandler(true, $user); $post = [ 'id' => 'foo', 'comment' => 'bar', diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/DoiLookupTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/DoiLookupTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a043d269477802e8bd64fbac2de575c60c132b47 --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/DoiLookupTest.php @@ -0,0 +1,78 @@ +<?php +/** + * DoiLookup test class. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +namespace VuFindTest\AjaxHandler; + +use VuFind\AjaxHandler\DoiLookup; +use VuFind\AjaxHandler\DoiLookupFactory; +use VuFind\Config\PluginManager as ConfigManager; +use VuFind\DoiLinker\DoiLinkerInterface; +use VuFind\DoiLinker\PluginManager; +use Zend\Config\Config; + +/** + * DoiLookup test class. + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +class DoiLookupTest extends \VuFindTest\Unit\AjaxHandlerTest +{ + /** + * Test a DOI lookup. + * + * @return void + */ + public function testLookup() + { + // Set up config manager: + $config = new Config(['DOI' => ['resolver' => 'foo']]); + $cm = $this->container->createMock(ConfigManager::class, ['get']); + $cm->expects($this->once())->method('get')->with($this->equalTo('config')) + ->will($this->returnValue($config)); + $this->container->set(ConfigManager::class, $cm); + + // Set up plugin manager: + $pm = new PluginManager($this->container); + $mockPlugin = $this->container + ->createMock(DoiLinkerInterface::class, ['getLinks']); + $mockPlugin->expects($this->once())->method('getLinks') + ->with($this->equalTo(['bar'])) + ->will($this->returnValue(['bar' => 'baz'])); + $pm->setService('foo', $mockPlugin); + $this->container->set(PluginManager::class, $pm); + + // Test the handler: + $factory = new DoiLookupFactory(); + $handler = $factory($this->container, DoiLookup::class); + $params = $this->getParamsHelper(['doi' => ['bar']]); + $this->assertEquals([['bar' => 'baz']], $handler->handleRequest($params)); + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/KeepAliveTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/KeepAliveTest.php index 0fa748c52cfd2fb95060314c4a775af9ebe1d2aa..7334e6f0cc36e046af50b7572fdebbbc394a822a 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/KeepAliveTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/KeepAliveTest.php @@ -29,6 +29,7 @@ namespace VuFindTest\AjaxHandler; use VuFind\AjaxHandler\KeepAlive; use VuFind\AjaxHandler\KeepAliveFactory; +use Zend\Session\SessionManager; /** * KeepAlive test class. @@ -48,12 +49,11 @@ class KeepAliveTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testResponse() { - $sm = $this->getMockService('Zend\Session\SessionManager', ['getId']); + $sm = $this->container->createMock(SessionManager::class, ['getId']); $sm->expects($this->once())->method('getId'); - $container = new \Zend\ServiceManager\ServiceManager(); - $container->setService('Zend\Session\SessionManager', $sm); + $this->container->set(SessionManager::class, $sm); $factory = new KeepAliveFactory(); - $handler = $factory($container, KeepAlive::class); + $handler = $factory($this->container, KeepAlive::class); $params = new \Zend\Mvc\Controller\Plugin\Params(); $this->assertEquals([true], $handler->handleRequest($params)); } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/RecommendTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/RecommendTest.php index c6330d1f44af7f0928581896305d4153e16597a4..d07c83dc503315c040895098e6119623d20f2cbf 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/RecommendTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/AjaxHandler/RecommendTest.php @@ -28,6 +28,14 @@ namespace VuFindTest\AjaxHandler; use VuFind\AjaxHandler\Recommend; +use VuFind\AjaxHandler\RecommendFactory; +use VuFind\Recommend\PluginManager; +use VuFind\Recommend\RecommendInterface; +use VuFind\Search\Results\PluginManager as ResultsManager; +use VuFind\Search\Solr\Results; +use VuFind\Session\Settings; +use VuFind\View\Helper\Root\Recommend as RecommendHelper; +use Zend\View\Renderer\PhpRenderer; /** * Recommend test class. @@ -47,20 +55,37 @@ class RecommendTest extends \VuFindTest\Unit\AjaxHandlerTest */ public function testResponse() { - $ss = $this->getMockService('VuFind\Session\Settings', ['disableWrite']); + // Set up session settings: + $ss = $this->container->createMock(Settings::class, ['disableWrite']); $ss->expects($this->once())->method('disableWrite'); - $mockPlugin = $this->getMockService('VuFind\Recommend\RecommendInterface'); - $rm = $this->getMockService('VuFind\Recommend\PluginManager', ['get']); + $this->container->set(Settings::class, $ss); + + // Set up recommend plugin manager: + $mockPlugin = $this->container->createMock(RecommendInterface::class); + $rm = $this->container->createMock(PluginManager::class, ['get']); $rm->expects($this->once())->method('get')->with($this->equalTo('foo')) ->will($this->returnValue($mockPlugin)); - $r = $this->getMockService('VuFind\Search\Solr\Results'); - $viewHelper = $this->getMockService('VuFind\View\Helper\Root\Recommend'); - $view = $this - ->getMockService('Zend\View\Renderer\PhpRenderer', ['plugin']); + $this->container->set(PluginManager::class, $rm); + + // Set up results plugin manager: + $resultsManager = $this->container + ->createMock(ResultsManager::class, ['get']); + $resultsManager->expects($this->once())->method('get') + ->with($this->equalTo('Solr')) + ->will($this->returnValue($this->container->createMock(Results::class))); + $this->container->set(ResultsManager::class, $resultsManager); + + // Set up view helper and renderer: + $viewHelper = $this->container->createMock(RecommendHelper::class); + $view = $this->container->createMock(PhpRenderer::class, ['plugin']); $view->expects($this->once())->method('plugin') ->with($this->equalTo('recommend')) ->will($this->returnValue($viewHelper)); - $handler = new Recommend($ss, $rm, $r, $view); + $this->container->set('ViewRenderer', $view); + + // Build and test the ajax handler: + $factory = new RecommendFactory(); + $handler = $factory($this->container, Recommend::class); $params = $this->getParamsHelper(['mod' => 'foo']); $this->assertEquals([null], $handler->handleRequest($params)); } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/MultiAuthTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/MultiAuthTest.php index 9742ad92698819fd8b2b7df0d7604318a0e07c8b..24d3f1a26c47f076c7624649a20821e465ec3694 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/MultiAuthTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/MultiAuthTest.php @@ -27,7 +27,6 @@ */ namespace VuFindTest\Auth; -use VuFind\Auth\MultiAuth; use Zend\Config\Config; /** diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php index b1f8057cc224137af57a4674be34ccf56a1609d6..c5f3c76b752eeacfd9bb5bf27593e7a5f5755e74 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php @@ -73,11 +73,11 @@ class CartTest extends \PHPUnit\Framework\TestCase * @return CookieManager */ protected function getMockCookieManager($cookies = [], $path = '/', - $domain = null, $secure = false + $domain = null, $secure = false, $httpOnly = false ) { return $this->getMockBuilder('VuFind\Cookie\CookieManager') ->setMethods(['set']) - ->setConstructorArgs([$cookies, $path, $domain, $secure]) + ->setConstructorArgs([$cookies, $path, $domain, $secure, $httpOnly]) ->getMock(); } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0961fcd91c6073ce1b26af5d20622a23a7e826af --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Form/FormTest.php @@ -0,0 +1,191 @@ +<?php +/** + * Form Test Class + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\Form; + +use VuFind\Config\YamlReader; +use VuFind\Form\Form; + +/** + * Form Test Class + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class FormTest extends \VuFindTest\Unit\TestCase +{ + /** + * Test defaults with no configuration. + * + * @return void + */ + public function testDefaultsWithoutConfiguration() + { + $form = new Form(new YamlReader()); + $this->assertTrue($form->isEnabled()); + $this->assertTrue($form->useCaptcha()); + $this->assertFalse($form->showOnlyForLoggedUsers()); + $this->assertEquals([], $form->getElements()); + $this->assertEquals([null, null], $form->getRecipient()); + $this->assertNull($form->getTitle()); + $this->assertNull($form->getHelp()); + $this->assertEquals('VuFind Feedback', $form->getEmailSubject([])); + $this->assertEquals( + 'Thank you for your feedback.', $form->getSubmitResponse() + ); + $this->assertEquals([[], 'Email/form.phtml'], $form->formatEmailMessage([])); + $this->assertEquals( + 'Zend\InputFilter\InputFilter', get_class($form->getInputFilter()) + ); + } + + /** + * Test defaults with defaults passed to constructor. + * + * @return void + */ + public function testDefaultsWithConfiguration() + { + $defaults = [ + 'recipient_email' => 'me@example.com', + 'recipient_name' => 'me', + 'email_subject' => 'subject', + ]; + $form = new Form(new YamlReader(), $defaults); + $this->assertEquals(['me', 'me@example.com'], $form->getRecipient()); + $this->assertEquals('subject', $form->getEmailSubject([])); + } + + /** + * Test that the class blocks unknown form IDs. + * + * @return void + * + * @expectedException VuFind\Exception\RecordMissing + * @expectedExceptionMessage Form 'foo' not found + */ + public function testUndefinedFormId() + { + $form = new Form(new YamlReader()); + $form->setFormId('foo'); + } + + /** + * Test defaults with no configuration. + * + * @return void + */ + public function testDefaultsWithFormSet() + { + $form = new Form(new YamlReader()); + $form->setFormId('FeedbackSite'); + $this->assertTrue($form->isEnabled()); + $this->assertTrue($form->useCaptcha()); + $this->assertFalse($form->showOnlyForLoggedUsers()); + $this->assertEquals( + [ + [ + 'type' => 'textarea', + 'name' => 'message', + 'required' => true, + 'label' => 'Comments', + 'settings' => ['cols' => 50, 'rows' => 8], + ], + [ + 'type' => 'text', + 'name' => 'name', + 'group' => '__sender__', + 'label' => 'feedback_name', + 'settings' => ['size' => 50], + ], + [ + 'type' => 'email', + 'name' => 'email', + 'group' => '__sender__', + 'label' => 'feedback_email', + 'settings' => ['size' => 50], + ], + [ + 'type' => 'submit', + 'name' => 'submit', + 'label' => 'Send', + ], + ], + $form->getElements() + ); + $this->assertEquals([null, null], $form->getRecipient()); + $this->assertEquals('Send us your feedback!', $form->getTitle()); + $this->assertNull($form->getHelp()); + $this->assertEquals('VuFind Feedback', $form->getEmailSubject([])); + $this->assertEquals( + 'Thank you for your feedback.', $form->getSubmitResponse() + ); + $this->assertEquals( + [ + [ + 'Comments' => ['type' => 'textarea', 'value' => 'x'], + 'feedback_name' => ['type' => 'text', 'value' => 'y'], + 'feedback_email' => ['type' => 'email', 'value' => 'z@foo.com'], + ], + 'Email/form.phtml' + ], + $form->formatEmailMessage( + [ + 'message' => 'x', + 'name' => 'y', + 'email' => 'z@foo.com' + ] + ) + ); + $this->assertEquals( + 'Zend\InputFilter\InputFilter', get_class($form->getInputFilter()) + ); + + // Validators: Required field problems + $form->setData(['email' => 'foo@bar.com', 'message' => null]); + $this->assertFalse($form->isValid()); + $form->setData(['email' => 'foo@bar.com', 'message' => '']); + $this->assertFalse($form->isValid()); + + // Validators: Email problems + $form->setData(['email' => ' ', 'message' => 'message']); + $this->assertFalse($form->isValid()); + $form->setData(['email' => 'foo', 'message' => 'message']); + $this->assertFalse($form->isValid()); + $form->setData(['email' => 'foo@', 'message' => 'message']); + $this->assertFalse($form->isValid()); + $form->setData(['email' => 'foo@bar', 'message' => 'message']); + $this->assertFalse($form->isValid()); + + // Validators: Good data + $form->setData(['email' => 'foo@bar.com', 'message' => 'message']); + $this->assertTrue($form->isValid()); + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8242d4da2e9dbd144fcec604d2109d1f7b5763c7 --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php @@ -0,0 +1,192 @@ +<?php +/** + * ILS driver test + * + * PHP version 7 + * + * Copyright (C) Villanova University 2011. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Jochen Lienhard <lienhard@ub.uni-freiburg.de> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +namespace VuFindTest\ILS\Driver; + +use InvalidArgumentException; + +use VuFind\ILS\Driver\Folio; + +/** + * ILS driver test + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +class FolioTest extends \VuFindTest\Unit\TestCase +{ + protected $testConfig = [ + 'API' => [ + 'base_url' => 'localhost', + 'tenant' => 'config_tenant', + 'username' => 'config_username', + 'password' => 'config_password' + ] + ]; + + protected $testResponses = null; + + protected $testRequestLog = []; + + protected $driver = null; + + /** + * Replace makeRequest to inject test returns + * + * @param string $method GET/POST/PUT/DELETE/etc + * @param string $path API path (with a leading /) + * @param array $params Parameters object to be sent as data + * @param array $headers Additional headers + * + * @return \Zend\Http\Response + */ + public function mockMakeRequest($method = "GET", $path = "/", $params = [], $headers = []) + { + // Run preRequest + $httpHeaders = new \Zend\Http\Headers(); + $httpHeaders->addHeaders($headers); + list($httpHeaders, $params) = $this->driver->preRequest($httpHeaders, $params); + // Log request + $this->testRequestLog[] = [ + 'method' => $method, + 'path' => $path, + 'params' => $params, + 'headers' => $httpHeaders->toArray() + ]; + // Create response + $testResponse = array_shift($this->testResponses); + $response = new \Zend\Http\Response(); + $response->setStatusCode($testResponse['status'] ?? 200); + $response->setContent($testResponse['body'] ?? ''); + $response->getHeaders()->addHeaders($testResponse['headers'] ?? []); + return $response; + } + + /** + * Generate a new Folio driver to return responses set in a json fixture + * + * Overwrites $this->driver + * Uses session cache + */ + protected function createConnector($test) + { + // Setup test responses + $file = realpath( + __DIR__ . + '/../../../../../../tests/fixtures/folio/responses/' . $test . '.json' + ); + if (!is_string($file) || !file_exists($file) || !is_readable($file)) { + throw new InvalidArgumentException( + sprintf('Unable to load fixture file: %s ', $file) + ); + } + $this->testResponses = json_decode(file_get_contents($file), true); + // Reset log + $this->testRequestLog = []; + // Session factory + $factory = function ($namespace) { + $manager = new \Zend\Session\SessionManager(); + return new \Zend\Session\Container("Folio_$namespace", $manager); + }; + // Create a stub for the SomeClass class + $this->driver = $this->getMockBuilder(\VuFind\ILS\Driver\Folio::class) + ->setConstructorArgs([new \VuFind\Date\Converter(), $factory]) + ->setMethods(['makeRequest']) + ->getMock(); + // Configure the stub + $this->driver->setConfig($this->testConfig); + $this->driver->expects($this->any()) + ->method('makeRequest') + ->will($this->returnCallback([$this, 'mockMakeRequest'])); + $this->driver->init(); + } + + /** + * Request a token where one does not exist + */ + public function testTokens() + { + $this->createConnector('get-tokens'); // saves to $this->driver + $profile = $this->driver->getMyProfile(['username' => 'whatever']); + // Get token + // - Right URL + $this->assertEquals('/authn/login', $this->testRequestLog[0]['path']); + // - Right tenant + $this->assertEquals( + $this->testConfig['API']['tenant'], + $this->testRequestLog[0]['headers']['X-Okapi-Tenant'] + ); + // Profile request + // - Passed correct token + $this->assertEquals( + 'x-okapi-token-config-tenant', // from fixtures: get-tokens.json + $this->testRequestLog[1]['headers']['X-Okapi-Token'] + ); + } + + /** + * Check a valid token retrieved from session cache + */ + public function testCheckValidToken() + { + $this->createConnector('check-valid-token'); + $profile = $this->driver->getMyTransactions(['username' => 'whatever']); + // Check token + $this->assertEquals('/users', $this->testRequestLog[0]['path']); + // Move to method call + $this->assertEquals('/circulation/loans', $this->testRequestLog[1]['path']); + // - Passed correct token + $this->assertEquals( + 'x-okapi-token-config-tenant', // from fixtures: get-tokens.json (cached) + $this->testRequestLog[1]['headers']['X-Okapi-Token'] + ); + } + + /** + * Check and renew an invalid token retrieved from session cache + */ + public function testCheckInvalidToken() + { + $this->createConnector('check-invalid-token'); + $profile = $this->driver->getPickupLocations(['username' => 'whatever']); + // Check token + $this->assertEquals('/users', $this->testRequestLog[0]['path']); + // Request new token + $this->assertEquals('/authn/login', $this->testRequestLog[1]['path']); + // Move to method call + $this->assertEquals('/locations', $this->testRequestLog[2]['path']); + // - Passed correct token + $this->assertEquals( + 'x-okapi-token-after-invalid', // from fixtures: check-invalid-token.json + $this->testRequestLog[2]['headers']['X-Okapi-Token'] + ); + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php index b318f66506d28b3c4b3bd6eeb6d66f430e47ff45..510f548ca8376c90dff07fa07939addee60533db 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php @@ -103,14 +103,27 @@ class NoILSTest extends \VuFindTest\Unit\TestCase } /** - * Test that driver makes holdings visible when in MARC mode. + * Test that driver makes holdings visible when in custom mode. * * @return void */ - public function testMarcHoldingsVisibility() + public function testCustomHoldingsVisibility() { - $this->driver - ->setConfig(['settings' => ['useHoldings' => 'marc']]); + $this->driver->setConfig( + [ + 'settings' => ['useHoldings' => 'custom'], + 'Holdings' => [ + 'number' => 0, + 'availability' => false, + 'status' => 'foo', + 'use_unknown_message' => true, + 'location' => 'bar', + 'reserve' => 'N', + 'callnumber' => 'xyzzy', + 'barcode' => null, + ] + ] + ); $this->assertTrue($this->driver->hasHoldings('foo')); } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/OAI/ServerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/OAI/ServerTest.php index 028e50ba26121ac0b4defebee08d2f5c4feb354c..f575bdb8c4badd85a14df38525db412a15865b61 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/OAI/ServerTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/OAI/ServerTest.php @@ -70,7 +70,7 @@ class ServerTest extends \VuFindTest\Unit\TestCase $config['Site']['email'] = 'fake@example.com'; } - return new Server( + $server = new Server( $this->getMockResultsManager(), $this->getMockRecordLoader(), $this->getMockTableManager(), @@ -78,6 +78,8 @@ class ServerTest extends \VuFindTest\Unit\TestCase $baseURL, $params ); + $server->setRecordFormatter($this->getMockRecordFormatter()); + return $server; } /** @@ -115,4 +117,16 @@ class ServerTest extends \VuFindTest\Unit\TestCase ->disableOriginalConstructor() ->getMock(); } + + /** + * Get a mock record formatter + * + * @return \VuFindApi\Formatter\RecordFormatter + */ + protected function getMockRecordFormatter() + { + return $this->getMockBuilder('VuFindApi\Formatter\RecordFormatter') + ->disableOriginalConstructor() + ->getMock(); + } } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/ChecklistTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/ChecklistTest.php new file mode 100644 index 0000000000000000000000000000000000000000..35dd3bb025560c6576cfbd78909b90281ed4b5b0 --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/ChecklistTest.php @@ -0,0 +1,75 @@ +<?php + +/** + * Checklist tests. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2010. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\Record; + +use VuFind\Record\Checklist; + +/** + * Checklist tests. + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class ChecklistTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test checklists + * + * @return void + */ + public function testChecklist() + { + $list = new Checklist(['a', 'b', 'c']); + $this->assertFalse($list->hasChecked()); + $this->assertTrue($list->hasUnchecked()); + // Check only returns true the first time: + $this->assertTrue($list->check('b')); + $this->assertFalse($list->check('b')); + // Not in list: + $this->assertFalse($list->check('nope')); + // Check intermediate state: + $this->assertEquals(['a', 'c'], $list->getUnchecked()); + $this->assertEquals(['b'], $list->getChecked()); + $this->assertTrue($list->hasChecked()); + $this->assertTrue($list->hasUnchecked()); + // Can't uncheck unchecked value: + $this->assertFalse($list->uncheck('c')); + // Check rest of list: + $this->assertTrue($list->check('a')); + $this->assertTrue($list->check('c')); + $this->assertFalse($list->hasUnchecked()); + // Now uncheck something: + $this->assertTrue($list->uncheck('b')); + $this->assertEquals(['a', 'c'], $list->getChecked()); + $this->assertEquals(['b'], $list->getUnchecked()); + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a119ecf76c682d7192ba99ef8ef95ad16494033b --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/DefaultRecordTest.php @@ -0,0 +1,408 @@ +<?php +/** + * DefaultRecord Record Driver Test Class + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\RecordDriver; + +use VuFind\RecordDriver\DefaultRecord; +use VuFind\RecordDriver\Response\PublicationDetails; + +/** + * DefaultRecord Record Driver Test Class + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class DefaultRecordTest extends \VuFindTest\Unit\TestCase +{ + /** + * Test getPublicationDates for a record. + * + * @return void + */ + public function testGetPublicationDates() + { + $pubDates = ['1992']; + $this->assertEquals($pubDates, $this->getDriver()->getPublicationDates()); + } + + /** + * Test getCoordinateLabels for a record. + * + * @return void + */ + public function testGetCoordinateLabels() + { + $coordinateLabels = []; + $this->assertEquals($coordinateLabels, $this->getDriver()->getCoordinateLabels()); + } + + /** + * Test getDisplayCoordinates for a record. + * + * @return void + */ + public function testGetDisplayCoordinates() + { + $displayCoordinates = []; + $this->assertEquals($displayCoordinates, $this->getDriver()->getDisplayCoordinates()); + } + + /** + * Test getDisplayCoordinates for a record. + * + * @return void + */ + public function testGetGeoLocation() + { + $geoLoc = []; + $this->assertEquals($geoLoc, $this->getDriver()->getGeoLocation()); + } + + /** + * Test getSchemaOrgFormats for a record. + * + * @return void + */ + public function testGetSchemaOrgFormats() + { + $formats = "Book"; + $this->assertEquals($formats, $this->getDriver()->getSchemaOrgFormats()); + } + + /** + * Test getSortTitle for a record. + * + * @return void + */ + public function testGetSortTitle() + { + $this->assertEquals("congiura dei principi napoletani 1701 :(prima e seconda stesura)", $this->getDriver()->getSortTitle()); + } + + /** + * Test getContainerReference for a record. + * + * @return void + */ + public function testGetContainerReference() + { + $this->assertEquals("", $this->getDriver()->getContainerReference()); + } + + /** + * Test getThumbnail for a record. + * + * @return void + */ + public function testGetThumbnail() + { + $thumbnail = [ + 'author' => 'Vico, Giambattista, 1668-1744.', + 'callnumber' => '', + 'size' => 'small', + 'title' => 'La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) /', + 'recordid' => 'testbug2', + 'source' => 'Solr', + 'isbn' => '8820737493', + 'oclc' => '30585539']; + $this->assertEquals($thumbnail, $this->getDriver()->getThumbnail()); + } + + /** + * Test getURLs for a record. + * + * @return void + */ + public function testGetURLs() + { + $testURL = [['url' => "http://fictional.com/sample/url"]]; + $this->assertEquals($testURL, $this->getDriver()->getURLs()); + } + + /** + * Test getURLs for a record. + * + * @return void + */ + public function testGetTOC() + { + $this->assertEquals([], $this->getDriver()->getTOC()); + } + + /** + * Test getSummary for a record. + * + * @return void + */ + public function testGetSummary() + { + $this->assertEquals([], $this->getDriver()->getSummary()); + } + + /** + * Test getSubtitle for a record. + * + * @return void + */ + public function testGetSubtitle() + { + $this->assertEquals('(prima e seconda stesura) /', $this->getDriver()->getSubtitle()); + } + + /** + * Test getSecondaryAuthorsRoles for a record. + * + * @return void + */ + public function testGetSecondaryAuthorsRoles() + { + $this->assertEquals([], $this->getDriver()->getSecondaryAuthorsRoles()); + } + + /** + * Test getSecondaryAuthors for a record. + * + * @return void + */ + public function testGetSecondaryAuthors() + { + $author2 = ["Pandolfi, Claudia."]; + $this->assertEquals($author2, $this->getDriver()->getSecondaryAuthors()); + } + + /** + * Test getPublicationDetails for a record. + * + * @return void + */ + public function testGetPublicationDetails() + { + $pubDetails = [new PublicationDetails("", "Centro di Studi Vichiani,", "1992")]; + $this->assertEquals($pubDetails, $this->getDriver()->getPublicationDetails()); + } + + /** + * Test getPrimaryAuthorsRoles for a record. + * + * @return void + */ + public function testGetPrimaryAuthorsRoles() + { + $this->assertEquals([], $this->getDriver()->getPrimaryAuthorsRoles()); + } + + /** + * Test getPrimaryAuthor for a record. + * + * @return void + */ + public function testGetPrimaryAuthor() + { + $this->assertEquals("Vico, Giambattista, 1668-1744.", $this->getDriver()->getPrimaryAuthor()); + } + + /** + * Test getPreviousTitles for a record. + * + * @return void + */ + public function testGetPreviousTitles() + { + $this->assertEquals([], $this->getDriver()->getPreviousTitles()); + } + + /** + * Test getPhysicalDescriptions for a record. + * + * @return void + */ + public function testGetPhysicalDescriptions() + { + $physical[0] = "296 p. : ill. ; 24 cm."; + $this->assertEquals($physical, $this->getDriver()->getPhysicalDescriptions()); + } + + /** + * Test getCoinsOpenUrl for a record. + * + * @return void + */ + public function testGetCoinsOpenUrl() + { + $coinsOpenUrl = "url_ver=Z39.88-2004&ctx_ver=Z39.88-2004&ctx_enc=info%3Aofi%2Fenc%3A" + . "UTF-8&rfr_id=info%3Asid%2Fvufind.svn.sourceforge.net%3Agenerator&rft.title=La+co" + . "ngiura+dei+Principi+Napoletani+1701+%3A+%28prima+e+seconda+stesura%29+%2F&rft.da" + . "te=1992&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&rft.genre=book&rft.btitl" + . "e=La+congiura+dei+Principi+Napoletani+1701+%3A+%28prima+e+seconda+stesura%29+%2F" + . "&rft.series=Vico%2C+Giambattista%2C+1668-1744.+Works.+1982+%3B&rft.au=Vico%2C+Gi" + . "ambattista%2C+1668-1744.&rft.pub=Centro+di+Studi+Vichiani%2C&rft.edition=Fiction" + . "al+edition.&rft.isbn=8820737493"; + $this->assertEquals($coinsOpenUrl, $this->getDriver()->getCoinsOpenUrl()); + } + + /** + * Test getNewerTitles for a record. + * + * @return void + */ + public function testGetNewerTitles() + { + $this->assertEquals([], $this->getDriver()->getNewerTitles()); + } + + /** + * Test getLCCN for a record. + * + * @return void + */ + public function testGetLCCN() + { + $this->assertEquals("", $this->getDriver()->getLCCN()); + } + + /** + * Test getInstitutions for a record. + * + * @return void + */ + public function testGetInstitutions() + { + $institution = ["MyInstitution"]; + $this->assertEquals($institution, $this->getDriver()->getInstitutions()); + } + + /** + * Test getLastIndexed for a record. + * + * @return void + */ + public function testGetLastIndexed() + { + $this->assertEquals("", $this->getDriver()->getLastIndexed()); + } + + /** + * Test getPrimaryAuthorsWithHighlighting for a record. + * + * @return void + */ + public function testGetPrimaryAuthorsWithHighlighting() + { + $primAuthHighlight = ["Vico, Giambattista, 1668-1744."]; + $this->assertEquals($primAuthHighlight, $this->getDriver()->getPrimaryAuthorsWithHighlighting()); + } + + /** + * Test getDateSpan for a record. + * + * @return void + */ + public function testGetDateSpan() + { + $this->assertEquals([], $this->getDriver()->getDateSpan()); + } + + /** + * Test getCorporateAuthorsRoles for a record. + * + * @return void + */ + public function testGetCorporateAuthorsRoles() + { + $this->assertEquals([], $this->getDriver()->getCorporateAuthorsRoles()); + } + + /** + * Test getCorporateAuthors for a record. + * + * @return void + */ + public function testGetCorporateAuthors() + { + $this->assertEquals([], $this->getDriver()->getCorporateAuthors()); + } + + /** + * Test getCleanDOI for a record. + * + * @return void + */ + public function testGetCleanDOI() + { + $cleanDOI = false; + $this->assertEquals($cleanDOI, $this->getDriver()->getCleanDOI()); + } + + /** + * Test getCallNumber for a record. + * + * @return void + */ + public function testGetCallNumber() + { + $this->assertEquals("", $this->getDriver()->getCallNumber()); + } + + /** + * Test getBreadcrumb for a record. + * + * @return void + */ + public function testGetBreadcrumb() + { + $breadcrumb = "La congiura dei Principi Napoletani 1701 :"; + $this->assertEquals($breadcrumb, $this->getDriver()->getBreadcrumb()); + } + + /** + * Get a record driver with fake data. + * + * @param array $overrides Fixture fields to override. + * + * @return SolrDefault + */ + protected function getDriver($overrides = []) + { + $fixture = json_decode( + file_get_contents( + realpath( + VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/testbug2.json' + ) + ), + true + ); + + $record = new DefaultRecord(); + $record->setRawData($overrides + $fixture['response']['docs'][0]); + return $record; + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EDSTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EDSTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8f42bd0c9a0c6638eccb79118f3ec535bfbc058b --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EDSTest.php @@ -0,0 +1,306 @@ +<?php +/** + * EDS Record Driver Test Class + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\RecordDriver; + +use VuFind\RecordDriver\EDS; + +/** + * EDS Record Driver Test Class + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class EDSTest extends \VuFindTest\Unit\TestCase +{ + /** + * Test exportDisabled for a record. + * + * @return void + */ + public function testExportDisabled() + { + $this->assertEquals(true, $this->getDriver()->exportDisabled('endnote')); + } + + /** + * Test getUniqueID for a record. + * + * @return void + */ + public function testGetUniqueID() + { + $overrides = [ + 'Header' => ['DbId' => 'TDB123', 'An' => 'TAn456'] + ]; + $driver = $this->getDriver($overrides); + $this->assertEquals('TDB123,TAn456', $driver->getUniqueID()); + } + + /** + * Test getShortTitle for a record. + * + * @return void + */ + public function testGetShortTitle() + { + $this->assertEquals('', $this->getDriver()->getShortTitle()); + } + + /** + * Test getItemsAbstract for a record. + * + * @return void + */ + public function testGetItemsAbstract() + { + $this->assertEquals('', $this->getDriver()->getItemsAbstract()); + } + + /** + * Test getAccessLevel for a record. + * + * @return void + */ + public function testGetAccessLevel() + { + $this->assertEquals('', $this->getDriver()->getAccessLevel()); + } + + /** + * Test getItemsAuthors for a record. + * + * @return void + */ + public function testGetItemsAuthors() + { + $this->assertEquals('', $this->getDriver()->getItemsAuthors()); + } + + /** + * Test getCustomLinks for a record. + * + * @return void + */ + public function testGetCustomLinks() + { + $this->assertEquals([], $this->getDriver()->getCustomLinks()); + } + + /** + * Test getFTCustomLinks for a record. + * + * @return void + */ + public function testGetFTCustomLinks() + { + $this->assertEquals([], $this->getDriver()->getFTCustomLinks()); + } + + /** + * Test getDbLabel for a record. + * + * @return void + */ + public function testGetDbLabel() + { + $this->assertEquals('', $this->getDriver()->getDbLabel()); + } + + /** + * Test getHTMLFullText for a record. + * + * @return void + */ + public function testGetHTMLFullText() + { + $this->assertEquals('', $this->getDriver()->getHTMLFullText()); + } + + /** + * Test hasHTMLFullTextAvailable for a record. + * + * @return void + */ + public function testHasHTMLFullTextAvailable() + { + $this->assertEquals(false, $this->getDriver()->hasHTMLFullTextAvailable()); + } + + /** + * Test getItems for a record. + * + * @return void + */ + public function testGetItems() + { + $this->assertEquals([], $this->getDriver()->getItems()); + } + + /** + * Test getPLink for a record. + * + * @return void + */ + public function testGetPLink() + { + $this->assertEquals('', $this->getDriver()->getPLink()); + } + + /** + * Test getPubType for a record. + * + * @return void + */ + public function testGetPubType() + { + $this->assertEquals('', $this->getDriver()->getPubType()); + } + + /** + * Test getPubTypeId for a record. + * + * @return void + */ + public function testGetPubTypeId() + { + $this->assertEquals('', $this->getDriver()->getPubTypeId()); + } + + /** + * Test hasPdfAvailable for a record. + * + * @return void + */ + public function testHasPdfAvailable() + { + $this->assertEquals(false, $this->getDriver()->hasPdfAvailable()); + } + + /** + * Test getPdfLink for a record. + * + * @return void + */ + public function testGetPdfLink() + { + $this->assertEquals(false, $this->getDriver()->getPdfLink()); + } + + /** + * Test getItemsSubjects for a record. + * + * @return void + */ + public function testGetItemsSubjects() + { + $this->assertEquals('', $this->getDriver()->getItemsSubjects()); + } + + /** + * Test getThumbnail for a record. + * + * @return void + */ + public function testGetThumbnail() + { + $this->assertEquals(false, $this->getDriver()->getThumbnail()); + } + + /** + * Test getItemsTitle for a record. + * + * @return void + */ + public function testGetItemsTitle() + { + $this->assertEquals('', $this->getDriver()->getItemsTitle()); + } + + /** + * Test getTitle for a record. + * + * @return void + */ + public function testGetTitle() + { + $this->assertEquals('', $this->getDriver()->getTitle()); + } + + /** + * Test getPrimaryAuthors for a record. + * + * @return void + */ + public function testGetPrimaryAuthors() + { + $this->assertEquals([], $this->getDriver()->getPrimaryAuthors()); + } + + /** + * Test getItemsTitleSource for a record. + * + * @return void + */ + public function testGetItemsTitleSource() + { + $this->assertEquals('', $this->getDriver()->getItemsTitleSource()); + } + + /** + * Test linkUrls for a record. + * + * @return void + */ + public function testLinkUrls() + { + $str = "http://fictional.com/sample/url"; + $this->assertEquals("<a href='" . $str . "'>" . $str . "</a>", $this->getDriver()->linkUrls($str)); + } + + /** + * Get a record driver with fake data. + * + * @param array $overrides Fixture fields to override. + * + * @return SolrDefault + */ + protected function getDriver($overrides = []) + { + // Simulate empty response for now: + $fixture = ['response' => ['docs' => [[]]]]; + + $record = new EDS(); + $record->setRawData($overrides + $fixture['response']['docs'][0]); + return $record; + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EITTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EITTest.php new file mode 100644 index 0000000000000000000000000000000000000000..368d27a004800e78925038954aef512bff7b84e6 --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/EITTest.php @@ -0,0 +1,140 @@ +<?php +/** + * EIT Record Driver Test Class + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\RecordDriver; + +use VuFind\RecordDriver\EIT; + +/** + * EIT Record Driver Test Class + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @author Sravanthi Adusumilli <vufind-tech@lists.sourceforge.net> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class EITTest extends \VuFindTest\Unit\TestCase +{ + /** + * Test getAllSubjectHeadings for a record. + * + * @return void + */ + public function testGetAllSubjectHeadings() + { + $this->assertEquals([], $this->getDriver()->getAllSubjectHeadings()); + } + + /** + * Test getBreadcrumb for a record. + * + * @return void + */ + public function testGetBreadcrumb() + { + $driver = $this->getDriver(); + $this->assertEquals('', $driver->getBreadcrumb()); + } + + /** + * Test getCleanISSN for a record. + * + * @return void + */ + public function testGetCleanISSN() + { + $this->assertEquals(false, $this->getDriver()->getCleanISSN()); + } + + /** + * Test getFormats for a record. + * + * @return void + */ + public function testGetFormats() + { + $this->assertEquals([], $this->getDriver()->getFormats()); + } + + /** + * Test getPrimaryAuthors for a record. + * + * @return void + */ + public function testGetPrimaryAuthors() + { + $this->assertEquals([], $this->getDriver()->getPrimaryAuthors()); + } + + /** + * Test getPublicationDates for a record. + * + * @return void + */ + public function testGetPublicationDates() + { + $this->assertEquals([], $this->getDriver()->getPublicationDates()); + } + + /** + * Test getPublishers for a record. + * + * @return void + */ + public function testGetPublishers() + { + $overrides = [ + 'header' => [ + 'controlInfo' => [ + 'pubinfo' => ['pub' => ['TestPublisher']] + ] + ] + ]; + $driver = $this->getDriver($overrides); + $this->assertEquals([['TestPublisher']], $driver->getPublishers()); + } + + /** + * Get a record driver with fake data. + * + * @param array $overrides Fixture fields to override. + * + * @return SolrDefault + */ + protected function getDriver($overrides = []) + { + // Simulate empty response for now: + $fixture = ['response' => ['docs' => [[]]]]; + + $record = new EIT(); + $record->setRawData($overrides + $fixture['response']['docs'][0]); + return $record; + } +} diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php index e01a7450d3888b728af5c373104eb44e171d7198..adc1f6ff9ec0fa3c1d216672198f02a8d4676109 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrDefaultTest.php @@ -54,6 +54,18 @@ class SolrDefaultTest extends \VuFindTest\Unit\TestCase $this->assertEquals('url_ver=Z39.88-2004&ctx_ver=Z39.88-2004&ctx_enc=info%3Aofi%2Fenc%3AUTF-8&rfr_id=info%3Asid%2Fvufind.svn.sourceforge.net%3Agenerator&rft.title=La+congiura+dei+Principi+Napoletani+1701+%3A+%28prima+e+seconda+stesura%29+%2F&rft.date=1992&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&rft.genre=book&rft.btitle=La+congiura+dei+Principi+Napoletani+1701+%3A+%28prima+e+seconda+stesura%29+%2F&rft.series=Vico%2C+Giambattista%2C+1668-1744.+Works.+1982+%3B&rft.au=Vico%2C+Giambattista%2C+1668-1744.&rft.pub=Centro+di+Studi+Vichiani%2C&rft.edition=Fictional+edition.&rft.isbn=8820737493', $driver->getOpenUrl()); } + /** + * Test a snippet caption. + * + * @return void + */ + public function testGetSnippetCaption() + { + $config = ['Snippet_Captions' => ['foo' => 'bar']]; + $driver = $this->getDriver([], $config); + $this->assertEquals('bar', $driver->getSnippetCaption('foo')); + } + /** * Test an OpenURL for an article. * @@ -117,14 +129,78 @@ XML; $this->assertEquals($expected, $xml); } + /** + * Test getContainerRecordID for a record. + * + * @return void + */ + public function testGetContainerRecordID() + { + $this->assertEquals("", $this->getDriver()->getContainerRecordID()); + } + + /** + * Test getChildRecordCount for a record. + * + * @return void + */ + public function testGetChildRecordCount() + { + $this->assertEquals(0, $this->getDriver()->getChildRecordCount()); + } + + /** + * Test getHighlightedTitle for a record. + * + * @return void + */ + public function testGetHighlightedTitle() + { + $this->assertEquals("", $this->getDriver()->getHighlightedTitle()); + } + + /** + * Test getHighlightedSnippet for a record. + * + * @return void + */ + public function testGetHighlightedSnippet() + { + $this->assertEquals(false, $this->getDriver()->getHighlightedSnippet()); + } + + /** + * Test HighlightDetails for a record. + * + * @return void + */ + public function testHighlightDetails() + { + $details['author'] = 'test'; + $driver = $this->getDriver(); + $driver->setHighlightDetails($details); + $this->assertEquals($details, $driver->getHighlightDetails()); + } + + /** + * Test getRawAuthorHighlights for a record. + * + * @return void + */ + public function testGetRawAuthorHighlights() + { + $this->assertEquals([], $this->getDriver()->getRawAuthorHighlights()); + } + /** * Get a record driver with fake data. * - * @param array $overrides Fixture fields to override. + * @param array $overrides Fixture fields to override. + * @param array $searchConfig Search configuration. * * @return SolrDefault */ - protected function getDriver($overrides = []) + protected function getDriver($overrides = [], $searchConfig = []) { $fixture = json_decode( file_get_contents( @@ -135,7 +211,7 @@ XML; true ); - $record = new SolrDefault(); + $record = new SolrDefault(null, null, new \Zend\Config\Config($searchConfig)); $record->setRawData($overrides + $fixture['response']['docs'][0]); return $record; } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/UserTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/UserTest.php index 276bc22651b8ac4a30cc129a883be4516fffbd60..d7db63f15b97e423715b7af3b5b98736c7b9060f 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/UserTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/UserTest.php @@ -91,7 +91,7 @@ class UserTest extends \VuFindTest\Unit\TestCase } /** - * Convenience method for executing similiar tests + * Convenience method for executing similar tests * * @param string $testuser Name of testuser * @param array $options Options like settings in permissions.ini diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php index 0e2622b0258bdfe5aa260d26bf33cd6358abca88..daa50dbeb2f7080b0e1a9737178593d936b70905 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php @@ -55,6 +55,7 @@ class RecordDataFormatterTest extends \VuFindTest\Unit\ViewHelperTestCase $this->getMockBuilder('VuFind\Auth\ILSAuthenticator')->disableOriginalConstructor()->getMock() ), 'context' => $context, + 'doi' => new \VuFind\View\Helper\Root\Doi($context), 'openUrl' => new \VuFind\View\Helper\Root\OpenUrl($context, [], $this->getMockBuilder('VuFind\Resolver\Driver\PluginManager')->disableOriginalConstructor()->getMock()), 'proxyUrl' => new \VuFind\View\Helper\Root\ProxyUrl(), 'record' => new \VuFind\View\Helper\Root\Record(), diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php index 5c431ad8c173dccf907d8924fe53a49acc31b1b8..ef019c79411179757d060cb9453724d4528a24be 100644 --- a/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php +++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php @@ -59,7 +59,7 @@ class AdminController extends AbstractAdmin $xml = false; if (isset($config->Index->url)) { $response = $this->serviceLocator->get('VuFindHttp\HttpService') - ->get($config->Index->url . '/admin/cores'); + ->get($config->Index->url . '/admin/cores?wt=xml'); $xml = $response->isSuccess() ? $response->getBody() : false; } $view = $this->createViewModel(); diff --git a/module/VuFindApi/config/module.config.php b/module/VuFindApi/config/module.config.php index 8b72c900a323a453107c2fa4440c24f655b3db03..1cdbb9823153f4457c779fdd532639e6835546e1 100644 --- a/module/VuFindApi/config/module.config.php +++ b/module/VuFindApi/config/module.config.php @@ -12,6 +12,12 @@ $config = [ 'SearchApi' => 'VuFindApi\Controller\SearchApiController', ], ], + 'service_manager' => [ + 'factories' => [ + 'VuFindApi\Formatter\FacetFormatter' => 'Zend\ServiceManager\Factory\InvokableFactory', + 'VuFindApi\Formatter\RecordFormatter' => 'VuFindApi\Formatter\RecordFormatterFactory', + ], + ], 'router' => [ 'routes' => [ 'apiHome' => [ diff --git a/module/VuFindApi/src/VuFindApi/Controller/Factory.php b/module/VuFindApi/src/VuFindApi/Controller/Factory.php index 0f95d5a5d1bed4677812c6e985b84c62fb4fa121..784099af9c82d6d1bb3e031c957569fa67e32c41 100644 --- a/module/VuFindApi/src/VuFindApi/Controller/Factory.php +++ b/module/VuFindApi/src/VuFindApi/Controller/Factory.php @@ -27,8 +27,6 @@ */ namespace VuFindApi\Controller; -use VuFindApi\Formatter\FacetFormatter; -use VuFindApi\Formatter\RecordFormatter; use Zend\ServiceManager\ServiceManager; /** @@ -67,11 +65,10 @@ class Factory */ public static function getSearchApiController(ServiceManager $sm) { - $recordFields = $sm->get('VuFind\Config\YamlReader') - ->get('SearchApiRecordFields.yaml'); - $helperManager = $sm->get('ViewHelperManager'); - $rf = new RecordFormatter($recordFields, $helperManager); - $controller = new SearchApiController($sm, $rf, new FacetFormatter()); - return $controller; + return new SearchApiController( + $sm, + $sm->get('VuFindApi\Formatter\RecordFormatter'), + $sm->get('VuFindApi\Formatter\FacetFormatter') + ); } } diff --git a/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php b/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php index 96588b0bfa4f6ce0e51b61199e6ce91493c15f50..9c7d843d49e429737cdd1459b52f5d4787ec2982 100644 --- a/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php +++ b/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php @@ -56,7 +56,10 @@ class BaseFormatter $this->resetArrayIndices($value); } - if ((is_array($value) && empty($value)) + // We don't want to return empty values -- unless it's an empty array + // with a non-numeric key, since the key could be significant (e.g. in + // the case of an author name => roles array with no assigned roles). + if ((is_numeric($key) && is_array($value) && empty($value)) || (is_bool($value) && !$value) || $value === null || $value === '' ) { diff --git a/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatterFactory.php b/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatterFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..84b1cc4c7d615a3522e7a2e8923517a0858ab30e --- /dev/null +++ b/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatterFactory.php @@ -0,0 +1,70 @@ +<?php +/** + * Record Formatter factory. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2018. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFindApi\Formatter; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * Record Formatter factory. + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class RecordFormatterFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + + $recordFields = $container->get('VuFind\Config\YamlReader') + ->get('SearchApiRecordFields.yaml'); + $helperManager = $container->get('ViewHelperManager'); + return new $requestedName($recordFields, $helperManager); + } +} diff --git a/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php index 686cfb894d947102266bc96b5d32bc80eaf862fe..169642533af2417f06ced1a9f9211a27f72b0609 100644 --- a/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php +++ b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php @@ -68,6 +68,7 @@ class RecordFormatterTest extends \VuFindTest\Unit\TestCase 'subjectsExtended' => [ 'vufind.method' => 'Formatter::getExtendedSubjectHeadings' ], + 'authors' => ['vufind.method' => 'getDeduplicatedAuthors'], ]; } @@ -121,6 +122,10 @@ class RecordFormatterTest extends \VuFindTest\Unit\TestCase 'spelling' => 's', 'Building' => ['foo', new TranslatableString('bar', 'xyzzy')], 'AllSubjectHeadings' => [['heading' => 'subject']], + 'DeduplicatedAuthors' => [ + 'primary' => ['Ms. A' => ['role' => ['Editor']]], + 'secondary' => ['Mr. B' => [], 'Mr. C' => []], + ], ] ); return $driver; @@ -158,6 +163,10 @@ class RecordFormatterTest extends \VuFindTest\Unit\TestCase 'buildings' => ['foo', ['value' => 'bar', 'translated' => 'xyzzy']], 'recordPage' => 'http://record', 'subjectsExtended' => [['heading' => 'subject']], + 'authors' => [ + 'primary' => ['Ms. A' => ['role' => ['Editor']]], + 'secondary' => ['Mr. B' => [], 'Mr. C' => []], + ], ], ]; $this->assertEquals($expected, $results); @@ -197,6 +206,7 @@ class RecordFormatterTest extends \VuFindTest\Unit\TestCase 'buildings' => [], 'recordPage' => [], 'subjectsExtended' => [], + 'authors' => [], ]; $this->assertEquals($expected, $results); } diff --git a/module/VuFindConsole/Module.php b/module/VuFindConsole/Module.php index bbcbf4f931733ae4d14e43a50783c623719c3bcd..b0462b1990aad2d3610c1658f30929a5d936cd2e 100644 --- a/module/VuFindConsole/Module.php +++ b/module/VuFindConsole/Module.php @@ -104,6 +104,7 @@ class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterfac 'generate extendclass' => 'Subclass a service, w/ lookup by class name', 'generate extendservice' => 'Override a service with a new child class', 'generate nontabrecordaction' => 'Add routes for non-tab record action', + 'generate plugin' => 'Create a new plugin class', 'generate recordroute' => 'Add a record route', 'generate staticroute' => 'Add a static route', 'generate theme' => 'Create and configure a new theme', diff --git a/module/VuFindConsole/config/module.config.php b/module/VuFindConsole/config/module.config.php index bdadb5389c7d8d86c9fe590e9cffd7c5d693e39e..584db8061e98068dd35211cf7f53e69b2a720159 100644 --- a/module/VuFindConsole/config/module.config.php +++ b/module/VuFindConsole/config/module.config.php @@ -55,6 +55,7 @@ $routes = [ 'generate/extendclass' => 'generate extendclass [--extendfactory] [<class>] [<target>]', 'generate/extendservice' => 'generate extendservice [<source>] [<target>]', 'generate/nontabrecordaction' => 'generate nontabrecordaction [<newAction>] [<module>]', + 'generate/plugin' => 'generate plugin [<class>] [<factory>]', 'generate/recordroute' => 'generate recordroute [<base>] [<newController>] [<module>]', 'generate/staticroute' => 'generate staticroute [<name>] [<module>]', 'generate/theme' => 'generate theme [<themename>]', @@ -77,7 +78,7 @@ $routes = [ 'util/expire_sessions' => 'util expire_sessions [--help|-h] [--batch=] [--sleep=] [<daysOld>]', 'util/index_reserves' => 'util index_reserves [--help|-h] [-d=s] [-t=s] [-f=s]', 'util/optimize' => 'util optimize [<core>]', - 'util/sitemap' => 'util sitemap', + 'util/sitemap' => 'util sitemap [--verbose]', 'util/suppressed' => 'util suppressed [--help|-h] [--authorities] [--outfile=s]', 'util/switch_db_hash' => 'util switch_db_hash [<newhash>] [<newkey>]', ]; diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php b/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php index 01252e446f5e7e0dd1a2122af42365468bb82b2f..aa190de726d9ddc2b7ec136a8d31f7df1215b6bf 100644 --- a/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php +++ b/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php @@ -222,6 +222,43 @@ class GenerateController extends AbstractBase return $this->getSuccessResponse(); } + /** + * Create a new plugin class + * + * @return \Zend\Console\Response + */ + public function pluginAction() + { + // Display help message if parameters missing: + $request = $this->getRequest(); + $class = $request->getParam('class'); + $factory = $request->getParam('factory'); + + if (empty($class)) { + Console::writeLine( + 'Usage: ' . $request->getScriptName() . ' generate plugin' + . ' [class_name] [factory]' + ); + Console::writeLine( + "\tclass_name - the name of the class you wish to create" + ); + Console::writeLine( + "\tfactory - an existing factory to use (omit to generate a new one)" + ); + return $this->getFailureResponse(); + } + + try { + $this->getGeneratorTools() + ->createPlugin($this->serviceLocator, $class, $factory); + } catch (\Exception $e) { + Console::writeLine($e->getMessage()); + return $this->getFailureResponse(); + } + + return $this->getSuccessResponse(); + } + /** * Add a new record route definition * diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php index d221d2cf2595ec733727589a80fc52ba0abea4bf..5d29961a9c520f4d0bc53e1a570858c4e9c0875e 100644 --- a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php +++ b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php @@ -283,6 +283,8 @@ class UtilController extends AbstractBase $this->serviceLocator->get('VuFind\Search\BackendManager'), $configLoader->get('config')->Site->url, $configLoader->get('sitemap') ); + $request = $this->getRequest(); + $generator->setVerbose($request->getParam('verbose', false)); $generator->generate(); foreach ($generator->getWarnings() as $warning) { Console::writeLine("$warning"); diff --git a/module/VuFindConsole/src/VuFindConsole/Generator/GeneratorTools.php b/module/VuFindConsole/src/VuFindConsole/Generator/GeneratorTools.php index 82732035c29dadd84ec704ecc7e43c342fca06e4..615112fb4e4268bdd5292b7afad994724c63715d 100644 --- a/module/VuFindConsole/src/VuFindConsole/Generator/GeneratorTools.php +++ b/module/VuFindConsole/src/VuFindConsole/Generator/GeneratorTools.php @@ -62,6 +62,124 @@ class GeneratorTools $this->config = $config; } + /** + * Create a plugin class. + * + * @param ContainerInterface $container Service manager + * @param string $class Class name to create + * @param string $factory Existing factory to use (null to + * generate a new one) + * + * @return bool + * @throws \Exception + */ + public function createPlugin(ContainerInterface $container, $class, + $factory = null + ) { + // Derive some key bits of information from the new class name: + $classParts = explode('\\', $class); + $module = $classParts[0]; + $shortName = strtolower(array_pop($classParts)); + $classParts[0] = 'VuFind'; + $classParts[] = 'PluginManager'; + $pmClass = implode('\\', $classParts); + // Set a flag for whether to generate a factory, and create class name + // if necessary. If existing factory specified, ensure it really exists. + if ($generateFactory = empty($factory)) { + $factory = $class . 'Factory'; + } elseif (!class_exists($factory)) { + throw new \Exception("Undefined factory: $factory"); + } + + // Figure out further information based on the plugin manager: + if (!$container->has($pmClass)) { + throw new \Exception('Cannot find expected plugin manager: ' . $pmClass); + } + $pm = $container->get($pmClass); + if (!method_exists($pm, 'getExpectedInterface')) { + throw new \Exception( + $pmClass . ' does not implement getExpectedInterface!' + ); + } + + // Force getExpectedInterface() to be public so we can read it: + $reflectionMethod = new \ReflectionMethod($pm, 'getExpectedInterface'); + $reflectionMethod->setAccessible(true); + $interface = $reflectionMethod->invoke($pm); + + // Figure out whether the plugin requirement is an interface or a + // parent class so we can create the right thing.... + if (interface_exists($interface)) { + $parent = null; + $interfaces = [$interface]; + } else { + $parent = $interface; + $interfaces = []; + } + $apmFactory = new \VuFind\ServiceManager\AbstractPluginManagerFactory(); + $pmKey = $apmFactory->getConfigKey(get_class($pm)); + $configPath = ['vufind', 'plugin_managers', $pmKey]; + + // Generate the classes and configuration: + $this->createClassInModule($class, $module, $parent, $interfaces); + if ($generateFactory) { + $this->generateFactory($class, $factory, $module); + } + $factoryPath = array_merge($configPath, ['factories', $class]); + $this->writeNewConfig($factoryPath, $factory, $module); + $aliasPath = array_merge($configPath, ['aliases', $shortName]); + // Don't back up the config twice -- the first backup from the previous + // write operation is sufficient. + $this->writeNewConfig($aliasPath, $class, $module, false); + + return true; + } + + /** + * Generate a factory class. + * + * @param string $class Name of class being built by factory + * @param string $factory Name of factory to generate + * @param string $module Name of module to generate factory within + * + * @return void + */ + protected function generateFactory($class, $factory, $module) + { + $this->createClassInModule( + $factory, $module, null, + ['Zend\ServiceManager\Factory\FactoryInterface'], + function ($generator) use ($class) { + $method = MethodGenerator::fromArray( + [ + 'name' => '__invoke', + 'body' => 'return new \\' . $class . '();', + ] + ); + $param1 = [ + 'name' => 'container', + 'type' => 'Interop\Container\ContainerInterface' + ]; + $param2 = [ + 'name' => 'requestedName', + ]; + $param3 = [ + 'name' => 'options', + 'type' => 'array', + 'defaultValue' => null, + ]; + $method->setParameters([$param1, $param2, $param3]); + // Copy doc block from this class' factory: + $reflection = new \Zend\Code\Reflection\MethodReflection( + GeneratorToolsFactory::class, '__invoke' + ); + $example = MethodGenerator::fromReflection($reflection); + $method->setDocBlock($example->getDocBlock()); + $generator->addMethods([$method]); + } + ); + } + /** * Extend a class defined somewhere in the service manager or its child * plugin managers. @@ -396,16 +514,22 @@ class GeneratorTools * Extend a specified class within a specified module. Return the name of * the new subclass. * - * @param string $class Name of class to create - * @param string $module Module in which to create the new class - * @param string $parent Parent class (null for no parent) + * @param string $class Name of class to create + * @param string $module Module in which to create the new class + * @param string $parent Parent class (null for no parent) + * @param string[] $interfaces Interfaces for class to implement + * @param \Callable $callback Callback to set up class generator * * @return void * @throws \Exception */ - protected function createClassInModule($class, $module, $parent = null) - { - $generator = new ClassGenerator($class, null, null, $parent); + protected function createClassInModule($class, $module, $parent = null, + array $interfaces = [], $callback = null + ) { + $generator = new ClassGenerator($class, null, null, $parent, $interfaces); + if (is_callable($callback)) { + $callback($generator); + } return $this->writeClass($generator, $module); } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Connector.php b/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Connector.php index 3a76f84b107d6135b307f7e8f0ba08daae9fda2f..61c37a47e0be8c9901766324849df65b5ba6e0a9 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Connector.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Connector.php @@ -87,6 +87,35 @@ class Connector implements \Zend\Log\LoggerAwareInterface $this->libraryId = $id; } + /** + * Perform a DOI lookup + * + * @param string $doi DOI + * @param bool $includeJournal Include journal data in response? + * + * @return mixed + */ + public function lookupDoi($doi, $includeJournal = false) + { + // Documentation says URL encoding of DOI is not necessary. + return $this->request( + 'articles/doi/' . $doi, + $includeJournal ? ['include' => 'journal'] : [] + ); + } + + /** + * Perform an ISSN lookup. + * + * @param string|array $issns ISSN(s) to look up. + * + * @return mixed + */ + public function lookupIssns($issns) + { + return $this->request('search', ['issns' => implode(',', (array)$issns)]); + } + /** * Perform a search * diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Response/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Response/RecordCollection.php index 533b90b89d6106825104b9ebcbcd8f33ff4ab59d..0e2dad1b9523a9ba48dcf7beb152d873a28067d4 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Response/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/BrowZine/Response/RecordCollection.php @@ -68,8 +68,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - return isset($this->response['recordCount']) - ? $this->response['recordCount'] : 0; + return $this->response['recordCount'] ?? 0; } /** @@ -90,7 +89,6 @@ class RecordCollection extends AbstractRecordCollection */ public function getOffset() { - return isset($this->response['offset']) - ? $this->response['offset'] : 0; + return $this->response['offset'] ?? 0; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php index e22d9da23123fe5fe9898c316cb4bb333a161662..cad62f92f8e54827dab2c7a16978061467d1d532 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php @@ -70,21 +70,21 @@ class Backend extends AbstractBackend * * @var string */ - protected $userName = null; + protected $userName; /** * Password for EBSCO EDS API account if using UID Authentication * * @var string */ - protected $password = null; + protected $password; /** * Profile for EBSCO EDS API account (may be overridden) * * @var string */ - protected $profile = null; + protected $profile; /** * Default profile for EBSCO EDS API account (taken from initial config and @@ -92,21 +92,21 @@ class Backend extends AbstractBackend * * @var string */ - protected $defaultProfile = null; + protected $defaultProfile; /** * Whether or not to use IP Authentication for communication with the EDS API * * @var bool */ - protected $ipAuth = false; + protected $ipAuth; /** * Organization EDS API requests are being made for * * @var string */ - protected $orgId = null; + protected $orgId; /** * Vufind Authentication manager @@ -158,23 +158,13 @@ class Backend extends AbstractBackend $this->isGuest = $isGuest; // Extract key values from configuration: - if (isset($config->EBSCO_Account->user_name)) { - $this->userName = $config->EBSCO_Account->user_name; - } - if (isset($config->EBSCO_Account->password)) { - $this->password = $config->EBSCO_Account->password; - } - if (isset($config->EBSCO_Account->ip_auth)) { - $this->ipAuth = $config->EBSCO_Account->ip_auth; - } - if (isset($config->EBSCO_Account->profile)) { - $this->profile = $config->EBSCO_Account->profile; - } - if (isset($config->EBSCO_Account->organization_id)) { - $this->orgId = $config->EBSCO_Account->organization_id; - } + $this->userName = $config->EBSCO_Account->user_name ?? null; + $this->password = $config->EBSCO_Account->password ?? null; + $this->ipAuth = $config->EBSCO_Account->ip_auth ?? false; + $this->profile = $config->EBSCO_Account->profile ?? null; + $this->orgId = $config->EBSCO_Account->organization_id ?? null; - // Save default profile value, since profile property may be overriden: + // Save default profile value, since profile property may be overridden: $this->defaultProfile = $this->profile; } @@ -271,7 +261,7 @@ class Backend extends AbstractBackend { try { $authenticationToken = $this->getAuthenticationToken(); - // check to see if the profile is overriden + // check to see if the profile is overridden $overrideProfile = (null !== $params) ? $params->get('profile') : null; if (isset($overrideProfile)) { $this->profile = $overrideProfile; diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Base.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Base.php index 344c442c00bf1b28a009f493bd6e1cbf255e33e7..373ccffc0f0e48b025721fd28613db18fe2db780 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Base.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Base.php @@ -87,7 +87,7 @@ abstract class Base * Sets up the EDS API Client * * @param array $settings Associative array of setting to use in - * conjunction with the EDS API + * conjunction with the EDS API * <ul> * <li>debug - boolean to control debug mode</li> * <li>orgid - Organization making calls to the EDS API </li> diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollection.php index 1bcf50be8b406d73a6ec6ce76500b842bff9a6e1..778455ef588fc5aa8ca24135d7e1f9a18ee989fc 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollection.php @@ -68,14 +68,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - $totalHits = 0; - if (isset($this->response['SearchResult']) - && isset($this->response['SearchResult']['Statistics']) - && isset($this->response['SearchResult']['Statistics']['TotalHits']) - ) { - $totalHits = $this->response['SearchResult']['Statistics']['TotalHits']; - } - return $totalHits; + return $this->response['SearchResult']['Statistics']['TotalHits'] ?? 0; } /** @@ -85,9 +78,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getRawFacets() { - return isset($this->response['SearchResult']) - && isset($this->response['SearchResult']['AvailableFacets']) - ? $this->response['SearchResult']['AvailableFacets'] : []; + return $this->response['SearchResult']['AvailableFacets'] ?? []; } /** @@ -98,9 +89,7 @@ class RecordCollection extends AbstractRecordCollection public function getFacets() { $vufindFacetList = []; - $facets = isset($this->response['SearchResult']) - && isset($this->response['SearchResult']['AvailableFacets']) - ? $this->response['SearchResult']['AvailableFacets'] : []; + $facets = $this->response['SearchResult']['AvailableFacets'] ?? []; foreach ($facets as $facet) { $vufindFacet['displayName'] = $facet['Id']; $vufindFacet['displayText'] = $facet['Label']; diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollectionFactory.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollectionFactory.php index 17ecf8d0992165b1d15c2d44f661bb081dd9e106..577e8558e53988b8a1be6773987af5a1ccaf9fa7 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollectionFactory.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Response/RecordCollectionFactory.php @@ -92,17 +92,10 @@ class RecordCollectionFactory implements RecordCollectionFactoryInterface ); } $collection = new $this->collectionClass($response); - //obtain path to records - $records = []; - if (isset($response['SearchResult']) - && isset($response['SearchResult']['Data']) - && isset($response['SearchResult']['Data']['Records']) - ) { - // Format of the search response - $records = $response['SearchResult']['Data']['Records']; - } elseif (isset($response['Records'])) { // Format of the retrieve response - $records = $response['Records']; - } + // Obtain path to records -- first try format of the search response, + // then try format of the retrieve response, then give up with empty array. + $records = $response['SearchResult']['Data']['Records'] + ?? $response['Records'] ?? []; foreach ($records as $record) { $collection->add(call_user_func($this->recordFactory, $record)); diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EIT/Response/XML/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/EIT/Response/XML/RecordCollection.php index 817462b11894f23efce8a5a9add7df0a8f8ef8d6..61afca4f70d30dd17501e390d3c5ee6330465edd 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/EIT/Response/XML/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/EIT/Response/XML/RecordCollection.php @@ -70,7 +70,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - return isset($this->response['total']) ? $this->response['total'] : 0; + return $this->response['total'] ?? 0; } /** @@ -90,6 +90,6 @@ class RecordCollection extends AbstractRecordCollection */ public function getOffset() { - return isset($this->response['offset']) ? $this->response['offset'] : 0; + return $this->response['offset'] ?? 0; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Connector.php b/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Connector.php index 6dd9f6e3a9b95427ab754669abedf847d4fa730c..2456a2219599eac39016c5ff128391a9f5bb6526 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Connector.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Connector.php @@ -81,14 +81,18 @@ class Connector implements \Zend\Log\LoggerAwareInterface * @param string $iid Institution ID * @param HttpClient $client HTTP client * @param float $apiVersion API version number + * @param string $baseUrl API base URL (optional) */ - public function __construct($iid, $client, $apiVersion = 1) + public function __construct($iid, $client, $apiVersion = 1, $baseUrl = null) { $this->apiVersion = $apiVersion; - if ($this->apiVersion < 2) { - $this->host = "http://api.libguides.com/api_search.php?"; + if (empty($baseUrl)) { + $this->host = ($this->apiVersion < 2) + ? "http://api.libguides.com/api_search.php?" + : "http://lgapi.libapps.com/widgets.php?"; } else { - $this->host = "http://lgapi.libapps.com/widgets.php?"; + // Ensure appropriate number of question marks: + $this->host = rtrim($baseUrl, '?') . '?'; } $this->iid = $iid; $this->client = $client; diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Response/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Response/RecordCollection.php index 247c6c045166a2641d91de18d4e35bbb76274db8..e95c61f4ea57f323e6128c8c1f9dcbd39c9c8e1a 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Response/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/LibGuides/Response/RecordCollection.php @@ -68,8 +68,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - return isset($this->response['recordCount']) - ? $this->response['recordCount'] : 0; + return $this->response['recordCount'] ?? 0; } /** @@ -90,7 +89,6 @@ class RecordCollection extends AbstractRecordCollection */ public function getOffset() { - return isset($this->response['offset']) - ? $this->response['offset'] : 0; + return $this->response['offset'] ?? 0; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Pazpar2/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/Pazpar2/Backend.php index 61f782743cad0f2a98f42c8e5773c956c4a2782c..c96175498cc6fd21136be1a1deb00f23cdc261e6 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Pazpar2/Backend.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Pazpar2/Backend.php @@ -139,7 +139,7 @@ class Backend extends AbstractBackend $this->connector->search($baseParams); /* Pazpar2 does not return all results immediately. Rather, we need to - * occassionally check with the Pazpar2 server on the status of the + * occasionally check with the Pazpar2 server on the status of the * search. * * This loop will continue to wait until the configured level of @@ -160,7 +160,7 @@ class Backend extends AbstractBackend ); $response = $this->connector->show($showParams); - $hits = isset($response->hit) ? $response->hit : []; + $hits = $response->hit ?? []; $collection = $this->createRecordCollection( $hits, intval($response->merged), $offset ); diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Primo/Response/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/Primo/Response/RecordCollection.php index 7fa90f450c40bd37c59624b0502e9b383f6e1a1b..58ca36264968ecd2fcefc71f508d49c86143fbc9 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Primo/Response/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Primo/Response/RecordCollection.php @@ -68,8 +68,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - return isset($this->response['recordCount']) - ? $this->response['recordCount'] : 0; + return $this->response['recordCount'] ?? 0; } /** @@ -79,8 +78,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getFacets() { - return isset($this->response['facets']) - ? $this->response['facets'] : []; + return $this->response['facets'] ?? []; } /** @@ -92,8 +90,7 @@ class RecordCollection extends AbstractRecordCollection { $page = isset($this->response['query']['pageNumber']) ? $this->response['query']['pageNumber'] - 1 : 0; - $size = isset($this->response['query']['pageSize']) - ? $this->response['query']['pageSize'] : 0; + $size = $this->response['query']['pageSize'] ?? 0; return $page * $size; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php index de532a8e8899be807f7d414b4ededfa7e11c4134..d5c42e0690a03ae505aa67fd09e9b34296cd8df1 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php @@ -482,6 +482,6 @@ class QueryBuilder implements QueryBuilderInterface } return $handler - ? $handler->createAdvancedQueryString($string, false) : $string; + ? $handler->createAdvancedQueryString($string) : $string; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Record.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Record.php index c7031a42fbbbb742c83170f33732b54ce704e70b..0855407285403df28c2843fe10f1e558f7f9bd30 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Record.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Record.php @@ -101,6 +101,6 @@ class Record implements RecordInterface */ public function __get($name) { - return isset($this->fields[$name]) ? $this->fields[$name] : null; + return $this->fields[$name] ?? null; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/RecordCollection.php index bebfe7a7baccc5c1c5579f07cc00b663a0639d2f..7ab8c7ae4e7e542553983b929ab6efdf71c5d450 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/RecordCollection.php @@ -135,8 +135,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getGroups() { - return isset($this->response['grouped']) - ? $this->response['grouped'] : []; + return $this->response['grouped'] ?? []; } /** @@ -146,8 +145,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getHighlighting() { - return isset($this->response['highlighting']) - ? $this->response['highlighting'] : []; + return $this->response['highlighting'] ?? []; } /** @@ -157,8 +155,7 @@ class RecordCollection extends AbstractRecordCollection */ protected function getSolrParameters() { - return isset($this->response['responseHeader']['params']) - ? $this->response['responseHeader']['params'] : []; + return $this->response['responseHeader']['params'] ?? []; } /** @@ -179,7 +176,6 @@ class RecordCollection extends AbstractRecordCollection */ protected function getRawSpellcheckSuggestions() { - return isset($this->response['spellcheck']['suggestions']) - ? $this->response['spellcheck']['suggestions'] : []; + return $this->response['spellcheck']['suggestions'] ?? []; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Backend.php index 91ff5c4c0b4797e9da9f89f817a78668c344ab2b..e4e4ac64b22b628517a70c1f6234a5765f8fc2ab 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Backend.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Backend.php @@ -134,8 +134,11 @@ class Backend extends AbstractBackend implements RetrieveBatchInterface */ public function retrieve($id, ParamBag $params = null) { + $finalParams = $params ?: new ParamBag(); + // We normally look up by ID, but we occasionally need to use bookmarks: + $idType = $finalParams->get('summonIdType')[0] ?? Connector::IDENTIFIER_ID; try { - $response = $this->connector->getRecord($id); + $response = $this->connector->getRecord($id, false, $idType); } catch (SummonException $e) { throw new BackendException( $e->getMessage(), diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Response/RecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Response/RecordCollection.php index 65d0598260f7d45cf136e9bdbeddb6f255ce6c3d..4f2e0716361944bb323dd85d4027f9821cfa39c8 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Response/RecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Summon/Response/RecordCollection.php @@ -62,8 +62,7 @@ class RecordCollection extends AbstractRecordCollection // Determine the offset: $page = isset($this->response['query']['pageNumber']) ? $this->response['query']['pageNumber'] - 1 : 0; - $size = isset($this->response['query']['pageSize']) - ? $this->response['query']['pageSize'] : 0; + $size = $this->response['query']['pageSize'] ?? 0; $this->offset = $page * $size; $this->rewind(); @@ -76,8 +75,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getTotal() { - return isset($this->response['recordCount']) - ? $this->response['recordCount'] : 0; + return $this->response['recordCount'] ?? 0; } /** @@ -87,8 +85,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getFacets() { - return isset($this->response['facetFields']) - ? $this->response['facetFields'] : []; + return $this->response['facetFields'] ?? []; } /** @@ -98,12 +95,8 @@ class RecordCollection extends AbstractRecordCollection */ public function getSpellcheck() { - if (isset($this->response['didYouMeanSuggestions']) - && is_array($this->response['didYouMeanSuggestions']) - ) { - return $this->response['didYouMeanSuggestions']; - } - return []; + return is_array($this->response['didYouMeanSuggestions'] ?? null) + ? $this->response['didYouMeanSuggestions'] : []; } /** @@ -113,8 +106,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getBestBets() { - return isset($this->response['recommendationLists']['bestBet']) - ? $this->response['recommendationLists']['bestBet'] : false; + return $this->response['recommendationLists']['bestBet'] ?? false; } /** @@ -124,8 +116,7 @@ class RecordCollection extends AbstractRecordCollection */ public function getDatabaseRecommendations() { - return isset($this->response['recommendationLists']['database']) - ? $this->response['recommendationLists']['database'] : false; + return $this->response['recommendationLists']['database'] ?? false; } /** @@ -135,7 +126,6 @@ class RecordCollection extends AbstractRecordCollection */ public function getTopicRecommendations() { - return isset($this->response['topicRecommendations']) - ? $this->response['topicRecommendations'] : false; + return $this->response['topicRecommendations'] ?? false; } } diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/WorldCat/Connector.php b/module/VuFindSearch/src/VuFindSearch/Backend/WorldCat/Connector.php index 13c9eed6c796ad21c624a42e612a935d8e27ce4e..46d47bccaa701752403ba9e9c49ff166fbdc11f6 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/WorldCat/Connector.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/WorldCat/Connector.php @@ -156,7 +156,7 @@ class Connector extends \VuFindSearch\Backend\SRU\Connector $response = $this->call('POST', $params->getArrayCopy(), false); $xml = simplexml_load_string($response); - $docs = isset($xml->records->record) ? $xml->records->record : []; + $docs = $xml->records->record ?? []; $finalDocs = []; foreach ($docs as $doc) { $finalDocs[] = $doc->recordData->asXML(); diff --git a/module/VuFindSearch/src/VuFindSearch/ParamBag.php b/module/VuFindSearch/src/VuFindSearch/ParamBag.php index 8aed52dcda71d7cc47e101d1b2e7202b6277751f..8921caf2a120aff7e8c7a3e68039600325a99275 100644 --- a/module/VuFindSearch/src/VuFindSearch/ParamBag.php +++ b/module/VuFindSearch/src/VuFindSearch/ParamBag.php @@ -73,7 +73,7 @@ class ParamBag implements \Countable */ public function get($name) { - return isset($this->params[$name]) ? $this->params[$name] : null; + return $this->params[$name] ?? null; } /** diff --git a/module/VuFindSearch/src/VuFindSearch/Response/AbstractRecordCollection.php b/module/VuFindSearch/src/VuFindSearch/Response/AbstractRecordCollection.php index b8c48657f1b614be3ca5ca8ee703f6f57a699c5b..45b973533820c51772758bcbb4dea66dbffacbd8 100644 --- a/module/VuFindSearch/src/VuFindSearch/Response/AbstractRecordCollection.php +++ b/module/VuFindSearch/src/VuFindSearch/Response/AbstractRecordCollection.php @@ -94,7 +94,7 @@ abstract class AbstractRecordCollection implements RecordCollectionInterface */ public function first() { - return isset($this->records[0]) ? $this->records[0] : null; + return $this->records[0] ?? null; } /** diff --git a/module/VuFindTheme/src/VuFindTheme/ThemeInfo.php b/module/VuFindTheme/src/VuFindTheme/ThemeInfo.php index d677c3f5baa5d0a5ecc96244f27e35941bf7ac84..f746506baf500561f81281abf1839519ba726135 100644 --- a/module/VuFindTheme/src/VuFindTheme/ThemeInfo.php +++ b/module/VuFindTheme/src/VuFindTheme/ThemeInfo.php @@ -199,7 +199,7 @@ class ThemeInfo * if boolean false, return containing theme name; if self::RETURN_ALL_DETAILS, * return an array containing both values (keyed with 'path' and 'theme'). * - * @return string + * @return string|array|null */ public function findContainingTheme($relativePath, $returnType = false) { diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php index c6b5037d9c3a3cb9100821e0d6a20565689fb9ee..80cefc329385ea0fe60a37aab8b3801e8b9d0360 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php @@ -145,10 +145,10 @@ trait ConcatTrait /** * Initialize class properties related to concatenation of resources. - * All of the elements to be concatenated into ($this->concatItems) - * and those that need to remain on their own ($this->otherItems). + * All of the elements to be concatenated into groups and + * and those that need to remain on their own special group 'other'. * - * @return void + * @return bool True if there are items */ protected function filterItems() { @@ -167,10 +167,23 @@ trait ConcatTrait continue; } + $path = $this->getFileType() . '/' . $this->getResourceFilePath($item); $details = $this->themeInfo->findContainingTheme( - $this->getFileType() . '/' . $this->getResourceFilePath($item), + $path, ThemeInfo::RETURN_ALL_DETAILS ); + // Deal with special case: $path was not found in any theme. + if (null === $details) { + $errorMsg = "Could not find file '$path' in theme files"; + method_exists($this, 'logError') + ? $this->logError($errorMsg) : error_log($errorMsg); + $this->groups[] = [ + 'other' => true, + 'item' => $item + ]; + $groupTypes[] = 'other'; + continue; + } $type = $this->getType($item); $index = array_search($type, $groupTypes); @@ -230,7 +243,10 @@ trait ConcatTrait } // Locate/create concatenated asset file $filename = md5($group['key']) . '.min.' . $this->getFileType(); - $concatPath = $this->getResourceCacheDir() . $filename; + // Minifier uses realpath, so do that here too to make sure we're not + // pointing to a symlink. Otherwise the path converter won't find the correct + // shared directory part. + $concatPath = realpath($this->getResourceCacheDir()) . '/' . $filename; if (!file_exists($concatPath)) { $lockfile = "$concatPath.lock"; $handle = fopen($lockfile, 'c+'); @@ -276,6 +292,7 @@ trait ConcatTrait . $this->getResourceFilePath($item), ThemeInfo::RETURN_ALL_DETAILS ); + $details['path'] = realpath($details['path']); $data[] = $this->getMinifiedData($details, $concatPath); } // Separate each file's data with a new line so that e.g. a file diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php index 60168d4d6dc776d963badfb2b74f3239e871f06c..949ee27d36db57dc3d061f2ac9427397313fe94b 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php @@ -39,8 +39,10 @@ use VuFindTheme\ThemeInfo; * @link https://vufind.org/wiki/development Wiki */ class HeadLink extends \Zend\View\Helper\HeadLink + implements \Zend\Log\LoggerAwareInterface { use ConcatTrait; + use \VuFind\Log\LoggerAwareTrait; /** * Theme information service @@ -193,7 +195,11 @@ class HeadLink extends \Zend\View\Helper\HeadLink */ public function getType($item) { - return isset($item->media) ? $item->media : 'all'; + $type = $item->media ?? 'all'; + if (isset($item->conditionalStylesheet)) { + $type .= '_' . $item->conditionalStylesheet; + } + return $type; } /** diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php index d2328c7795637cfbbf6430686ce91691d1522306..0ce0bb835d668dbef964d25515f752ed77219e5f 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php @@ -39,10 +39,12 @@ use VuFindTheme\ThemeInfo; * @link https://vufind.org/wiki/development Wiki */ class HeadScript extends \Zend\View\Helper\HeadScript + implements \Zend\Log\LoggerAwareInterface { use ConcatTrait { getMinifiedData as getBaseMinifiedData; } + use \VuFind\Log\LoggerAwareTrait; /** * Theme information service diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/ImageLink.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/ImageLink.php index 21b54fe403dae31543c2aeb7a0229e416c5b02d6..7b0de3ba14be1a5d888cc4c3ffe152523c766b13 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/ImageLink.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/ImageLink.php @@ -66,13 +66,19 @@ class ImageLink extends \Zend\View\Helper\AbstractHelper { // Normalize href to account for themes: $relPath = 'images/' . $image; - $currentTheme = $this->themeInfo->findContainingTheme($relPath); + $details = $this->themeInfo->findContainingTheme( + $relPath, \VuFindTheme\ThemeInfo::RETURN_ALL_DETAILS + ); - if (null === $currentTheme) { + if (null === $details) { return null; } $urlHelper = $this->getView()->plugin('url'); - return $urlHelper('home') . "themes/$currentTheme/" . $relPath; + $url = $urlHelper('home') . "themes/{$details['theme']}/" . $relPath; + $url .= strstr($url, '?') ? '&_=' : '?_='; + $url .= filemtime($details['path']); + + return $url; } } diff --git a/package.json b/package.json index 37cec6f6f153ea9e1194acb3e86fabf0fed4b4f5..ca4eee3e4099869b0a918a5b476d5886073e4a4f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vufind", - "version": "5.0.1", + "version": "5.1.0", "description": "Dev tools to handle css preprocessing, js magic, and compression", "repository": { "type": "git", diff --git a/packages/DEBIAN/changelog b/packages/DEBIAN/changelog index e0b2844b70a4f9e8c3d4c31838505348c4559460..830490f71a21c0338331f644f4e83db18851020e 100644 --- a/packages/DEBIAN/changelog +++ b/packages/DEBIAN/changelog @@ -1,3 +1,9 @@ +vufind 5.1 distribution; urgency=low + + * VuFind 5.1 release (see http://vufind.org/wiki/changelog for details) + + -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net> Mo 4 Feb 2019 10:00:00 UTC + vufind 5.0.1 distribution; urgency=low * VuFind 5.0.1 release (see http://vufind.org/wiki/changelog for details) diff --git a/packages/DEBIAN/control b/packages/DEBIAN/control index 2ddebeb5ac02f26979b7e89f85ca5f2dba949670..6ce06f5b42e452a2fc34ede6a5fd642504477792 100644 --- a/packages/DEBIAN/control +++ b/packages/DEBIAN/control @@ -1,5 +1,5 @@ Package: vufind -Version: 5.0.1 +Version: 5.1 Section: World Wide Web Priority: Optional Architecture: all diff --git a/solr.sh b/solr.sh index c26ca45dd86386c422270867366e8ca81feab7cb..c9d352a1985db54dc3aae79eefe265322556e099 100755 --- a/solr.sh +++ b/solr.sh @@ -42,9 +42,16 @@ usage() # Set VUFIND_HOME if [ -z "$VUFIND_HOME" ] then - VUFIND_HOME=$(dirname "$0") + # set VUFIND_HOME to the absolute path of the directory containing this script + # https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself + VUFIND_HOME="$(cd "$(dirname "$0")" && pwd -P)" + if [ -z "$VUFIND_HOME" ] + then + exit 1 + fi fi + if [ -z "$SOLR_HOME" ] then SOLR_HOME="$VUFIND_HOME/solr/vufind" diff --git a/tests/data/folio.mrc b/tests/data/folio.mrc new file mode 100644 index 0000000000000000000000000000000000000000..912c5bd500b7e40ebee24f831d5de0f49d49a915 --- /dev/null +++ b/tests/data/folio.mrc @@ -0,0 +1 @@ +01518cas a22003611a 45 00100370000000500170003700800410005401000360009502200140013103200170014503500160016203700660017804001280024404900170037205000180038921000270040722200400043424500240047424600400049826000450053830000270058331000190061036200570062950000220068650000690070851500310077765000490080865000360085765000320089371000600092578000630098578501080104837b1a546-a826-450b-b57a-9476c4e42b2020091117105557.0840328d19831987nyufx1p o 0 a0eng d a 84643014 //r88zsn 84011556 0 a0748-1985 a002051bUSPS aocm10569413 bHuman Sciences Press, Inc., 72 5th Ave., New York, N.Y. 10011 aKSWcKSWdCLUdAIPdNSTdDLCdNSDdNSTdDLCdHULdNSTdNSDdNLMdNSTdNSDdNSTdNSDdDLCdNSTdNSDdNSTdCLUdNSTdOCLdPVU aPVUP[SERIAL]00aAC489.R3bJ680 aJ. ration. emot. ther. 0aJournal of rational emotive therapy00a14 cows for America13aJournal of rational-emotive therapy a[New York] :bThe Institute,c1983-1987. a5 v. :bill. ;c26 cm. aTwo no. a year0 aVol. 1, no. 1 (fall 1983)-v. 5, no. 4 (winter 1987). aTitle from cover. aVols. for <spring 1985-> published by Human Sciences Press, Inc. aVol. 1 has only one issue. 0aRational-emotive psychotherapyvPeriodicals. 0aCognitive therapyvPeriodicals. 2aPsychotherapyvperiodicals.2 aInstitute for Rational-Emotive Therapy (New York, N.Y.)00tRational livingx0034-0049w(OCLC)1763461w(DLC) 7200064700tJournal of rational-emotive and cognitive-behavior therapyx0894-9085w(DLC) 88648219w(OCoLC)1630781401234cas a22003011a 45 0010037000000050017000370070014000540080041000680100023001090220014001320300011001460350016001570400083001730500018002562100019002742220020002932450035003132600049003483000028003973620050004255500050004755500132005255800063006576500032007207100060007527100035008127850085008473e38354f-e93a-48f2-b54d-c50265b1504c20091117105643.0hd bfa b|c|751101d19661983nyufr1p 0 a0eng a 72000647 //r8520 a0034-0049 aATLVBX aocm01763461 aDLCcMULdNSDdDLCdRCSdAIPdDLCdNSDdNSTdDLCdAIPdNSTdDLCdNSTdNSDdNST00aAA790.A1bR351 aRation. living 0aRational living00a1963 Birmingham church bombing a[New York] :bInstitute for Rational Living. a18 v. :bill. ;c27 cm.0 aVol. 1 (Feb. 1966)-v.18, no. 1 (spring 1983). aJournal of the Institute for Rational Living. aIssued by: Institute for Rational Living, Feb. 1966-spring 1982; Institute for Rational-Emotive Therapy, fall 1982-spring 1983. aContinued in 1983 by: Journal of rational emotive therapy. 0aMental healthvPeriodicals.2 aInstitute for Rational-Emotive Therapy (New York, N.Y.)2 aInstitute for Rational Living.10tJournal of rational emotive therapyx0748-1985w(DLC) 84643014w(OCoLC)1056941301060cas a22003011a 45 001003700000005001700037008004100054010003000095022001400125035001600139037005600155040003300211050002100244210002900265222003800294245001700332260004800349300002800397310001400425362003300439362004000472500002200512650003200534650003500566650004200601785009900643936001600742db08002d-449c-4a21-b154-d083bd20462820091117104735.0820311d19831998nyuqr1p o 0 a0eng d a 83-644252 zsn82-2030 0 a0731-7158 aocm08235783 bHaworth Press, 28 E. 22nd St., New York, N.Y. 10010 aNSDcNSDdDLCdAIPdNLMdNST0 aAC455.2.P73bP890 aPsychother. priv. pract. 0aPsychotherapy in private practice00a1990 to 2010 a[New York, N.Y.] :bHaworth Press,c[c1983- a17 v. :bill. ;c23 cm. aQuarterly0 aVol. 1, no. 1 (spring 1983)-1 aCeased with: Vol. 17, no. 4 (1998). aTitle from cover. 2aPsychotherapyvperiodicals. 2aPrivate Practicevperiodicals. 0aPsychotherapyxPracticevPeriodicals.00tJournal of psychotherapy in independent practicex1522-9580w(DLC)sn 98005091w(OCoLC)40524650 aSummer 198401361cas a22003611a 45 00100370000000500170003700700160005400800410007001000170011102200140012803000110014203200170015303500160017003700580018604000630024409000170030721000240032422200400034824500160038826000320040430000170043631000140045336200310046750000220049865000640052065000340058450600660061853000420068471000260072685600960075285601170084893600340096569640328-788e-43fc-9c3c-af39e243f3b720091117105437.0cr an ---uuuuu840713c19859999nyuqr1p 0 a0eng d asn 84006638 0 a0748-4518 aJQCRE6 a755730bUSPS aocm10945712 bPlenum Pub. Corp., 233 Spring St., New York, NY 10013 aNSDcNSDdFUGdNSDdNSTdIULdNSTdHULdNSTdEYMdNSTdHUL aAV6001b.J721 aJ. quant. criminol. 0aJournal of quantitative criminology00aABA Journal aNew York :bPlenum,cc1985- av. ;c23 cm. aQuarterly0 aVol. 1, no. 1 (Mar. 1985)- aTitle from cover. 0aCriminal justice, Administration ofxResearchvPeriodicals. 0aCrimexResearchvPeriodicals. aElectronic access restricted to Villanova University patrons. aAlso available on the World Wide Web.2 aLINK (Online service)41zOnline version [v. 15 (1999)-present]uhttp://springerlink.metapress.com/link.asp?id=10258641zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0748-4518&genre=journal aVol. 1, no. 4 (Dec. 1985) LIC01720cas a22004091a 45 00100370000000500170003700700150005400700140006900800410008301000220012402200140014603000110016003200170017103500160018804000790020405000170028321000200030022200300032024500230035026000430037330000250041636200240044150600660046553000420053155000870057355500420066050001030070265000430080570000360084870000350088470000460091971000490096571000340101485601210104885601170116993600240128625a443d1-541f-4784-b11f-905e43e6e41520091117092424.0cr mn ---|||||hd bda b|c|750901c19379999ncuqr1p 0 a0eng d a 40012649 //r86 a0022-3387 aJPRPAU a281800bUSPS aocm01588544 aMULcMULdNSDdDLCdNSDdDLCdm.c.dRCSdAIPdNSDdAIPdOCLdDLCdm/cdNST00aAF1001b.J661 aJ. parapsychol. 0aJournal of parapsychology04aaccidental atheist aDurham, N.C. :bDuke University Press. av. :bill. ;c23 cm.0 aVol. 1 (Mar. 1937)- aElectronic access restricted to Villanova University patrons. aAlso available on the World Wide Web. aIssued in cooperation with the Duke University Parapsychology Laboratory, 194 -50. aVols. 1-16, 1937-52, in v. 17, no. 3. aEditors: Mar. 1937-<Dec. 1938> J. B. Rhine, C. E. Stuart (with W. McDougall, Mar. 1937-Sept. 1938) 0aParapsychologyxResearchvPeriodicals.1 aMcDougall, William,d1871-1938.1 aStuart, Charles Edward,d1907-1 aRhine, J. B.q(Joseph Banks),d1895-1980.2 aDuke University.bParapsychology Laboratory.2 aProQuest Psychology Journals.41zOnline version [v. 59 (1995)-present]uhttp://proquest.umi.com/pqdweb?pmid=000029287&clientId=3260&RQT=318&VName=PQD41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3387&genre=journal aMar. 1937-Dec. 195801536cas a22003371a 45 001003700000005001700037008004100054010003700095022001400132035001600146040003800162041002300200050001500223222004100238245002100279260010900300300002000409310002500429321002200454362005700476500002200533546004100555550017300596580007100769650003800840650003000878710004700908710007500955780008101030785008701111f3cf2855-5dfd-486a-bdf3-465e6a29859920091117105533.0751101d19571970inumr1p o0 a0eng aa 53008626 //r853zsc 80001624 a0095-9057 aocm01772601 aDLCcMULdNSDdDLCdm/cdHULdNST0 aengafreageraita0 aAA1b.J975 0aJournal of mathematics and mechanics00aAge of TV heroes aBloomington, Ind. :bGraduate Institute for Mathematics and Mechanics, Indiana University,cc1957-c1970. a14 v. ;c26 cm. aMonthly,b-June 1970 aBimonthly,b1957-0 aVol. 6, no. 1 (Jan. 1957)-v. 19, no. 12 (June 1970). aTitle from cover. aEnglish, French, German and Italian. aVols. for 1957- published by the Graduate Institute for Mathematics and Mechanics, Indiana University; -June 1970 by the Dept. of Mathematics, Indiana University. aContinued in July 1970 by: Indiana University mathematics journal. 0aMechanics, AnalyticvPeriodicals. 0aMathematicsvPeriodicals.2 aIndiana University.bDept. of Mathematics.2 aIndiana University.bGraduate Institute for Mathematics and Mechanics.00tJournal of rational mechanics and analysisw(DLC)sf 85001244w(OCoLC)226307110tIndiana University mathematics journalx0022-2518w(DLC) 75640369w(OCoLC)175301901452cas a22003851a 45 0010037000000050017000370070015000540070014000690080041000830100017001240220014001410300011001550320017001660350016001830370060001990400059002590500014003182100016003322220030003482450032003782600042004103000025004523100022004773210024004993620022005235060066005455000047006115300042006586500029007007000038007297100034007678560122008018560117009239360026010402fb80735-18df-49a9-b4e9-2579c40fd8a720091117102216.0cr mn ---|||||hd bfa b|c|741112c19369999maubr1p 0 a0eng a 38003075 a0022-3980 aJOPSAM a282400bUSPS aocm01782317 bJournal Press, 2 Commercial St., Provincetown, MA 02657 aDLCcDLCdOCLdDLCdNSDdm.c.dOCLdRCSdAIPdOCLdNSD00aAF1b.J671 aJ. psychol. 4aThe Journal of psychology04aAl Gorehby Rebecca Stefoff aProvincetown, Mass. :bJournal Press. av. :bill. ;c25 cm. aBimonthly,b1965- aQuarterly,b1935-640 aVol. 1 (1935/36)- aElectronic access restricted to Villanova University patrons. aEditor: 1935/36-<Oct. 1937,> C. Murchison. aAlso available on the World Wide Web. 0aPsychologyvPeriodicals.1 aMurchison, Carl Allanmore,d1887-2 aProQuest Psychology Journals.41zOnline version [v. 128 (1994)-present]uhttp://proquest.umi.com/pqdweb?pmid=000014346&clientId=3260&RQT=318&VName=PQD41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3980&genre=journal aJan. 1975 (surrogate)01267cas a22003251a 45 001003700000005001700037007001500054008004100069010002200110022001400132030001100146035001600157040007300173050001400246210002300260222003800283245003000321260004200351300002500393362002400418506006600442500003000508530004200538650004100580650005200621700001800673710003600691856009700727856011700824d7bcca8e-ec42-464f-8cae-9777a16fb42c20091117102549.0cr an 741112c19569999enkbrzp 0 a0eng a 57003141 //r830 a0022-3999 aJPCRAT aocm01782774 aDLCcDLCdNSDdOCLdNSDdDLCdSERdOCLdRCSdDLCdOCLdAIPdOCLdNSD00aAC52b.J61 aJ. psychosom. res. 0aJournal of psychosomatic research00aAl Gorehby Dale Anderson aLondon ;aNew York :bPergamon Press. av. :bill. ;c26 cm.0 aVol. 1 (Feb. 1956)- aElectronic access restricted to Villanova University patrons. aEditor: 1956- D. Leigh. aAlso available on the World Wide Web. 2aPsychosomatic Medicinevperiodicals. 0aMedicine, PsychosomaticxResearchvPeriodicals.1 aLeigh, Denis.2 aScienceDirect (Online service).41zOnline version [v. 44 (1998)-present]uhttp://www.sciencedirect.com/science/journal/0022399941zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3999&genre=journal02174cas a2200469 a 45000010037000000050017000370060019000540070015000730080041000880100017001290350023001460400050001690220028002190370088002470500013003350490009003481300037003572100026003942220042004202450032004622600070004943100028005643210036005923620031006285000052006595000033007115000095007445060066008395380036009055500120009416500037010616500022010986500029011207100051011497100057012007100025012577760096012827800075013788560122014538560117015759940012016926d6cbb34-edb4-4577-b148-9a33d8d4130420091117160642.0m d cr mnu||||||||741112c19659999pauqx pss 0 a0eng d a 2006212058 a(OCoLC)ocm39109327 aFGAcFGAdOCLdOCLCQdFQMdNSDdEYMdHULdPVU0 a1559-8519y0022-449921 bSociety for the Scientific Study of Sexuality, PO Box 416, Allentown, PA 18105-041614aAQ5b.J6 aPVUM0 aJournal of sex research (Online)1 aJ. sex res.b(Online) 4aThe journal of sex researchb(Online)14aAl Gorehby Tracey Baptiste aNew York, N.Y. :bSociety for the Scientific Study of Sex,c1965- a4 issues yearly,b1967- aThree issues yearly,b1965-19660 aVol. 1, no. 1 (Mar. 1965)- aTitle from cover (JSTOR, viewed Apr. 18, 2007). aPlace of publication varies. aLatest issue consulted: Vol. 43, issue 4 (Nov. 2006) (SSSS website, viewed Apr. 18, 2007). aElectronic access restricted to Villanova University patrons. aMode of access: World Wide Web. aIssued by: Society for the Scientific Study of Sex, 1965-1994; Society for the Scientific Study of Sexuality, 1995- 0aSexologyxResearchvPeriodicals.12aSexvPeriodicals.22aPsychiatryvPeriodicals.2 aSociety for the Scientific Study of Sex (U.S.)2 aSociety for the Scientific Study of Sexuality (U.S.)2 aJSTOR (Organization)08iAlso issued in print:tJournal of sex researchx0022-4499w(DLC) 68130414w(OCoLC)178336500tAdvances in sex research (Online)w(DLC) 2007234124w(OCoLC)12320877540zOnline version [JSTOR: v. 1 (1965)-present ; latest 5 years unavailable]uhttp://www.jstor.org/journals/00224499.html40zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-4499&genre=journal aC0bPVU01206cas a22003251a 45 00100370000000500170003700700160005400800410007001000170011102200140012803000110014203500160015303700100016904000530017905000180023209000170025021000280026722200430029524500310033826000510036930000170042036200240043750000350046150600660049653000420056265000460060471000200065085600930067085601170076355b3095a-a55b-4411-b532-eb84c47e2c3020091117093002.0cr bn ---|||||751002c19709999njufr1p 0 a0eng a 75643076 0 a0047-2662 aJPHPAE aocm02240975 b07716 aDLCcDLCdNSDdDLCdOCLdRCSdAIPdNSDdOCLdNST0 aAF204.5b.J68 aAF204.5b.J61 aJ. phenomenol. psychol. 0aJournal of phenomenological psychology00aAl Gore and global warming a[Atlantic Highlands, N.J. :bHumanities Press] av. ;c23 cm.0 aVol. 1 (fall 1970)- aAt head of title <1974->: JPP. aElectronic access restricted to Villanova University patrons. aAlso available on the World Wide Web. 0aPhenomenological psychologyvPeriodicals.2 aIngenta (Firm).41zOnline version [v. 1 (1970/71)-present]uhttp://www.ingentaconnect.com/content/brill/jpp41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0047-2662&genre=journal \ No newline at end of file diff --git a/tests/jshint.json b/tests/jshint.json new file mode 100644 index 0000000000000000000000000000000000000000..ebcf84e417e6cbe7427098ae068640e313793c2f --- /dev/null +++ b/tests/jshint.json @@ -0,0 +1,4 @@ +{ + "latedef": true, + "laxbreak": true +} diff --git a/themes/bootprint3/less/bootprint.less b/themes/bootprint3/less/bootprint.less index 596a442afc5345420933d5ce00b3c27d0743b470..837c8cc22950bbdadeef1baa19fd60d6dc549faf 100644 --- a/themes/bootprint3/less/bootprint.less +++ b/themes/bootprint3/less/bootprint.less @@ -12,23 +12,23 @@ body { background: @brand-primary; - font-size: 13px + font-size: 13px; } #commentList .comment:nth-child(even) { background: @gray-lighter; } #dateVisColorSettings { stroke: @brand-primary; } #hierarchyRecord { background: #fff; } .cart-controls .checkbox { line-height: 2rem; } +.myresearch-menu a:hover { text-decoration: none; } /* --- Layout --- */ .main .container { padding-top: 1rem; } .main .sidebar { background-color: #fff; } -body.offcanvas .sidebar { - padding-left: 1rem; - padding-right: 1rem; -} + @media (min-width: 768px) { .main .sidebar { padding: 0; } + .sidebar.left { padding-right: 1rem; } + .sidebar.right { padding-left: 1rem; } } /* --- Header --- */ @@ -93,20 +93,6 @@ footer ul { padding-left: 30px; } .channel-title { margin-top: 1rem; } .channel-title .fa { margin-top: 4px; } -/* --- Offcanvas --- */ -body.offcanvas { - .offcanvas-toggle { - padding-bottom: 18px; - font-size: 16px; - background: #fff; - box-shadow: 0 0 2px #000; - color: @brand-primary; - } - .sidebar .list-group { color: #000; } - &.active .sidebar { color: #FFF; } - &.active .offcanvas-toggle { box-shadow: none; } -} - /* --- Random Items (results view) --- */ ul.random { list-style: none; @@ -156,6 +142,8 @@ ul.random.image li img { margin: 0 auto; } .facet.facetOR { padding-left: 1rem; } } +.checkboxFilter .facet { padding-left: 1px; } + .slider-container .slider-handle { background: @brand-primary; border: 1px solid @brand-primary; @@ -169,5 +157,8 @@ ul.random.image li img { margin: 0 auto; } color: #fff; &:hover { color: @brand-danger; } } -.jstree-facet .facet { padding: 0; } +.jstree-facet .facet { + padding: 0; + padding-right: 10px; +} .jstree-node.active { background-color: @active-orange; } diff --git a/themes/bootprint3/less/icons.less b/themes/bootprint3/less/icons.less index 7bd591defba94734236577b7a548bfd27e3def19..3728166f92b7196489fdd61b08714db6be2e6e7a 100644 --- a/themes/bootprint3/less/icons.less +++ b/themes/bootprint3/less/icons.less @@ -1,4 +1,5 @@ @bp3-icon-path: '../../bootprint3/images/icons'; +.doi-icon { width: 16px; } .bp-icon { background-position: center center; background-repeat: no-repeat; diff --git a/themes/bootprint3/scss/bootprint.scss b/themes/bootprint3/scss/bootprint.scss index c9b8e98ed7ba427cc052ea553c2e8342418411a0..bfe8ca5ae77c29c8c85f9e14a0593e200ecaa2c3 100644 --- a/themes/bootprint3/scss/bootprint.scss +++ b/themes/bootprint3/scss/bootprint.scss @@ -11,23 +11,23 @@ $active-orange: #E70 !default; body { background: $brand-primary; - font-size: 13px + font-size: 13px; } #commentList .comment:nth-child(even) { background: $gray-lighter; } #dateVisColorSettings { stroke: $brand-primary; } #hierarchyRecord { background: #fff; } .cart-controls .checkbox { line-height: 2rem; } +.myresearch-menu a:hover { text-decoration: none; } /* --- Layout --- */ .main .container { padding-top: 1rem; } .main .sidebar { background-color: #fff; } -body.offcanvas .sidebar { - padding-left: 1rem; - padding-right: 1rem; -} + @media (min-width: 768px) { .main .sidebar { padding: 0; } + .sidebar.left { padding-right: 1rem; } + .sidebar.right { padding-left: 1rem; } } /* --- Header --- */ @@ -82,25 +82,16 @@ footer ul { padding-left: 30px; } [id^=list].list-group .col-sm-9 { margin: 0; } /* --- Channels --- */ +.channel { + max-width: 96%; + margin-left: 2%; + margin-right: 2%; +} .channel, .channel-title.no-results { margin-bottom: 2rem; } .channel-title { margin-top: 1rem; } .channel-title .fa { margin-top: 4px; } -/* --- Offcanvas --- */ -body.offcanvas { - .offcanvas-toggle { - padding-bottom: 18px; - font-size: 16px; - background: #fff; - box-shadow: 0 0 2px #000; - color: $brand-primary; - } - .sidebar .list-group { color: #000; } - &.active .sidebar { color: #FFF; } - &.active .offcanvas-toggle { box-shadow: none; } -} - /* --- Random Items (results view) --- */ ul.random { list-style: none; @@ -149,8 +140,9 @@ ul.random.image li img { margin: 0 auto; } .facet .badge a { color: #fff; } .facet.facetOR { padding-left: 1rem; } - .facet.excludable { padding-right: 0; } } +.checkboxFilter .facet { padding-left: 1px; } + .slider-container .slider-handle { background: $brand-primary; border: 1px solid $brand-primary; @@ -164,5 +156,8 @@ ul.random.image li img { margin: 0 auto; } color: #fff; &:hover { color: $brand-danger; } } -.jstree-facet .facet { padding: 0; } +.jstree-facet .facet { + padding: 0; + padding-right: 10px; +} .jstree-node.active { background-color: $active-orange; } diff --git a/themes/bootprint3/scss/icons.scss b/themes/bootprint3/scss/icons.scss index ff55c65d9f5fe1ead08fedc38ed543512a0b6047..8c2885d47543ad68e0a680c0964e53353b6f8ec9 100644 --- a/themes/bootprint3/scss/icons.scss +++ b/themes/bootprint3/scss/icons.scss @@ -1,4 +1,5 @@ $bp3-icon-path: '../../bootprint3/images/icons' !default; +.doi-icon { width: 16px; } .bp-icon { background-position: center center; background-repeat: no-repeat; diff --git a/themes/bootstrap3/css/vendor/bootstrap.min.css b/themes/bootstrap3/css/vendor/bootstrap.min.css index ed3905e0e0c91d4ed7d8aa14412dffeb038745ff..7f3562ec2da266134c658a692321938e7e3bacb7 100644 --- a/themes/bootstrap3/css/vendor/bootstrap.min.css +++ b/themes/bootstrap3/css/vendor/bootstrap.min.css @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:"Glyphicons Halflings";src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"),url(../fonts/glyphicons-halflings-regular.woff2) format("woff2"),url(../fonts/glyphicons-halflings-regular.woff) format("woff"),url(../fonts/glyphicons-halflings-regular.ttf) format("truetype"),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} /*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/themes/bootstrap3/css/vendor/bootstrap.min.css.map b/themes/bootstrap3/css/vendor/bootstrap.min.css.map new file mode 100644 index 0000000000000000000000000000000000000000..6bb00ce23458c039a1953f55322afda24bffc77f --- /dev/null +++ b/themes/bootstrap3/css/vendor/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap.css","less/normalize.less","dist/css/bootstrap.css","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;AAKA,4ECKA,KACE,YAAA,WACA,qBAAA,KACA,yBAAA,KAOF,KACE,OAAA,EAaF,QCnBA,MACA,QACA,WACA,OACA,OACA,OACA,OACA,KACA,KACA,IACA,QACA,QDqBE,QAAA,MAQF,MCzBA,OACA,SACA,MD2BE,QAAA,aACA,eAAA,SAQF,sBACE,QAAA,KACA,OAAA,EAQF,SCrCA,SDuCE,QAAA,KAUF,EACE,iBAAA,YAQF,SCnDA,QDqDE,QAAA,EAWF,YACE,cAAA,KACA,gBAAA,UACA,wBAAA,UAAA,OAAA,qBAAA,UAAA,OAAA,gBAAA,UAAA,OAOF,EC/DA,ODiEE,YAAA,IAOF,IACE,WAAA,OAQF,GACE,UAAA,IACA,OAAA,MAAA,EAOF,KACE,WAAA,KACA,MAAA,KAOF,MACE,UAAA,IAOF,ICzFA,ID2FE,UAAA,IACA,YAAA,EACA,SAAA,SACA,eAAA,SAGF,IACE,IAAA,MAGF,IACE,OAAA,OAUF,IACE,OAAA,EAOF,eACE,SAAA,OAUF,OACE,OAAA,IAAA,KAOF,GACE,mBAAA,YAAA,gBAAA,YAAA,WAAA,YACA,OAAA,EAOF,IACE,SAAA,KAOF,KC7HA,IACA,IACA,KD+HE,YAAA,SAAA,CAAA,UACA,UAAA,IAkBF,OC7IA,MACA,SACA,OACA,SD+IE,MAAA,QACA,KAAA,QACA,OAAA,EAOF,OACE,SAAA,QAUF,OC1JA,OD4JE,eAAA,KAWF,OCnKA,wBACA,kBACA,mBDqKE,mBAAA,OACA,OAAA,QAOF,iBCxKA,qBD0KE,OAAA,QAOF,yBC7KA,wBD+KE,OAAA,EACA,QAAA,EAQF,MACE,YAAA,OAWF,qBC5LA,kBD8LE,mBAAA,WAAA,gBAAA,WAAA,WAAA,WACA,QAAA,EASF,8CCjMA,8CDmME,OAAA,KAQF,mBACE,mBAAA,UACA,mBAAA,YAAA,gBAAA,YAAA,WAAA,YASF,iDC5MA,8CD8ME,mBAAA,KAOF,SACE,OAAA,IAAA,MAAA,OACA,OAAA,EAAA,IACA,QAAA,MAAA,OAAA,MAQF,OACE,OAAA,EACA,QAAA,EAOF,SACE,SAAA,KAQF,SACE,YAAA,IAUF,MACE,gBAAA,SACA,eAAA,EAGF,GC3OA,GD6OE,QAAA,EDlPF,qFGhLA,aACE,ED2LA,OADA,QCvLE,MAAA,eACA,YAAA,eACA,WAAA,cACA,mBAAA,eAAA,WAAA,eAGF,ED0LA,UCxLE,gBAAA,UAGF,cACE,QAAA,KAAA,WAAA,IAGF,kBACE,QAAA,KAAA,YAAA,IAKF,mBDqLA,6BCnLE,QAAA,GDuLF,WCpLA,IAEE,OAAA,IAAA,MAAA,KACA,kBAAA,MAGF,MACE,QAAA,mBDqLF,IClLA,GAEE,kBAAA,MAGF,IACE,UAAA,eDmLF,GACA,GCjLA,EAGE,QAAA,EACA,OAAA,EAGF,GD+KA,GC7KE,iBAAA,MAMF,QACE,QAAA,KAEF,YD2KA,oBCxKI,iBAAA,eAGJ,OACE,OAAA,IAAA,MAAA,KAGF,OACE,gBAAA,mBADF,UD2KA,UCtKI,iBAAA,eD0KJ,mBCvKA,mBAGI,OAAA,IAAA,MAAA,gBCrFN,WACE,YAAA,uBACA,IAAA,+CACA,IAAA,sDAAA,2BAAA,CAAA,iDAAA,eAAA,CAAA,gDAAA,cAAA,CAAA,+CAAA,kBAAA,CAAA,2EAAA,cAQF,WACE,SAAA,SACA,IAAA,IACA,QAAA,aACA,YAAA,uBACA,WAAA,OACA,YAAA,IACA,YAAA,EACA,uBAAA,YACA,wBAAA,UAIkC,2BAAW,QAAA,QACX,uBAAW,QAAA,QF2P/C,sBEzPoC,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,wBAAW,QAAA,QACX,2BAAW,QAAA,QACX,yBAAW,QAAA,QACX,wBAAW,QAAA,QACX,wBAAW,QAAA,QACX,yBAAW,QAAA,QACX,wBAAW,QAAA,QACX,uBAAW,QAAA,QACX,6BAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,2BAAW,QAAA,QACX,qBAAW,QAAA,QACX,0BAAW,QAAA,QACX,qBAAW,QAAA,QACX,yBAAW,QAAA,QACX,0BAAW,QAAA,QACX,2BAAW,QAAA,QACX,sBAAW,QAAA,QACX,yBAAW,QAAA,QACX,sBAAW,QAAA,QACX,wBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,+BAAW,QAAA,QACX,2BAAW,QAAA,QACX,yBAAW,QAAA,QACX,wBAAW,QAAA,QACX,8BAAW,QAAA,QACX,yBAAW,QAAA,QACX,0BAAW,QAAA,QACX,2BAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,6BAAW,QAAA,QACX,6BAAW,QAAA,QACX,8BAAW,QAAA,QACX,4BAAW,QAAA,QACX,yBAAW,QAAA,QACX,0BAAW,QAAA,QACX,sBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,2BAAW,QAAA,QACX,wBAAW,QAAA,QACX,yBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,yBAAW,QAAA,QACX,8BAAW,QAAA,QACX,6BAAW,QAAA,QACX,6BAAW,QAAA,QACX,+BAAW,QAAA,QACX,8BAAW,QAAA,QACX,gCAAW,QAAA,QACX,uBAAW,QAAA,QACX,8BAAW,QAAA,QACX,+BAAW,QAAA,QACX,iCAAW,QAAA,QACX,0BAAW,QAAA,QACX,6BAAW,QAAA,QACX,yBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,wBAAW,QAAA,QACX,uBAAW,QAAA,QACX,gCAAW,QAAA,QACX,gCAAW,QAAA,QACX,2BAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,uBAAW,QAAA,QACX,0BAAW,QAAA,QACX,+BAAW,QAAA,QACX,+BAAW,QAAA,QACX,wBAAW,QAAA,QACX,+BAAW,QAAA,QACX,gCAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,8BAAW,QAAA,QACX,0BAAW,QAAA,QACX,gCAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,gCAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,6BAAW,QAAA,QACX,8BAAW,QAAA,QACX,2BAAW,QAAA,QACX,6BAAW,QAAA,QACX,4BAAW,QAAA,QACX,8BAAW,QAAA,QACX,+BAAW,QAAA,QACX,mCAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,2BAAW,QAAA,QACX,4BAAW,QAAA,QACX,+BAAW,QAAA,QACX,wBAAW,QAAA,QACX,2BAAW,QAAA,QACX,yBAAW,QAAA,QACX,0BAAW,QAAA,QACX,yBAAW,QAAA,QACX,6BAAW,QAAA,QACX,+BAAW,QAAA,QACX,0BAAW,QAAA,QACX,gCAAW,QAAA,QACX,+BAAW,QAAA,QACX,8BAAW,QAAA,QACX,kCAAW,QAAA,QACX,oCAAW,QAAA,QACX,sBAAW,QAAA,QACX,2BAAW,QAAA,QACX,uBAAW,QAAA,QACX,8BAAW,QAAA,QACX,4BAAW,QAAA,QACX,8BAAW,QAAA,QACX,6BAAW,QAAA,QACX,4BAAW,QAAA,QACX,0BAAW,QAAA,QACX,4BAAW,QAAA,QACX,qCAAW,QAAA,QACX,oCAAW,QAAA,QACX,kCAAW,QAAA,QACX,oCAAW,QAAA,QACX,wBAAW,QAAA,QACX,yBAAW,QAAA,QACX,wBAAW,QAAA,QACX,yBAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,4BAAW,QAAA,QACX,4BAAW,QAAA,QACX,8BAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,0BAAW,QAAA,QACX,sBAAW,QAAA,QACX,sBAAW,QAAA,QACX,uBAAW,QAAA,QACX,mCAAW,QAAA,QACX,uCAAW,QAAA,QACX,gCAAW,QAAA,QACX,oCAAW,QAAA,QACX,qCAAW,QAAA,QACX,yCAAW,QAAA,QACX,4BAAW,QAAA,QACX,yBAAW,QAAA,QACX,gCAAW,QAAA,QACX,8BAAW,QAAA,QACX,yBAAW,QAAA,QACX,wBAAW,QAAA,QACX,0BAAW,QAAA,QACX,6BAAW,QAAA,QACX,yBAAW,QAAA,QACX,uBAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,yBAAW,QAAA,QACX,yBAAW,QAAA,QACX,uBAAW,QAAA,QACX,8BAAW,QAAA,QACX,+BAAW,QAAA,QACX,gCAAW,QAAA,QACX,8BAAW,QAAA,QACX,8BAAW,QAAA,QACX,8BAAW,QAAA,QACX,2BAAW,QAAA,QACX,0BAAW,QAAA,QACX,yBAAW,QAAA,QACX,6BAAW,QAAA,QACX,2BAAW,QAAA,QACX,4BAAW,QAAA,QACX,wBAAW,QAAA,QACX,wBAAW,QAAA,QACX,2BAAW,QAAA,QACX,2BAAW,QAAA,QACX,4BAAW,QAAA,QACX,+BAAW,QAAA,QACX,8BAAW,QAAA,QACX,4BAAW,QAAA,QACX,4BAAW,QAAA,QACX,4BAAW,QAAA,QACX,iCAAW,QAAA,QACX,oCAAW,QAAA,QACX,iCAAW,QAAA,QACX,+BAAW,QAAA,QACX,+BAAW,QAAA,QACX,iCAAW,QAAA,QACX,qBAAW,QAAA,QACX,4BAAW,QAAA,QACX,4BAAW,QAAA,QACX,2BAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QASX,wBAAW,QAAA,QACX,4BAAW,QAAA,QACX,uBAAW,QAAA,QACX,wBAAW,QAAA,QACX,uBAAW,QAAA,QACX,yBAAW,QAAA,QACX,yBAAW,QAAA,QACX,+BAAW,QAAA,QACX,uBAAW,QAAA,QACX,6BAAW,QAAA,QACX,sBAAW,QAAA,QACX,wBAAW,QAAA,QACX,wBAAW,QAAA,QACX,4BAAW,QAAA,QACX,uBAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,2BAAW,QAAA,QACX,0BAAW,QAAA,QACX,sBAAW,QAAA,QACX,sBAAW,QAAA,QACX,sBAAW,QAAA,QACX,sBAAW,QAAA,QACX,wBAAW,QAAA,QACX,sBAAW,QAAA,QACX,wBAAW,QAAA,QACX,4BAAW,QAAA,QACX,mCAAW,QAAA,QACX,4BAAW,QAAA,QACX,oCAAW,QAAA,QACX,kCAAW,QAAA,QACX,iCAAW,QAAA,QACX,+BAAW,QAAA,QACX,sBAAW,QAAA,QACX,wBAAW,QAAA,QACX,6BAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,kCAAW,QAAA,QACX,mCAAW,QAAA,QACX,sCAAW,QAAA,QACX,0CAAW,QAAA,QACX,oCAAW,QAAA,QACX,wCAAW,QAAA,QACX,qCAAW,QAAA,QACX,iCAAW,QAAA,QACX,gCAAW,QAAA,QACX,kCAAW,QAAA,QACX,+BAAW,QAAA,QACX,0BAAW,QAAA,QACX,8BAAW,QAAA,QACX,4BAAW,QAAA,QACX,4BAAW,QAAA,QACX,6BAAW,QAAA,QACX,4BAAW,QAAA,QACX,0BAAW,QAAA,QCxS/C,ECkEE,mBAAA,WACG,gBAAA,WACK,WAAA,WJo+BV,OGriCA,QC+DE,mBAAA,WACG,gBAAA,WACK,WAAA,WDzDV,KACE,UAAA,KACA,4BAAA,cAGF,KACE,YAAA,gBAAA,CAAA,SAAA,CAAA,KAAA,CAAA,WACA,UAAA,KACA,YAAA,WACA,MAAA,KACA,iBAAA,KHoiCF,OGhiCA,MHiiCA,OACA,SG9hCE,YAAA,QACA,UAAA,QACA,YAAA,QAMF,EACE,MAAA,QACA,gBAAA,KH8hCF,QG5hCE,QAEE,MAAA,QACA,gBAAA,UAGF,QEnDA,QAAA,IAAA,KAAA,yBACA,eAAA,KF6DF,OACE,OAAA,EAMF,IACE,eAAA,OHqhCF,4BADA,0BGhhCA,gBH+gCA,iBADA,eMxlCE,QAAA,MACA,UAAA,KACA,OAAA,KH6EF,aACE,cAAA,IAMF,eACE,QAAA,IACA,YAAA,WACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,cAAA,IC+FA,mBAAA,IAAA,IAAA,YACK,cAAA,IAAA,IAAA,YACG,WAAA,IAAA,IAAA,YE5LR,QAAA,aACA,UAAA,KACA,OAAA,KHiGF,YACE,cAAA,IAMF,GACE,WAAA,KACA,cAAA,KACA,OAAA,EACA,WAAA,IAAA,MAAA,KAQF,SACE,SAAA,SACA,MAAA,IACA,OAAA,IACA,QAAA,EACA,OAAA,KACA,SAAA,OACA,KAAA,cACA,OAAA,EAQA,0BH8/BF,yBG5/BI,SAAA,OACA,MAAA,KACA,OAAA,KACA,OAAA,EACA,SAAA,QACA,KAAA,KAWJ,cACE,OAAA,QH4/BF,IACA,IACA,IACA,IACA,IACA,IOtpCA,GP4oCA,GACA,GACA,GACA,GACA,GO9oCE,YAAA,QACA,YAAA,IACA,YAAA,IACA,MAAA,QPyqCF,WAZA,UAaA,WAZA,UAaA,WAZA,UAaA,WAZA,UAaA,WAZA,UAaA,WAZA,UACA,UOxqCA,SPyqCA,UAZA,SAaA,UAZA,SAaA,UAZA,SAaA,UAZA,SAaA,UAZA,SOxpCI,YAAA,IACA,YAAA,EACA,MAAA,KP8qCJ,IAEA,IAEA,IO9qCA,GP2qCA,GAEA,GO1qCE,WAAA,KACA,cAAA,KPqrCF,WANA,UAQA,WANA,UAQA,WANA,UACA,UOxrCA,SP0rCA,UANA,SAQA,UANA,SO9qCI,UAAA,IPyrCJ,IAEA,IAEA,IO1rCA,GPurCA,GAEA,GOtrCE,WAAA,KACA,cAAA,KPisCF,WANA,UAQA,WANA,UAQA,WANA,UACA,UOpsCA,SPssCA,UANA,SAQA,UANA,SO1rCI,UAAA,IPqsCJ,IOjsCA,GAAU,UAAA,KPqsCV,IOpsCA,GAAU,UAAA,KPwsCV,IOvsCA,GAAU,UAAA,KP2sCV,IO1sCA,GAAU,UAAA,KP8sCV,IO7sCA,GAAU,UAAA,KPitCV,IOhtCA,GAAU,UAAA,KAMV,EACE,OAAA,EAAA,EAAA,KAGF,MACE,cAAA,KACA,UAAA,KACA,YAAA,IACA,YAAA,IAEA,yBAAA,MACE,UAAA,MPitCJ,OOxsCA,MAEE,UAAA,IP0sCF,MOvsCA,KAEE,QAAA,KACA,iBAAA,QAIF,WAAuB,WAAA,KACvB,YAAuB,WAAA,MACvB,aAAuB,WAAA,OACvB,cAAuB,WAAA,QACvB,aAAuB,YAAA,OAGvB,gBAAuB,eAAA,UACvB,gBAAuB,eAAA,UACvB,iBAAuB,eAAA,WAGvB,YACE,MAAA,KAEF,cCvGE,MAAA,QR2zCF,qBQ1zCE,qBAEE,MAAA,QDuGJ,cC1GE,MAAA,QRk0CF,qBQj0CE,qBAEE,MAAA,QD0GJ,WC7GE,MAAA,QRy0CF,kBQx0CE,kBAEE,MAAA,QD6GJ,cChHE,MAAA,QRg1CF,qBQ/0CE,qBAEE,MAAA,QDgHJ,aCnHE,MAAA,QRu1CF,oBQt1CE,oBAEE,MAAA,QDuHJ,YAGE,MAAA,KE7HA,iBAAA,QT+1CF,mBS91CE,mBAEE,iBAAA,QF6HJ,YEhIE,iBAAA,QTs2CF,mBSr2CE,mBAEE,iBAAA,QFgIJ,SEnIE,iBAAA,QT62CF,gBS52CE,gBAEE,iBAAA,QFmIJ,YEtIE,iBAAA,QTo3CF,mBSn3CE,mBAEE,iBAAA,QFsIJ,WEzIE,iBAAA,QT23CF,kBS13CE,kBAEE,iBAAA,QF8IJ,aACE,eAAA,IACA,OAAA,KAAA,EAAA,KACA,cAAA,IAAA,MAAA,KPgvCF,GOxuCA,GAEE,WAAA,EACA,cAAA,KP4uCF,MAFA,MACA,MO9uCA,MAMI,cAAA,EAOJ,eACE,aAAA,EACA,WAAA,KAIF,aALE,aAAA,EACA,WAAA,KAMA,YAAA,KAFF,gBAKI,QAAA,aACA,cAAA,IACA,aAAA,IAKJ,GACE,WAAA,EACA,cAAA,KPouCF,GOluCA,GAEE,YAAA,WAEF,GACE,YAAA,IAEF,GACE,YAAA,EAaA,yBAAA,kBAEI,MAAA,KACA,MAAA,MACA,MAAA,KACA,WAAA,MGxNJ,SAAA,OACA,cAAA,SACA,YAAA,OHiNA,kBASI,YAAA,OP4tCN,0BOjtCA,YAEE,OAAA,KAGF,YACE,UAAA,IA9IqB,eAAA,UAmJvB,WACE,QAAA,KAAA,KACA,OAAA,EAAA,EAAA,KACA,UAAA,OACA,YAAA,IAAA,MAAA,KPitCF,yBO5sCI,wBP2sCJ,yBO1sCM,cAAA,EPgtCN,kBO1tCA,kBPytCA,iBOtsCI,QAAA,MACA,UAAA,IACA,YAAA,WACA,MAAA,KP4sCJ,yBO1sCI,yBPysCJ,wBOxsCM,QAAA,cAQN,oBPqsCA,sBOnsCE,cAAA,KACA,aAAA,EACA,WAAA,MACA,aAAA,IAAA,MAAA,KACA,YAAA,EP0sCF,kCOpsCI,kCPksCJ,iCAGA,oCAJA,oCAEA,mCOnsCe,QAAA,GP4sCf,iCO3sCI,iCPysCJ,gCAGA,mCAJA,mCAEA,kCOzsCM,QAAA,cAMN,QACE,cAAA,KACA,WAAA,OACA,YAAA,WIxSF,KXm/CA,IACA,IACA,KWj/CE,YAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,aAAA,CAAA,UAIF,KACE,QAAA,IAAA,IACA,UAAA,IACA,MAAA,QACA,iBAAA,QACA,cAAA,IAIF,IACE,QAAA,IAAA,IACA,UAAA,IACA,MAAA,KACA,iBAAA,KACA,cAAA,IACA,mBAAA,MAAA,EAAA,KAAA,EAAA,gBAAA,WAAA,MAAA,EAAA,KAAA,EAAA,gBANF,QASI,QAAA,EACA,UAAA,KACA,YAAA,IACA,mBAAA,KAAA,WAAA,KAKJ,IACE,QAAA,MACA,QAAA,MACA,OAAA,EAAA,EAAA,KACA,UAAA,KACA,YAAA,WACA,MAAA,KACA,WAAA,UACA,UAAA,WACA,iBAAA,QACA,OAAA,IAAA,MAAA,KACA,cAAA,IAXF,SAeI,QAAA,EACA,UAAA,QACA,MAAA,QACA,YAAA,SACA,iBAAA,YACA,cAAA,EAKJ,gBACE,WAAA,MACA,WAAA,OC1DF,WCHE,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KDGA,yBAAA,WACE,MAAA,OAEF,yBAAA,WACE,MAAA,OAEF,0BAAA,WACE,MAAA,QAUJ,iBCvBE,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KD6BF,KCvBE,aAAA,MACA,YAAA,MD0BF,gBACE,aAAA,EACA,YAAA,EAFF,8BAKI,cAAA,EACA,aAAA,EZwiDJ,UAoCA,WAIA,WAIA,WAxCA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAjCA,UAoCA,WAIA,WAIA,WAxCA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAjCA,UAoCA,WAIA,WAIA,WAxCA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UatnDC,UbynDD,WAIA,WAIA,WAxCA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UAIA,UcpmDM,SAAA,SAEA,WAAA,IAEA,cAAA,KACA,aAAA,KDtBL,UbmpDD,WACA,WACA,WAVA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,Uc3mDM,MAAA,KDvCL,WC+CG,MAAA,KD/CH,WC+CG,MAAA,aD/CH,WC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,YD/CH,gBC8DG,MAAA,KD9DH,gBC8DG,MAAA,aD9DH,gBC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,YD9DH,eCmEG,MAAA,KDnEH,gBCoDG,KAAA,KDpDH,gBCoDG,KAAA,aDpDH,gBCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,YDpDH,eCyDG,KAAA,KDzDH,kBCwEG,YAAA,KDxEH,kBCwEG,YAAA,aDxEH,kBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,YDxEH,iBCwEG,YAAA,EFCJ,yBCzEC,Ub2zDC,WACA,WACA,WAVA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UcnxDI,MAAA,KDvCL,WC+CG,MAAA,KD/CH,WC+CG,MAAA,aD/CH,WC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,YD/CH,gBC8DG,MAAA,KD9DH,gBC8DG,MAAA,aD9DH,gBC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,YD9DH,eCmEG,MAAA,KDnEH,gBCoDG,KAAA,KDpDH,gBCoDG,KAAA,aDpDH,gBCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,YDpDH,eCyDG,KAAA,KDzDH,kBCwEG,YAAA,KDxEH,kBCwEG,YAAA,aDxEH,kBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,YDxEH,iBCwEG,YAAA,GFUJ,yBClFC,Ubo+DC,WACA,WACA,WAVA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,Uc57DI,MAAA,KDvCL,WC+CG,MAAA,KD/CH,WC+CG,MAAA,aD/CH,WC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,YD/CH,gBC8DG,MAAA,KD9DH,gBC8DG,MAAA,aD9DH,gBC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,YD9DH,eCmEG,MAAA,KDnEH,gBCoDG,KAAA,KDpDH,gBCoDG,KAAA,aDpDH,gBCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,YDpDH,eCyDG,KAAA,KDzDH,kBCwEG,YAAA,KDxEH,kBCwEG,YAAA,aDxEH,kBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,YDxEH,iBCwEG,YAAA,GFmBJ,0BC3FC,Ub6oEC,WACA,WACA,WAVA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UcrmEI,MAAA,KDvCL,WC+CG,MAAA,KD/CH,WC+CG,MAAA,aD/CH,WC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,ID/CH,UC+CG,MAAA,aD/CH,UC+CG,MAAA,YD/CH,gBC8DG,MAAA,KD9DH,gBC8DG,MAAA,aD9DH,gBC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,ID9DH,eC8DG,MAAA,aD9DH,eC8DG,MAAA,YD9DH,eCmEG,MAAA,KDnEH,gBCoDG,KAAA,KDpDH,gBCoDG,KAAA,aDpDH,gBCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,IDpDH,eCoDG,KAAA,aDpDH,eCoDG,KAAA,YDpDH,eCyDG,KAAA,KDzDH,kBCwEG,YAAA,KDxEH,kBCwEG,YAAA,aDxEH,kBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,IDxEH,iBCwEG,YAAA,aDxEH,iBCwEG,YAAA,YDxEH,iBCwEG,YAAA,GCjEJ,MACE,iBAAA,YADF,uBAQI,SAAA,OACA,QAAA,aACA,MAAA,KAKA,sBf+xEJ,sBe9xEM,SAAA,OACA,QAAA,WACA,MAAA,KAKN,QACE,YAAA,IACA,eAAA,IACA,MAAA,KACA,WAAA,KAGF,GACE,WAAA,KAMF,OACE,MAAA,KACA,UAAA,KACA,cAAA,Kf6xEF,mBAHA,mBAIA,mBAHA,mBACA,mBe/xEA,mBAWQ,QAAA,IACA,YAAA,WACA,eAAA,IACA,WAAA,IAAA,MAAA,KAdR,mBAoBI,eAAA,OACA,cAAA,IAAA,MAAA,KfyxEJ,uCe9yEA,uCf+yEA,wCAHA,wCAIA,2CAHA,2Ce/wEQ,WAAA,EA9BR,mBAoCI,WAAA,IAAA,MAAA,KApCJ,cAyCI,iBAAA,KfoxEJ,6BAHA,6BAIA,6BAHA,6BACA,6Be5wEA,6BAOQ,QAAA,IAWR,gBACE,OAAA,IAAA,MAAA,KfqwEF,4BAHA,4BAIA,4BAHA,4BACA,4BerwEA,4BAQQ,OAAA,IAAA,MAAA,KfmwER,4Be3wEA,4BAeM,oBAAA,IAUN,yCAEI,iBAAA,QASJ,4BAEI,iBAAA,QfqvEJ,0BAGA,0BATA,0BAGA,0BAIA,0BAGA,0BATA,0BAGA,0BACA,0BAGA,0BgBt4EE,0BhBg4EF,0BgBz3EM,iBAAA,QhBs4EN,sCAEA,sCADA,oCgBj4EE,sChB+3EF,sCgBz3EM,iBAAA,QhBs4EN,2BAGA,2BATA,2BAGA,2BAIA,2BAGA,2BATA,2BAGA,2BACA,2BAGA,2BgB35EE,2BhBq5EF,2BgB94EM,iBAAA,QhB25EN,uCAEA,uCADA,qCgBt5EE,uChBo5EF,uCgB94EM,iBAAA,QhB25EN,wBAGA,wBATA,wBAGA,wBAIA,wBAGA,wBATA,wBAGA,wBACA,wBAGA,wBgBh7EE,wBhB06EF,wBgBn6EM,iBAAA,QhBg7EN,oCAEA,oCADA,kCgB36EE,oChBy6EF,oCgBn6EM,iBAAA,QhBg7EN,2BAGA,2BATA,2BAGA,2BAIA,2BAGA,2BATA,2BAGA,2BACA,2BAGA,2BgBr8EE,2BhB+7EF,2BgBx7EM,iBAAA,QhBq8EN,uCAEA,uCADA,qCgBh8EE,uChB87EF,uCgBx7EM,iBAAA,QhBq8EN,0BAGA,0BATA,0BAGA,0BAIA,0BAGA,0BATA,0BAGA,0BACA,0BAGA,0BgB19EE,0BhBo9EF,0BgB78EM,iBAAA,QhB09EN,sCAEA,sCADA,oCgBr9EE,sChBm9EF,sCgB78EM,iBAAA,QDoJN,kBACE,WAAA,KACA,WAAA,KAEA,oCAAA,kBACE,MAAA,KACA,cAAA,KACA,WAAA,OACA,mBAAA,yBACA,OAAA,IAAA,MAAA,KALF,yBASI,cAAA,Efq0EJ,qCAHA,qCAIA,qCAHA,qCACA,qCe70EA,qCAkBU,YAAA,OAlBV,kCA0BI,OAAA,Ef+zEJ,0DAHA,0DAIA,0DAHA,0DACA,0Dex1EA,0DAmCU,YAAA,Ef8zEV,yDAHA,yDAIA,yDAHA,yDACA,yDeh2EA,yDAuCU,aAAA,Efg0EV,yDev2EA,yDfw2EA,yDAFA,yDelzEU,cAAA,GEzNZ,SAIE,UAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EAGF,OACE,QAAA,MACA,MAAA,KACA,QAAA,EACA,cAAA,KACA,UAAA,KACA,YAAA,QACA,MAAA,KACA,OAAA,EACA,cAAA,IAAA,MAAA,QAGF,MACE,QAAA,aACA,UAAA,KACA,cAAA,IACA,YAAA,IAUF,mBb6BE,mBAAA,WACG,gBAAA,WACK,WAAA,WarBR,mBAAA,KACA,gBAAA,KAAA,WAAA,KjBkgFF,qBiB9/EA,kBAEE,OAAA,IAAA,EAAA,EACA,WAAA,MACA,YAAA,OjBogFF,wCADA,qCADA,8BAFA,+BACA,2BiB3/EE,4BAGE,OAAA,YAIJ,iBACE,QAAA,MAIF,kBACE,QAAA,MACA,MAAA,KAIF,iBjBu/EA,aiBr/EE,OAAA,KjB0/EF,2BiBt/EA,uBjBq/EA,wBK/kFE,QAAA,IAAA,KAAA,yBACA,eAAA,KYgGF,OACE,QAAA,MACA,YAAA,IACA,UAAA,KACA,YAAA,WACA,MAAA,KA0BF,cACE,QAAA,MACA,MAAA,KACA,OAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,WACA,MAAA,KACA,iBAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,cAAA,Ib3EA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBAyHR,mBAAA,aAAA,YAAA,IAAA,CAAA,WAAA,YAAA,KACK,cAAA,aAAA,YAAA,IAAA,CAAA,WAAA,YAAA,KACG,mBAAA,aAAA,YAAA,IAAA,CAAA,mBAAA,YAAA,KAAA,WAAA,aAAA,YAAA,IAAA,CAAA,mBAAA,YAAA,KAAA,WAAA,aAAA,YAAA,IAAA,CAAA,WAAA,YAAA,KAAA,WAAA,aAAA,YAAA,IAAA,CAAA,WAAA,YAAA,IAAA,CAAA,mBAAA,YAAA,Kc1IR,oBACE,aAAA,QACA,QAAA,EdYF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,qBAiCR,gCACE,MAAA,KACA,QAAA,EAEF,oCAA0B,MAAA,KAC1B,yCAAgC,MAAA,Ka+ChC,0BACE,iBAAA,YACA,OAAA,EAQF,wBjBq+EF,wBACA,iCiBn+EI,iBAAA,KACA,QAAA,EAGF,wBjBo+EF,iCiBl+EI,OAAA,YAIF,sBACE,OAAA,KAcJ,qDAKI,8BjBm9EF,wCACA,+BAFA,8BiBj9EI,YAAA,KjB09EJ,iCAEA,2CACA,kCAFA,iCiBx9EE,0BjBq9EF,oCACA,2BAFA,0BiBl9EI,YAAA,KjB+9EJ,iCAEA,2CACA,kCAFA,iCiB79EE,0BjB09EF,oCACA,2BAFA,0BiBv9EI,YAAA,MAWN,YACE,cAAA,KjBy9EF,UiBj9EA,OAEE,SAAA,SACA,QAAA,MACA,WAAA,KACA,cAAA,KjBm9EF,yBiBh9EE,sBjBk9EF,mCADA,gCiB98EM,OAAA,YjBm9EN,gBiB99EA,aAgBI,WAAA,KACA,aAAA,KACA,cAAA,EACA,YAAA,IACA,OAAA,QjBm9EJ,+BACA,sCiBj9EA,yBjB+8EA,gCiB38EE,SAAA,SACA,WAAA,MACA,YAAA,MjBi9EF,oBiB98EA,cAEE,WAAA,KjBg9EF,iBiB58EA,cAEE,SAAA,SACA,QAAA,aACA,aAAA,KACA,cAAA,EACA,YAAA,IACA,eAAA,OACA,OAAA,QjB88EF,0BiB38EE,uBjB68EF,oCADA,iCiB18EI,OAAA,YjB+8EJ,kCiB58EA,4BAEE,WAAA,EACA,YAAA,KASF,qBACE,WAAA,KAEA,YAAA,IACA,eAAA,IAEA,cAAA,EAEA,8BjBm8EF,8BiBj8EI,cAAA,EACA,aAAA,EAaJ,UC3PE,OAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IACA,cAAA,IAEA,gBACE,OAAA,KACA,YAAA,KlBsrFJ,0BkBnrFE,kBAEE,OAAA,KDiPJ,6BAEI,OAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IACA,cAAA,IANJ,mCASI,OAAA,KACA,YAAA,KjBq8EJ,6CiB/8EA,qCAcI,OAAA,KAdJ,oCAiBI,OAAA,KACA,WAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IAIJ,UCvRE,OAAA,KACA,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UACA,cAAA,IAEA,gBACE,OAAA,KACA,YAAA,KlB2tFJ,0BkBxtFE,kBAEE,OAAA,KD6QJ,6BAEI,OAAA,KACA,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UACA,cAAA,IANJ,mCASI,OAAA,KACA,YAAA,KjB88EJ,6CiBx9EA,qCAcI,OAAA,KAdJ,oCAiBI,OAAA,KACA,WAAA,KACA,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UASJ,cAEE,SAAA,SAFF,4BAMI,cAAA,OAIJ,uBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,QAAA,EACA,QAAA,MACA,MAAA,KACA,OAAA,KACA,YAAA,KACA,WAAA,OACA,eAAA,KjBo8EF,oDADA,uCiBj8EA,iCAGE,MAAA,KACA,OAAA,KACA,YAAA,KjBo8EF,oDADA,uCiBj8EA,iCAGE,MAAA,KACA,OAAA,KACA,YAAA,KjBq8EF,uBAEA,8BAJA,4BiB/7EA,yBjBg8EA,oBAEA,2BAGA,4BAEA,mCAHA,yBAEA,gCkBx1FI,MAAA,QDkZJ,2BC9YI,aAAA,QdiDF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBchDN,iCACE,aAAA,Qd8CJ,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,QACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,Qa4VV,gCCpYI,MAAA,QACA,iBAAA,QACA,aAAA,QDkYJ,oCC9XI,MAAA,QlB61FJ,uBAEA,8BAJA,4BiB19EA,yBjB29EA,oBAEA,2BAGA,4BAEA,mCAHA,yBAEA,gCkBt3FI,MAAA,QDqZJ,2BCjZI,aAAA,QdiDF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBchDN,iCACE,aAAA,Qd8CJ,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,QACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,Qa+VV,gCCvYI,MAAA,QACA,iBAAA,QACA,aAAA,QDqYJ,oCCjYI,MAAA,QlB23FJ,qBAEA,4BAJA,0BiBr/EA,uBjBs/EA,kBAEA,yBAGA,0BAEA,iCAHA,uBAEA,8BkBp5FI,MAAA,QDwZJ,yBCpZI,aAAA,QdiDF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBchDN,+BACE,aAAA,Qd8CJ,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,QACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,CAAA,EAAA,EAAA,IAAA,QakWV,8BC1YI,MAAA,QACA,iBAAA,QACA,aAAA,QDwYJ,kCCpYI,MAAA,QD2YF,2CACE,IAAA,KAEF,mDACE,IAAA,EAUJ,YACE,QAAA,MACA,WAAA,IACA,cAAA,KACA,MAAA,QAkBA,yBAAA,yBAGI,QAAA,aACA,cAAA,EACA,eAAA,OALJ,2BAUI,QAAA,aACA,MAAA,KACA,eAAA,OAZJ,kCAiBI,QAAA,aAjBJ,0BAqBI,QAAA,aACA,eAAA,OjBi/EJ,wCiBvgFA,6CjBsgFA,2CiB3+EM,MAAA,KA3BN,wCAiCI,MAAA,KAjCJ,4BAqCI,cAAA,EACA,eAAA,OjB4+EJ,uBiBlhFA,oBA6CI,QAAA,aACA,WAAA,EACA,cAAA,EACA,eAAA,OjBy+EJ,6BiBzhFA,0BAmDM,aAAA,EjB0+EN,4CiB7hFA,sCAwDI,SAAA,SACA,YAAA,EAzDJ,kDA8DI,IAAA,GjBw+EN,2BAEA,kCiB/9EA,wBjB89EA,+BiBr9EI,YAAA,IACA,WAAA,EACA,cAAA,EjB09EJ,2BiBr+EA,wBAiBI,WAAA,KAjBJ,6BJ9gBE,aAAA,MACA,YAAA,MIwiBA,yBAAA,gCAEI,YAAA,IACA,cAAA,EACA,WAAA,OA/BN,sDAwCI,MAAA,KAQA,yBAAA,+CAEI,YAAA,KACA,UAAA,MAKJ,yBAAA,+CAEI,YAAA,IACA,UAAA,ME9kBR,KACE,QAAA,aACA,cAAA,EACA,YAAA,IACA,WAAA,OACA,YAAA,OACA,eAAA,OACA,iBAAA,aAAA,aAAA,aACA,OAAA,QACA,iBAAA,KACA,OAAA,IAAA,MAAA,YCoCA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,WACA,cAAA,IhBqKA,oBAAA,KACG,iBAAA,KACC,gBAAA,KACI,YAAA,KJs1FV,kBAHA,kBACA,WACA,kBAHA,kBmB1hGI,WdrBF,QAAA,IAAA,KAAA,yBACA,eAAA,KLwjGF,WADA,WmB7hGE,WAGE,MAAA,KACA,gBAAA,KnB+hGJ,YmB5hGE,YAEE,iBAAA,KACA,QAAA,Ef2BF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBexBR,cnB4hGF,eACA,wBmB1hGI,OAAA,YE9CF,OAAA,kBACA,QAAA,IjBiEA,mBAAA,KACQ,WAAA,KefN,enB4hGJ,yBmB1hGM,eAAA,KASN,aC7DE,MAAA,KACA,iBAAA,KACA,aAAA,KpBqlGF,mBoBnlGE,mBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpBqlGJ,oBoBnlGE,oBpBolGF,mCoBjlGI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpB2lGJ,0BAHA,0BAHA,0BAKA,0BAHA,0BoBrlGI,0BpB0lGJ,yCAHA,yCAHA,yCoBjlGM,MAAA,KACA,iBAAA,QACA,aAAA,QpBgmGN,4BAHA,4BoBvlGI,4BpB2lGJ,6BAHA,6BAHA,6BAOA,sCAHA,sCAHA,sCoBnlGM,iBAAA,KACA,aAAA,KDuBN,oBClBI,MAAA,KACA,iBAAA,KDoBJ,aChEE,MAAA,KACA,iBAAA,QACA,aAAA,QpB0oGF,mBoBxoGE,mBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpB0oGJ,oBoBxoGE,oBpByoGF,mCoBtoGI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpBgpGJ,0BAHA,0BAHA,0BAKA,0BAHA,0BoB1oGI,0BpB+oGJ,yCAHA,yCAHA,yCoBtoGM,MAAA,KACA,iBAAA,QACA,aAAA,QpBqpGN,4BAHA,4BoB5oGI,4BpBgpGJ,6BAHA,6BAHA,6BAOA,sCAHA,sCAHA,sCoBxoGM,iBAAA,QACA,aAAA,QD0BN,oBCrBI,MAAA,QACA,iBAAA,KDwBJ,aCpEE,MAAA,KACA,iBAAA,QACA,aAAA,QpB+rGF,mBoB7rGE,mBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpB+rGJ,oBoB7rGE,oBpB8rGF,mCoB3rGI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpBqsGJ,0BAHA,0BAHA,0BAKA,0BAHA,0BoB/rGI,0BpBosGJ,yCAHA,yCAHA,yCoB3rGM,MAAA,KACA,iBAAA,QACA,aAAA,QpB0sGN,4BAHA,4BoBjsGI,4BpBqsGJ,6BAHA,6BAHA,6BAOA,sCAHA,sCAHA,sCoB7rGM,iBAAA,QACA,aAAA,QD8BN,oBCzBI,MAAA,QACA,iBAAA,KD4BJ,UCxEE,MAAA,KACA,iBAAA,QACA,aAAA,QpBovGF,gBoBlvGE,gBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,gBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpBovGJ,iBoBlvGE,iBpBmvGF,gCoBhvGI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpB0vGJ,uBAHA,uBAHA,uBAKA,uBAHA,uBoBpvGI,uBpByvGJ,sCAHA,sCAHA,sCoBhvGM,MAAA,KACA,iBAAA,QACA,aAAA,QpB+vGN,yBAHA,yBoBtvGI,yBpB0vGJ,0BAHA,0BAHA,0BAOA,mCAHA,mCAHA,mCoBlvGM,iBAAA,QACA,aAAA,QDkCN,iBC7BI,MAAA,QACA,iBAAA,KDgCJ,aC5EE,MAAA,KACA,iBAAA,QACA,aAAA,QpByyGF,mBoBvyGE,mBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpByyGJ,oBoBvyGE,oBpBwyGF,mCoBryGI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpB+yGJ,0BAHA,0BAHA,0BAKA,0BAHA,0BoBzyGI,0BpB8yGJ,yCAHA,yCAHA,yCoBryGM,MAAA,KACA,iBAAA,QACA,aAAA,QpBozGN,4BAHA,4BoB3yGI,4BpB+yGJ,6BAHA,6BAHA,6BAOA,sCAHA,sCAHA,sCoBvyGM,iBAAA,QACA,aAAA,QDsCN,oBCjCI,MAAA,QACA,iBAAA,KDoCJ,YChFE,MAAA,KACA,iBAAA,QACA,aAAA,QpB81GF,kBoB51GE,kBAEE,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,kBACE,MAAA,KACA,iBAAA,QACA,aAAA,QpB81GJ,mBoB51GE,mBpB61GF,kCoB11GI,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QpBo2GJ,yBAHA,yBAHA,yBAKA,yBAHA,yBoB91GI,yBpBm2GJ,wCAHA,wCAHA,wCoB11GM,MAAA,KACA,iBAAA,QACA,aAAA,QpBy2GN,2BAHA,2BoBh2GI,2BpBo2GJ,4BAHA,4BAHA,4BAOA,qCAHA,qCAHA,qCoB51GM,iBAAA,QACA,aAAA,QD0CN,mBCrCI,MAAA,QACA,iBAAA,KD6CJ,UACE,YAAA,IACA,MAAA,QACA,cAAA,EAEA,UnBwzGF,iBADA,iBAEA,oBACA,6BmBrzGI,iBAAA,YfnCF,mBAAA,KACQ,WAAA,KeqCR,UnB0zGF,iBADA,gBADA,gBmBpzGI,aAAA,YnB0zGJ,gBmBxzGE,gBAEE,MAAA,QACA,gBAAA,UACA,iBAAA,YnB2zGJ,0BmBvzGI,0BnBwzGJ,mCAFA,mCmBpzGM,MAAA,KACA,gBAAA,KnB0zGN,mBmBjzGA,QC9EE,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UACA,cAAA,IpBm4GF,mBmBpzGA,QClFE,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IACA,cAAA,IpB04GF,mBmBvzGA,QCtFE,QAAA,IAAA,IACA,UAAA,KACA,YAAA,IACA,cAAA,ID2FF,WACE,QAAA,MACA,MAAA,KAIF,sBACE,WAAA,InBuzGF,6BADA,4BmB/yGE,6BACE,MAAA,KG1JJ,MACE,QAAA,ElBoLA,mBAAA,QAAA,KAAA,OACK,cAAA,QAAA,KAAA,OACG,WAAA,QAAA,KAAA,OkBnLR,SACE,QAAA,EAIJ,UACE,QAAA,KAEA,aAAY,QAAA,MACZ,eAAY,QAAA,UACZ,kBAAY,QAAA,gBAGd,YACE,SAAA,SACA,OAAA,EACA,SAAA,OlBsKA,4BAAA,MAAA,CAAA,WACQ,uBAAA,MAAA,CAAA,WAAA,oBAAA,MAAA,CAAA,WAOR,4BAAA,KACQ,uBAAA,KAAA,oBAAA,KAGR,mCAAA,KACQ,8BAAA,KAAA,2BAAA,KmB5MV,OACE,QAAA,aACA,MAAA,EACA,OAAA,EACA,YAAA,IACA,eAAA,OACA,WAAA,IAAA,OACA,WAAA,IAAA,QACA,aAAA,IAAA,MAAA,YACA,YAAA,IAAA,MAAA,YvBu/GF,UuBn/GA,QAEE,SAAA,SAIF,uBACE,QAAA,EAIF,eACE,SAAA,SACA,IAAA,KACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,MAAA,KACA,UAAA,MACA,QAAA,IAAA,EACA,OAAA,IAAA,EAAA,EACA,UAAA,KACA,WAAA,KACA,WAAA,KACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,KACA,OAAA,IAAA,MAAA,gBACA,cAAA,InBuBA,mBAAA,EAAA,IAAA,KAAA,iBACQ,WAAA,EAAA,IAAA,KAAA,iBmBlBR,0BACE,MAAA,EACA,KAAA,KAzBJ,wBCzBE,OAAA,IACA,OAAA,IAAA,EACA,SAAA,OACA,iBAAA,QDsBF,oBAmCI,QAAA,MACA,QAAA,IAAA,KACA,MAAA,KACA,YAAA,IACA,YAAA,WACA,MAAA,KACA,YAAA,OvB8+GJ,0BuB5+GI,0BAEE,MAAA,QACA,gBAAA,KACA,iBAAA,QAOJ,yBvBw+GF,+BADA,+BuBp+GI,MAAA,KACA,gBAAA,KACA,iBAAA,QACA,QAAA,EASF,2BvBi+GF,iCADA,iCuB79GI,MAAA,KvBk+GJ,iCuB99GE,iCAEE,gBAAA,KACA,OAAA,YACA,iBAAA,YACA,iBAAA,KEzGF,OAAA,0DF+GF,qBAGI,QAAA,MAHJ,QAQI,QAAA,EAQJ,qBACE,MAAA,EACA,KAAA,KAQF,oBACE,MAAA,KACA,KAAA,EAIF,iBACE,QAAA,MACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,WACA,MAAA,KACA,YAAA,OAIF,mBACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,IAIF,2BACE,MAAA,EACA,KAAA,KAQF,evB+7GA,sCuB37GI,QAAA,GACA,WAAA,EACA,cAAA,IAAA,OACA,cAAA,IAAA,QAPJ,uBvBs8GA,8CuB37GI,IAAA,KACA,OAAA,KACA,cAAA,IASJ,yBACE,6BApEA,MAAA,EACA,KAAA,KAmEA,kCA1DA,MAAA,KACA,KAAA,GG1IF,W1BkoHA,oB0BhoHE,SAAA,SACA,QAAA,aACA,eAAA,O1BooHF,yB0BxoHA,gBAMI,SAAA,SACA,MAAA,K1B4oHJ,gCAFA,gCAFA,+BAFA,+BAKA,uBAFA,uBAFA,sB0BroHI,sBAIE,QAAA,EAMN,qB1BooHA,2BACA,2BACA,iC0BjoHI,YAAA,KAKJ,aACE,YAAA,KADF,kB1BmoHA,wBACA,0B0B7nHI,MAAA,KAPJ,kB1BwoHA,wBACA,0B0B7nHI,YAAA,IAIJ,yEACE,cAAA,EAIF,4BACE,YAAA,EACA,mECpDA,wBAAA,EACA,2BAAA,EDwDF,6C1B2nHA,8C2B5qHE,uBAAA,EACA,0BAAA,EDsDF,sBACE,MAAA,KAEF,8DACE,cAAA,EAEF,mE1B0nHA,oE2B/rHE,wBAAA,EACA,2BAAA,ED0EF,oECnEE,uBAAA,EACA,0BAAA,EDuEF,mC1BwnHA,iC0BtnHE,QAAA,EAiBF,iCACE,cAAA,IACA,aAAA,IAEF,oCACE,cAAA,KACA,aAAA,KAKF,iCtB/CE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBsBkDR,0CtBnDA,mBAAA,KACQ,WAAA,KsByDV,YACE,YAAA,EAGF,eACE,aAAA,IAAA,IAAA,EACA,oBAAA,EAGF,uBACE,aAAA,EAAA,IAAA,IAOF,yB1B4lHA,+BACA,oC0BzlHI,QAAA,MACA,MAAA,KACA,MAAA,KACA,UAAA,KAPJ,oCAcM,MAAA,KAdN,8B1BumHA,oCACA,oCACA,0C0BnlHI,WAAA,KACA,YAAA,EAKF,4DACE,cAAA,EAEF,sDC7KA,uBAAA,IACA,wBAAA,IAOA,2BAAA,EACA,0BAAA,EDwKA,sDCjLA,uBAAA,EACA,wBAAA,EAOA,2BAAA,IACA,0BAAA,ID6KF,uEACE,cAAA,EAEF,4E1BqlHA,6E2BtwHE,2BAAA,EACA,0BAAA,EDsLF,6EC/LE,uBAAA,EACA,wBAAA,EDsMF,qBACE,QAAA,MACA,MAAA,KACA,aAAA,MACA,gBAAA,SAJF,0B1BslHA,gC0B/kHI,QAAA,WACA,MAAA,KACA,MAAA,GATJ,qCAYI,MAAA,KAZJ,+CAgBI,KAAA,K1BmlHJ,gD0BlkHA,6C1BmkHA,2DAFA,wD0B5jHM,SAAA,SACA,KAAA,cACA,eAAA,KE1ON,aACE,SAAA,SACA,QAAA,MACA,gBAAA,SAGA,0BACE,MAAA,KACA,cAAA,EACA,aAAA,EATJ,2BAeI,SAAA,SACA,QAAA,EAKA,MAAA,KAEA,MAAA,KACA,cAAA,EAEA,iCACE,QAAA,EAUN,8B5B2xHA,mCACA,sCkBpwHE,OAAA,KACA,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UACA,cAAA,IAEA,oClBswHF,yCACA,4CkBtwHI,OAAA,KACA,YAAA,KlB4wHJ,8CACA,mDACA,sDkB3wHE,sClBuwHF,2CACA,8CkBtwHI,OAAA,KUhCJ,8B5B6yHA,mCACA,sCkB3xHE,OAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IACA,cAAA,IAEA,oClB6xHF,yCACA,4CkB7xHI,OAAA,KACA,YAAA,KlBmyHJ,8CACA,mDACA,sDkBlyHE,sClB8xHF,2CACA,8CkB7xHI,OAAA,KlBqyHJ,2B4B5zHA,mB5B2zHA,iB4BxzHE,QAAA,W5B8zHF,8D4B5zHE,sD5B2zHF,oD4B1zHI,cAAA,EAIJ,mB5B2zHA,iB4BzzHE,MAAA,GACA,YAAA,OACA,eAAA,OAKF,mBACE,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,WAAA,OACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,cAAA,IAGA,4BACE,QAAA,IAAA,KACA,UAAA,KACA,cAAA,IAEF,4BACE,QAAA,KAAA,KACA,UAAA,KACA,cAAA,I5ByzHJ,wC4B70HA,qCA0BI,WAAA,EAKJ,uC5BkzHA,+BACA,kCACA,6CACA,8CAEA,6DADA,wE2B55HE,wBAAA,EACA,2BAAA,EC8GF,+BACE,aAAA,EAEF,sC5BmzHA,8BAKA,+DADA,oDAHA,iCACA,4CACA,6C2Bh6HE,uBAAA,EACA,0BAAA,ECkHF,8BACE,YAAA,EAKF,iBACE,SAAA,SAGA,UAAA,EACA,YAAA,OALF,sBAUI,SAAA,SAVJ,2BAYM,YAAA,K5BizHN,6BADA,4B4B7yHI,4BAGE,QAAA,EAKJ,kC5B0yHF,wC4BvyHM,aAAA,KAGJ,iC5BwyHF,uC4BryHM,QAAA,EACA,YAAA,KC/JN,KACE,aAAA,EACA,cAAA,EACA,WAAA,KAHF,QAOI,SAAA,SACA,QAAA,MARJ,UAWM,SAAA,SACA,QAAA,MACA,QAAA,KAAA,K7By8HN,gB6Bx8HM,gBAEE,gBAAA,KACA,iBAAA,KAKJ,mBACE,MAAA,K7Bu8HN,yB6Br8HM,yBAEE,MAAA,KACA,gBAAA,KACA,OAAA,YACA,iBAAA,YAOJ,a7Bi8HJ,mBADA,mB6B77HM,iBAAA,KACA,aAAA,QAzCN,kBLLE,OAAA,IACA,OAAA,IAAA,EACA,SAAA,OACA,iBAAA,QKEF,cA0DI,UAAA,KASJ,UACE,cAAA,IAAA,MAAA,KADF,aAGI,MAAA,KAEA,cAAA,KALJ,eASM,aAAA,IACA,YAAA,WACA,OAAA,IAAA,MAAA,YACA,cAAA,IAAA,IAAA,EAAA,EACA,qBACE,aAAA,KAAA,KAAA,KAMF,sB7B86HN,4BADA,4B6B16HQ,MAAA,KACA,OAAA,QACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,oBAAA,YAKN,wBAqDA,MAAA,KA8BA,cAAA,EAnFA,2BAwDE,MAAA,KAxDF,6BA0DI,cAAA,IACA,WAAA,OA3DJ,iDAgEE,IAAA,KACA,KAAA,KAGF,yBAAA,2BAEI,QAAA,WACA,MAAA,GAHJ,6BAKM,cAAA,GAzEN,6BAuFE,aAAA,EACA,cAAA,IAxFF,kC7Bu8HF,wCADA,wC6Bx2HI,OAAA,IAAA,MAAA,KAGF,yBAAA,6BAEI,cAAA,IAAA,MAAA,KACA,cAAA,IAAA,IAAA,EAAA,EAHJ,kC7Bg3HA,wCADA,wC6Bv2HI,oBAAA,MAhGN,cAEI,MAAA,KAFJ,gBAMM,cAAA,IANN,iBASM,YAAA,IAKA,uB7By8HN,6BADA,6B6Br8HQ,MAAA,KACA,iBAAA,QAQR,gBAEI,MAAA,KAFJ,mBAIM,WAAA,IACA,YAAA,EAYN,eACE,MAAA,KADF,kBAII,MAAA,KAJJ,oBAMM,cAAA,IACA,WAAA,OAPN,wCAYI,IAAA,KACA,KAAA,KAGF,yBAAA,kBAEI,QAAA,WACA,MAAA,GAHJ,oBAKM,cAAA,GASR,oBACE,cAAA,EADF,yBAKI,aAAA,EACA,cAAA,IANJ,8B7By7HA,oCADA,oC6B56HI,OAAA,IAAA,MAAA,KAGF,yBAAA,yBAEI,cAAA,IAAA,MAAA,KACA,cAAA,IAAA,IAAA,EAAA,EAHJ,8B7Bo7HA,oCADA,oC6B36HI,oBAAA,MAUN,uBAEI,QAAA,KAFJ,qBAKI,QAAA,MASJ,yBAEE,WAAA,KF7OA,uBAAA,EACA,wBAAA,EGQF,QACE,SAAA,SACA,WAAA,KACA,cAAA,KACA,OAAA,IAAA,MAAA,YAKA,yBAAA,QACE,cAAA,KAaF,yBAAA,eACE,MAAA,MAeJ,iBACE,cAAA,KACA,aAAA,KACA,WAAA,QACA,WAAA,IAAA,MAAA,YACA,mBAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,WAAA,MAAA,EAAA,IAAA,EAAA,qBAEA,2BAAA,MAEA,oBACE,WAAA,KAGF,yBAAA,iBACE,MAAA,KACA,WAAA,EACA,mBAAA,KAAA,WAAA,KAEA,0BACE,QAAA,gBACA,OAAA,eACA,eAAA,EACA,SAAA,kBAGF,oBACE,WAAA,Q9BknIJ,sC8B7mIE,mC9B4mIF,oC8BzmII,cAAA,EACA,aAAA,G9B+mIN,qB8B1mIA,kBAWE,SAAA,MACA,MAAA,EACA,KAAA,EACA,QAAA,K9BmmIF,sC8BjnIA,mCAGI,WAAA,MAEA,4D9BinIF,sC8BjnIE,mCACE,WAAA,OAWJ,yB9B2mIA,qB8B3mIA,kBACE,cAAA,GAIJ,kBACE,IAAA,EACA,aAAA,EAAA,EAAA,IAEF,qBACE,OAAA,EACA,cAAA,EACA,aAAA,IAAA,EAAA,E9B+mIF,kCAFA,gCACA,4B8BtmIA,0BAII,aAAA,MACA,YAAA,MAEA,yB9BwmIF,kCAFA,gCACA,4B8BvmIE,0BACE,aAAA,EACA,YAAA,GAaN,mBACE,QAAA,KACA,aAAA,EAAA,EAAA,IAEA,yBAAA,mBACE,cAAA,GAOJ,cACE,MAAA,KACA,OAAA,KACA,QAAA,KAAA,KACA,UAAA,KACA,YAAA,K9B8lIF,oB8B5lIE,oBAEE,gBAAA,KATJ,kBAaI,QAAA,MAGF,yBACE,iC9B0lIF,uC8BxlII,YAAA,OAWN,eACE,SAAA,SACA,MAAA,MACA,QAAA,IAAA,KACA,aAAA,KC9LA,WAAA,IACA,cAAA,ID+LA,iBAAA,YACA,iBAAA,KACA,OAAA,IAAA,MAAA,YACA,cAAA,IAIA,qBACE,QAAA,EAdJ,yBAmBI,QAAA,MACA,MAAA,KACA,OAAA,IACA,cAAA,IAtBJ,mCAyBI,WAAA,IAGF,yBAAA,eACE,QAAA,MAUJ,YACE,OAAA,MAAA,MADF,iBAII,YAAA,KACA,eAAA,KACA,YAAA,KAGF,yBAAA,iCAGI,SAAA,OACA,MAAA,KACA,MAAA,KACA,WAAA,EACA,iBAAA,YACA,OAAA,EACA,mBAAA,KAAA,WAAA,K9BykIJ,kD8BllIA,sCAYM,QAAA,IAAA,KAAA,IAAA,KAZN,sCAeM,YAAA,K9B0kIN,4C8BzkIM,4CAEE,iBAAA,MAOR,yBAAA,YACE,MAAA,KACA,OAAA,EAFF,eAKI,MAAA,KALJ,iBAOM,YAAA,KACA,eAAA,MAYR,aACE,QAAA,KAAA,KACA,aAAA,MACA,YAAA,MACA,WAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,Y1B5NA,mBAAA,MAAA,EAAA,IAAA,EAAA,oBAAA,CAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,oBAAA,CAAA,EAAA,IAAA,EAAA,qB2BjER,WAAA,IACA,cAAA,Id6cA,yBAAA,yBAGI,QAAA,aACA,cAAA,EACA,eAAA,OALJ,2BAUI,QAAA,aACA,MAAA,KACA,eAAA,OAZJ,kCAiBI,QAAA,aAjBJ,0BAqBI,QAAA,aACA,eAAA,OjB+4HJ,wCiBr6HA,6CjBo6HA,2CiBz4HM,MAAA,KA3BN,wCAiCI,MAAA,KAjCJ,4BAqCI,cAAA,EACA,eAAA,OjB04HJ,uBiBh7HA,oBA6CI,QAAA,aACA,WAAA,EACA,cAAA,EACA,eAAA,OjBu4HJ,6BiBv7HA,0BAmDM,aAAA,EjBw4HN,4CiB37HA,sCAwDI,SAAA,SACA,YAAA,EAzDJ,kDA8DI,IAAA,GaxOF,yBAAA,yBACE,cAAA,IAEA,oCACE,cAAA,GASN,yBAAA,aACE,MAAA,KACA,YAAA,EACA,eAAA,EACA,aAAA,EACA,YAAA,EACA,OAAA,E1BvPF,mBAAA,KACQ,WAAA,M0B+PV,8BACE,WAAA,EHpUA,uBAAA,EACA,wBAAA,EGuUF,mDACE,cAAA,EHzUA,uBAAA,IACA,wBAAA,IAOA,2BAAA,EACA,0BAAA,EG0UF,YChVE,WAAA,IACA,cAAA,IDkVA,mBCnVA,WAAA,KACA,cAAA,KDqVA,mBCtVA,WAAA,KACA,cAAA,KD+VF,aChWE,WAAA,KACA,cAAA,KDkWA,yBAAA,aACE,MAAA,KACA,aAAA,KACA,YAAA,MAaJ,yBACE,aEtWA,MAAA,eFuWA,cE1WA,MAAA,gBF4WE,aAAA,MAFF,4BAKI,aAAA,GAUN,gBACE,iBAAA,QACA,aAAA,QAFF,8BAKI,MAAA,K9BmlIJ,oC8BllII,oCAEE,MAAA,QACA,iBAAA,YATN,6BAcI,MAAA,KAdJ,iCAmBM,MAAA,K9BglIN,uC8B9kIM,uCAEE,MAAA,KACA,iBAAA,YAIF,sC9B6kIN,4CADA,4C8BzkIQ,MAAA,KACA,iBAAA,QAIF,wC9B2kIN,8CADA,8C8BvkIQ,MAAA,KACA,iBAAA,YAOF,oC9BskIN,0CADA,0C8BlkIQ,MAAA,KACA,iBAAA,QAIJ,yBAAA,sDAIM,MAAA,K9BmkIR,4D8BlkIQ,4DAEE,MAAA,KACA,iBAAA,YAIF,2D9BikIR,iEADA,iE8B7jIU,MAAA,KACA,iBAAA,QAIF,6D9B+jIR,mEADA,mE8B3jIU,MAAA,KACA,iBAAA,aA/EZ,+BAuFI,aAAA,K9B4jIJ,qC8B3jII,qCAEE,iBAAA,KA1FN,yCA6FM,iBAAA,KA7FN,iC9B0pIA,6B8BvjII,aAAA,QAnGJ,6BA4GI,MAAA,KACA,mCACE,MAAA,KA9GN,0BAmHI,MAAA,K9BojIJ,gC8BnjII,gCAEE,MAAA,K9BsjIN,0C8BljIM,0C9BmjIN,mDAFA,mD8B/iIQ,MAAA,KAQR,gBACE,iBAAA,KACA,aAAA,QAFF,8BAKI,MAAA,Q9B+iIJ,oC8B9iII,oCAEE,MAAA,KACA,iBAAA,YATN,6BAcI,MAAA,QAdJ,iCAmBM,MAAA,Q9B4iIN,uC8B1iIM,uCAEE,MAAA,KACA,iBAAA,YAIF,sC9ByiIN,4CADA,4C8BriIQ,MAAA,KACA,iBAAA,QAIF,wC9BuiIN,8CADA,8C8BniIQ,MAAA,KACA,iBAAA,YAMF,oC9BmiIN,0CADA,0C8B/hIQ,MAAA,KACA,iBAAA,QAIJ,yBAAA,kEAIM,aAAA,QAJN,0DAOM,iBAAA,QAPN,sDAUM,MAAA,Q9BgiIR,4D8B/hIQ,4DAEE,MAAA,KACA,iBAAA,YAIF,2D9B8hIR,iEADA,iE8B1hIU,MAAA,KACA,iBAAA,QAIF,6D9B4hIR,mEADA,mE8BxhIU,MAAA,KACA,iBAAA,aApFZ,+BA6FI,aAAA,K9BwhIJ,qC8BvhII,qCAEE,iBAAA,KAhGN,yCAmGM,iBAAA,KAnGN,iC9B4nIA,6B8BnhII,aAAA,QAzGJ,6BA6GI,MAAA,QACA,mCACE,MAAA,KA/GN,0BAoHI,MAAA,Q9BqhIJ,gC8BphII,gCAEE,MAAA,K9BuhIN,0C8BnhIM,0C9BohIN,mDAFA,mD8BhhIQ,MAAA,KGtoBR,YACE,QAAA,IAAA,KACA,cAAA,KACA,WAAA,KACA,iBAAA,QACA,cAAA,IALF,eAQI,QAAA,aARJ,yBAWM,QAAA,EAAA,IACA,MAAA,KACA,QAAA,SAbN,oBAkBI,MAAA,KCpBJ,YACE,QAAA,aACA,aAAA,EACA,OAAA,KAAA,EACA,cAAA,IAJF,eAOI,QAAA,OAPJ,iBlCyrJA,oBkC/qJM,SAAA,SACA,MAAA,KACA,QAAA,IAAA,KACA,YAAA,KACA,YAAA,WACA,MAAA,QACA,gBAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,KlCorJN,uBkClrJM,uBlCmrJN,0BAFA,0BkC/qJQ,QAAA,EACA,MAAA,QACA,iBAAA,KACA,aAAA,KAGJ,6BlCkrJJ,gCkC/qJQ,YAAA,EPnBN,uBAAA,IACA,0BAAA,IOsBE,4BlCirJJ,+B2BhtJE,wBAAA,IACA,2BAAA,IOwCE,sBlC+qJJ,4BAFA,4BADA,yBAIA,+BAFA,+BkC3qJM,QAAA,EACA,MAAA,KACA,OAAA,QACA,iBAAA,QACA,aAAA,QlCmrJN,wBAEA,8BADA,8BkCxuJA,2BlCsuJA,iCADA,iCkCtqJM,MAAA,KACA,OAAA,YACA,iBAAA,KACA,aAAA,KASN,oBlCqqJA,uBmC7uJM,QAAA,KAAA,KACA,UAAA,KACA,YAAA,UAEF,gCnC+uJJ,mC2B1uJE,uBAAA,IACA,0BAAA,IQAE,+BnC8uJJ,kC2BvvJE,wBAAA,IACA,2BAAA,IO2EF,oBlCgrJA,uBmC7vJM,QAAA,IAAA,KACA,UAAA,KACA,YAAA,IAEF,gCnC+vJJ,mC2B1vJE,uBAAA,IACA,0BAAA,IQAE,+BnC8vJJ,kC2BvwJE,wBAAA,IACA,2BAAA,ISHF,OACE,aAAA,EACA,OAAA,KAAA,EACA,WAAA,OACA,WAAA,KAJF,UAOI,QAAA,OAPJ,YpCuxJA,eoC7wJM,QAAA,aACA,QAAA,IAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,cAAA,KpCixJN,kBoC/xJA,kBAmBM,gBAAA,KACA,iBAAA,KApBN,epCoyJA,kBoCzwJM,MAAA,MA3BN,mBpCwyJA,sBoCtwJM,MAAA,KAlCN,mBpC6yJA,yBADA,yBAEA,sBoCnwJM,MAAA,KACA,OAAA,YACA,iBAAA,KC9CN,OACE,QAAA,OACA,QAAA,KAAA,KAAA,KACA,UAAA,IACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,WAAA,OACA,YAAA,OACA,eAAA,SACA,cAAA,MrCuzJF,cqCnzJI,cAEE,MAAA,KACA,gBAAA,KACA,OAAA,QAKJ,aACE,QAAA,KAIF,YACE,SAAA,SACA,IAAA,KAOJ,eCtCE,iBAAA,KtCk1JF,2BsC/0JI,2BAEE,iBAAA,QDqCN,eC1CE,iBAAA,QtCy1JF,2BsCt1JI,2BAEE,iBAAA,QDyCN,eC9CE,iBAAA,QtCg2JF,2BsC71JI,2BAEE,iBAAA,QD6CN,YClDE,iBAAA,QtCu2JF,wBsCp2JI,wBAEE,iBAAA,QDiDN,eCtDE,iBAAA,QtC82JF,2BsC32JI,2BAEE,iBAAA,QDqDN,cC1DE,iBAAA,QtCq3JF,0BsCl3JI,0BAEE,iBAAA,QCFN,OACE,QAAA,aACA,UAAA,KACA,QAAA,IAAA,IACA,UAAA,KACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,WAAA,OACA,YAAA,OACA,eAAA,OACA,iBAAA,KACA,cAAA,KAGA,aACE,QAAA,KAIF,YACE,SAAA,SACA,IAAA,KvCq3JJ,0BuCl3JE,eAEE,IAAA,EACA,QAAA,IAAA,IvCo3JJ,cuC/2JI,cAEE,MAAA,KACA,gBAAA,KACA,OAAA,QAKJ,+BvC42JF,4BuC12JI,MAAA,QACA,iBAAA,KAGF,wBACE,MAAA,MAGF,+BACE,aAAA,IAGF,uBACE,YAAA,IC1DJ,WACE,YAAA,KACA,eAAA,KACA,cAAA,KACA,MAAA,QACA,iBAAA,KxCu6JF,ewC56JA,cASI,MAAA,QATJ,aAaI,cAAA,KACA,UAAA,KACA,YAAA,IAfJ,cAmBI,iBAAA,QAGF,sBxCk6JF,4BwCh6JI,cAAA,KACA,aAAA,KACA,cAAA,IA1BJ,sBA8BI,UAAA,KAGF,oCAAA,WACE,YAAA,KACA,eAAA,KAEA,sBxCi6JF,4BwC/5JI,cAAA,KACA,aAAA,KxCm6JJ,ewC16JA,cAYI,UAAA,MC1CN,WACE,QAAA,MACA,QAAA,IACA,cAAA,KACA,YAAA,WACA,iBAAA,KACA,OAAA,IAAA,MAAA,KACA,cAAA,IrCiLA,mBAAA,OAAA,IAAA,YACK,cAAA,OAAA,IAAA,YACG,WAAA,OAAA,IAAA,YJ+xJV,iByCz9JA,eAaI,aAAA,KACA,YAAA,KzCi9JJ,mBADA,kByC58JE,kBAGE,aAAA,QArBJ,oBA0BI,QAAA,IACA,MAAA,KC3BJ,OACE,QAAA,KACA,cAAA,KACA,OAAA,IAAA,MAAA,YACA,cAAA,IAJF,UAQI,WAAA,EACA,MAAA,QATJ,mBAcI,YAAA,IAdJ,S1Co/JA,U0Ch+JI,cAAA,EApBJ,WAwBI,WAAA,IASJ,mB1C09JA,mB0Cx9JE,cAAA,KAFF,0B1C89JA,0B0Cx9JI,SAAA,SACA,IAAA,KACA,MAAA,MACA,MAAA,QAQJ,eCvDE,MAAA,QACA,iBAAA,QACA,aAAA,QDqDF,kBClDI,iBAAA,QDkDJ,2BC9CI,MAAA,QDkDJ,YC3DE,MAAA,QACA,iBAAA,QACA,aAAA,QDyDF,eCtDI,iBAAA,QDsDJ,wBClDI,MAAA,QDsDJ,eC/DE,MAAA,QACA,iBAAA,QACA,aAAA,QD6DF,kBC1DI,iBAAA,QD0DJ,2BCtDI,MAAA,QD0DJ,cCnEE,MAAA,QACA,iBAAA,QACA,aAAA,QDiEF,iBC9DI,iBAAA,QD8DJ,0BC1DI,MAAA,QCDJ,wCACE,KAAQ,oBAAA,KAAA,EACR,GAAQ,oBAAA,EAAA,GAIV,mCACE,KAAQ,oBAAA,KAAA,EACR,GAAQ,oBAAA,EAAA,GAFV,gCACE,KAAQ,oBAAA,KAAA,EACR,GAAQ,oBAAA,EAAA,GAQV,UACE,OAAA,KACA,cAAA,KACA,SAAA,OACA,iBAAA,QACA,cAAA,IxCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,eACQ,WAAA,MAAA,EAAA,IAAA,IAAA,ewClCV,cACE,MAAA,KACA,MAAA,GACA,OAAA,KACA,UAAA,KACA,YAAA,KACA,MAAA,KACA,WAAA,OACA,iBAAA,QxCyBA,mBAAA,MAAA,EAAA,KAAA,EAAA,gBACQ,WAAA,MAAA,EAAA,KAAA,EAAA,gBAyHR,mBAAA,MAAA,IAAA,KACK,cAAA,MAAA,IAAA,KACG,WAAA,MAAA,IAAA,KJw6JV,sB4CnjKA,gCCDI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKDEF,wBAAA,KAAA,KAAA,gBAAA,KAAA,K5CwjKF,qB4CjjKA,+BxC5CE,kBAAA,qBAAA,GAAA,OAAA,SACK,aAAA,qBAAA,GAAA,OAAA,SACG,UAAA,qBAAA,GAAA,OAAA,SwCmDV,sBEvEE,iBAAA,QAGA,wCDgDE,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKDsBJ,mBE3EE,iBAAA,QAGA,qCDgDE,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKD0BJ,sBE/EE,iBAAA,QAGA,wCDgDE,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKD8BJ,qBEnFE,iBAAA,QAGA,uCDgDE,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKExDJ,OAEE,WAAA,KAEA,mBACE,WAAA,EAIJ,O/CqpKA,Y+CnpKE,SAAA,OACA,KAAA,EAGF,YACE,MAAA,QAGF,cACE,QAAA,MAGA,4BACE,UAAA,KAIJ,a/CgpKA,mB+C9oKE,aAAA,KAGF,Y/C+oKA,kB+C7oKE,cAAA,K/CkpKF,Y+C/oKA,Y/C8oKA,a+C3oKE,QAAA,WACA,eAAA,IAGF,cACE,eAAA,OAGF,cACE,eAAA,OAIF,eACE,WAAA,EACA,cAAA,IAMF,YACE,aAAA,EACA,WAAA,KCrDF,YAEE,aAAA,EACA,cAAA,KAQF,iBACE,SAAA,SACA,QAAA,MACA,QAAA,KAAA,KAEA,cAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,KAGA,6BrB7BA,uBAAA,IACA,wBAAA,IqB+BA,4BACE,cAAA,ErBzBF,2BAAA,IACA,0BAAA,IqB6BA,0BhDqrKF,gCADA,gCgDjrKI,MAAA,KACA,OAAA,YACA,iBAAA,KALF,mDhD4rKF,yDADA,yDgDlrKM,MAAA,QATJ,gDhDisKF,sDADA,sDgDprKM,MAAA,KAKJ,wBhDqrKF,8BADA,8BgDjrKI,QAAA,EACA,MAAA,KACA,iBAAA,QACA,aAAA,QANF,iDhDisKF,wDAHA,uDADA,uDAMA,8DAHA,6DAJA,uDAMA,8DAHA,6DgDnrKM,MAAA,QAZJ,8ChDwsKF,oDADA,oDgDxrKM,MAAA,QAWN,kBhDkrKA,uBgDhrKE,MAAA,KAFF,2ChDsrKA,gDgDjrKI,MAAA,KhDsrKJ,wBgDlrKE,wBhDmrKF,6BAFA,6BgD/qKI,MAAA,KACA,gBAAA,KACA,iBAAA,QAIJ,uBACE,MAAA,KACA,WAAA,KnCvGD,yBoCIG,MAAA,QACA,iBAAA,QAEA,0BjDuxKJ,+BiDrxKM,MAAA,QAFF,mDjD2xKJ,wDiDtxKQ,MAAA,QjD2xKR,gCiDxxKM,gCjDyxKN,qCAFA,qCiDrxKQ,MAAA,QACA,iBAAA,QAEF,iCjD4xKN,uCAFA,uCADA,sCAIA,4CAFA,4CiDxxKQ,MAAA,KACA,iBAAA,QACA,aAAA,QpCzBP,sBoCIG,MAAA,QACA,iBAAA,QAEA,uBjDozKJ,4BiDlzKM,MAAA,QAFF,gDjDwzKJ,qDiDnzKQ,MAAA,QjDwzKR,6BiDrzKM,6BjDszKN,kCAFA,kCiDlzKQ,MAAA,QACA,iBAAA,QAEF,8BjDyzKN,oCAFA,oCADA,mCAIA,yCAFA,yCiDrzKQ,MAAA,KACA,iBAAA,QACA,aAAA,QpCzBP,yBoCIG,MAAA,QACA,iBAAA,QAEA,0BjDi1KJ,+BiD/0KM,MAAA,QAFF,mDjDq1KJ,wDiDh1KQ,MAAA,QjDq1KR,gCiDl1KM,gCjDm1KN,qCAFA,qCiD/0KQ,MAAA,QACA,iBAAA,QAEF,iCjDs1KN,uCAFA,uCADA,sCAIA,4CAFA,4CiDl1KQ,MAAA,KACA,iBAAA,QACA,aAAA,QpCzBP,wBoCIG,MAAA,QACA,iBAAA,QAEA,yBjD82KJ,8BiD52KM,MAAA,QAFF,kDjDk3KJ,uDiD72KQ,MAAA,QjDk3KR,+BiD/2KM,+BjDg3KN,oCAFA,oCiD52KQ,MAAA,QACA,iBAAA,QAEF,gCjDm3KN,sCAFA,sCADA,qCAIA,2CAFA,2CiD/2KQ,MAAA,KACA,iBAAA,QACA,aAAA,QDiGR,yBACE,WAAA,EACA,cAAA,IAEF,sBACE,cAAA,EACA,YAAA,IExHF,OACE,cAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,YACA,cAAA,I9C0DA,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gB8CtDV,YACE,QAAA,KAKF,eACE,QAAA,KAAA,KACA,cAAA,IAAA,MAAA,YvBtBA,uBAAA,IACA,wBAAA,IuBmBF,0CAMI,MAAA,QAKJ,aACE,WAAA,EACA,cAAA,EACA,UAAA,KACA,MAAA,QlD24KF,oBAEA,sBkDj5KA,elD84KA,mBAEA,qBkDr4KI,MAAA,QAKJ,cACE,QAAA,KAAA,KACA,iBAAA,QACA,WAAA,IAAA,MAAA,KvB1CA,2BAAA,IACA,0BAAA,IuBmDF,mBlD+3KA,mCkD53KI,cAAA,EAHJ,oClDm4KA,oDkD73KM,aAAA,IAAA,EACA,cAAA,EAIF,4DlD63KJ,4EkD33KQ,WAAA,EvBzEN,uBAAA,IACA,wBAAA,IuB8EE,0DlD23KJ,0EkDz3KQ,cAAA,EvBzEN,2BAAA,IACA,0BAAA,IuBmDF,+EvB5DE,uBAAA,EACA,wBAAA,EuB4FF,wDAEI,iBAAA,EAGJ,0BACE,iBAAA,ElDw3KF,8BkDh3KA,clD+2KA,gCkD32KI,cAAA,ElDi3KJ,sCkDr3KA,sBlDo3KA,wCkD72KM,cAAA,KACA,aAAA,KlDk3KN,wDkD13KA,0BvB3GE,uBAAA,IACA,wBAAA,I3B2+KF,yFAFA,yFACA,2DkDh4KA,2DAmBQ,uBAAA,IACA,wBAAA,IlDo3KR,wGAIA,wGANA,wGAIA,wGAHA,0EAIA,0EkD34KA,0ElDy4KA,0EkDj3KU,uBAAA,IlD03KV,uGAIA,uGANA,uGAIA,uGAHA,yEAIA,yEkDr5KA,yElDm5KA,yEkDv3KU,wBAAA,IlD83KV,sDkD15KA,yBvBnGE,2BAAA,IACA,0BAAA,I3BigLF,qFAEA,qFkDj6KA,wDlDg6KA,wDkDv3KQ,2BAAA,IACA,0BAAA,IlD43KR,oGAIA,oGAFA,oGAIA,oGkD56KA,uElDy6KA,uEAFA,uEAIA,uEkD73KU,0BAAA,IlDk4KV,mGAIA,mGAFA,mGAIA,mGkDt7KA,sElDm7KA,sEAFA,sEAIA,sEkDn4KU,2BAAA,IAlDV,0BlD07KA,qCACA,0BACA,qCkDj4KI,WAAA,IAAA,MAAA,KlDq4KJ,kDkDh8KA,kDA+DI,WAAA,EA/DJ,uBlDo8KA,yCkDj4KI,OAAA,ElD44KJ,+CANA,+CAQA,+CANA,+CAEA,+CkD78KA,+ClDg9KA,iEANA,iEAQA,iEANA,iEAEA,iEANA,iEkD93KU,YAAA,ElDm5KV,8CANA,8CAQA,8CANA,8CAEA,8CkD39KA,8ClD89KA,gEANA,gEAQA,gEANA,gEAEA,gEANA,gEkDx4KU,aAAA,ElDu5KV,+CAIA,+CkDz+KA,+ClDu+KA,+CADA,iEAIA,iEANA,iEAIA,iEkDj5KU,cAAA,EAvFV,8ClDi/KA,8CAFA,8CAIA,8CALA,gEAIA,gEAFA,gEAIA,gEkDp5KU,cAAA,EAhGV,yBAsGI,cAAA,EACA,OAAA,EAUJ,aACE,cAAA,KADF,oBAKI,cAAA,EACA,cAAA,IANJ,2BASM,WAAA,IATN,4BAcI,cAAA,ElD04KJ,wDkDx5KA,wDAkBM,WAAA,IAAA,MAAA,KAlBN,2BAuBI,WAAA,EAvBJ,uDAyBM,cAAA,IAAA,MAAA,KAON,eC5PE,aAAA,KAEA,8BACE,MAAA,KACA,iBAAA,QACA,aAAA,KAHF,0DAMI,iBAAA,KANJ,qCASI,MAAA,QACA,iBAAA,KAGJ,yDAEI,oBAAA,KD8ON,eC/PE,aAAA,QAEA,8BACE,MAAA,KACA,iBAAA,QACA,aAAA,QAHF,0DAMI,iBAAA,QANJ,qCASI,MAAA,QACA,iBAAA,KAGJ,yDAEI,oBAAA,QDiPN,eClQE,aAAA,QAEA,8BACE,MAAA,QACA,iBAAA,QACA,aAAA,QAHF,0DAMI,iBAAA,QANJ,qCASI,MAAA,QACA,iBAAA,QAGJ,yDAEI,oBAAA,QDoPN,YCrQE,aAAA,QAEA,2BACE,MAAA,QACA,iBAAA,QACA,aAAA,QAHF,uDAMI,iBAAA,QANJ,kCASI,MAAA,QACA,iBAAA,QAGJ,sDAEI,oBAAA,QDuPN,eCxQE,aAAA,QAEA,8BACE,MAAA,QACA,iBAAA,QACA,aAAA,QAHF,0DAMI,iBAAA,QANJ,qCASI,MAAA,QACA,iBAAA,QAGJ,yDAEI,oBAAA,QD0PN,cC3QE,aAAA,QAEA,6BACE,MAAA,QACA,iBAAA,QACA,aAAA,QAHF,yDAMI,iBAAA,QANJ,oCASI,MAAA,QACA,iBAAA,QAGJ,wDAEI,oBAAA,QChBN,kBACE,SAAA,SACA,QAAA,MACA,OAAA,EACA,QAAA,EACA,SAAA,OALF,yCpDivLA,wBADA,yBAEA,yBACA,wBoDvuLI,SAAA,SACA,IAAA,EACA,OAAA,EACA,KAAA,EACA,MAAA,KACA,OAAA,KACA,OAAA,EAKJ,wBACE,eAAA,OAIF,uBACE,eAAA,IC3BF,MACE,WAAA,KACA,QAAA,KACA,cAAA,KACA,iBAAA,QACA,OAAA,IAAA,MAAA,QACA,cAAA,IjD0DA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBiDjEV,iBASI,aAAA,KACA,aAAA,gBAKJ,SACE,QAAA,KACA,cAAA,IAEF,SACE,QAAA,IACA,cAAA,ICpBF,OACE,MAAA,MACA,UAAA,KACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,YAAA,EAAA,IAAA,EAAA,KjCTA,OAAA,kBACA,QAAA,GrBkyLF,asDvxLE,aAEE,MAAA,KACA,gBAAA,KACA,OAAA,QjChBF,OAAA,kBACA,QAAA,GiCuBA,aACE,QAAA,EACA,OAAA,QACA,WAAA,IACA,OAAA,EACA,mBAAA,KACA,gBAAA,KAAA,WAAA,KCxBJ,YACE,SAAA,OAIF,OACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,SAAA,OACA,2BAAA,MAIA,QAAA,EAGA,0BnDiHA,kBAAA,kBACI,cAAA,kBACC,aAAA,kBACG,UAAA,kBAkER,mBAAA,kBAAA,IAAA,SAEK,cAAA,aAAA,IAAA,SACG,WAAA,kBAAA,IAAA,SAAA,WAAA,UAAA,IAAA,SAAA,WAAA,UAAA,IAAA,QAAA,CAAA,kBAAA,IAAA,QAAA,CAAA,aAAA,IAAA,SmDrLR,wBnD6GA,kBAAA,eACI,cAAA,eACC,aAAA,eACG,UAAA,emD9GV,mBACE,WAAA,OACA,WAAA,KAIF,cACE,SAAA,SACA,MAAA,KACA,OAAA,KAIF,eACE,SAAA,SACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,KACA,OAAA,IAAA,MAAA,eACA,cAAA,InDcA,mBAAA,EAAA,IAAA,IAAA,eACQ,WAAA,EAAA,IAAA,IAAA,emDZR,QAAA,EAIF,gBACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KACA,iBAAA,KAEA,qBlCpEA,OAAA,iBACA,QAAA,EkCoEA,mBlCrEA,OAAA,kBACA,QAAA,GkCyEF,cACE,QAAA,KACA,cAAA,IAAA,MAAA,QAIF,qBACE,WAAA,KAIF,aACE,OAAA,EACA,YAAA,WAKF,YACE,SAAA,SACA,QAAA,KAIF,cACE,QAAA,KACA,WAAA,MACA,WAAA,IAAA,MAAA,QAHF,wBAQI,cAAA,EACA,YAAA,IATJ,mCAaI,YAAA,KAbJ,oCAiBI,YAAA,EAKJ,yBACE,SAAA,SACA,IAAA,QACA,MAAA,KACA,OAAA,KACA,SAAA,OAIF,yBAEE,cACE,MAAA,MACA,OAAA,KAAA,KAEF,enDrEA,mBAAA,EAAA,IAAA,KAAA,eACQ,WAAA,EAAA,IAAA,KAAA,emDyER,UAAY,MAAA,OAGd,yBACE,UAAY,MAAA,OC9Id,SACE,SAAA,SACA,QAAA,KACA,QAAA,MCRA,YAAA,gBAAA,CAAA,SAAA,CAAA,KAAA,CAAA,WAEA,WAAA,OACA,YAAA,IACA,YAAA,WACA,WAAA,KACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,aAAA,OACA,UAAA,OACA,YAAA,ODHA,UAAA,KnCTA,OAAA,iBACA,QAAA,EmCYA,YnCbA,OAAA,kBACA,QAAA,GmCaA,aACE,QAAA,IAAA,EACA,WAAA,KAEF,eACE,QAAA,EAAA,IACA,YAAA,IAEF,gBACE,QAAA,IAAA,EACA,WAAA,IAEF,cACE,QAAA,EAAA,IACA,YAAA,KAIF,4BACE,OAAA,EACA,KAAA,IACA,YAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEF,iCACE,MAAA,IACA,OAAA,EACA,cAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEF,kCACE,OAAA,EACA,KAAA,IACA,cAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEF,8BACE,IAAA,IACA,KAAA,EACA,WAAA,KACA,aAAA,IAAA,IAAA,IAAA,EACA,mBAAA,KAEF,6BACE,IAAA,IACA,MAAA,EACA,WAAA,KACA,aAAA,IAAA,EAAA,IAAA,IACA,kBAAA,KAEF,+BACE,IAAA,EACA,KAAA,IACA,YAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAEF,oCACE,IAAA,EACA,MAAA,IACA,WAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAEF,qCACE,IAAA,EACA,KAAA,IACA,WAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAKJ,eACE,UAAA,MACA,QAAA,IAAA,IACA,MAAA,KACA,WAAA,OACA,iBAAA,KACA,cAAA,IAIF,eACE,SAAA,SACA,MAAA,EACA,OAAA,EACA,aAAA,YACA,aAAA,MEzGF,SACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,UAAA,MACA,QAAA,IDXA,YAAA,gBAAA,CAAA,SAAA,CAAA,KAAA,CAAA,WAEA,WAAA,OACA,YAAA,IACA,YAAA,WACA,WAAA,KACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,aAAA,OACA,UAAA,OACA,YAAA,OCAA,UAAA,KACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,KACA,OAAA,IAAA,MAAA,eACA,cAAA,ItDiDA,mBAAA,EAAA,IAAA,KAAA,eACQ,WAAA,EAAA,IAAA,KAAA,esD9CR,aAAQ,WAAA,MACR,eAAU,YAAA,KACV,gBAAW,WAAA,KACX,cAAS,YAAA,MAvBX,gBA4BI,aAAA,KAEA,gB1DkjMJ,sB0DhjMM,SAAA,SACA,QAAA,MACA,MAAA,EACA,OAAA,EACA,aAAA,YACA,aAAA,MAGF,sBACE,QAAA,GACA,aAAA,KAIJ,oBACE,OAAA,MACA,KAAA,IACA,YAAA,MACA,iBAAA,KACA,iBAAA,gBACA,oBAAA,EACA,0BACE,OAAA,IACA,YAAA,MACA,QAAA,IACA,iBAAA,KACA,oBAAA,EAGJ,sBACE,IAAA,IACA,KAAA,MACA,WAAA,MACA,mBAAA,KACA,mBAAA,gBACA,kBAAA,EACA,4BACE,OAAA,MACA,KAAA,IACA,QAAA,IACA,mBAAA,KACA,kBAAA,EAGJ,uBACE,IAAA,MACA,KAAA,IACA,YAAA,MACA,iBAAA,EACA,oBAAA,KACA,oBAAA,gBACA,6BACE,IAAA,IACA,YAAA,MACA,QAAA,IACA,iBAAA,EACA,oBAAA,KAIJ,qBACE,IAAA,IACA,MAAA,MACA,WAAA,MACA,mBAAA,EACA,kBAAA,KACA,kBAAA,gBACA,2BACE,MAAA,IACA,OAAA,MACA,QAAA,IACA,mBAAA,EACA,kBAAA,KAKN,eACE,QAAA,IAAA,KACA,OAAA,EACA,UAAA,KACA,iBAAA,QACA,cAAA,IAAA,MAAA,QACA,cAAA,IAAA,IAAA,EAAA,EAGF,iBACE,QAAA,IAAA,KCpHF,UACE,SAAA,SAGF,gBACE,SAAA,SACA,MAAA,KACA,SAAA,OAHF,sBAMI,SAAA,SACA,QAAA,KvD6KF,mBAAA,IAAA,YAAA,KACK,cAAA,IAAA,YAAA,KACG,WAAA,IAAA,YAAA,KJs/LV,4B2D5qMA,0BAcM,YAAA,EAIF,8BAAA,uBAAA,sBvDuLF,mBAAA,kBAAA,IAAA,YAEK,cAAA,aAAA,IAAA,YACG,WAAA,kBAAA,IAAA,YAAA,WAAA,UAAA,IAAA,YAAA,WAAA,UAAA,IAAA,WAAA,CAAA,kBAAA,IAAA,WAAA,CAAA,aAAA,IAAA,YA7JR,4BAAA,OAEQ,oBAAA,OA+GR,oBAAA,OAEQ,YAAA,OJ0hMR,mC2DrqMI,2BvDmHJ,kBAAA,sBACQ,UAAA,sBuDjHF,KAAA,E3DwqMN,kC2DtqMI,2BvD8GJ,kBAAA,uBACQ,UAAA,uBuD5GF,KAAA,E3D0qMN,6B2DxqMI,gC3DuqMJ,iCI9jMA,kBAAA,mBACQ,UAAA,mBuDtGF,KAAA,GArCR,wB3DgtMA,sBACA,sB2DpqMI,QAAA,MA7CJ,wBAiDI,KAAA,EAjDJ,sB3DwtMA,sB2DlqMI,SAAA,SACA,IAAA,EACA,MAAA,KAxDJ,sBA4DI,KAAA,KA5DJ,sBA+DI,KAAA,MA/DJ,2B3DouMA,4B2DjqMI,KAAA,EAnEJ,6BAuEI,KAAA,MAvEJ,8BA0EI,KAAA,KAQJ,kBACE,SAAA,SACA,IAAA,EACA,OAAA,EACA,KAAA,EACA,MAAA,IACA,UAAA,KACA,MAAA,KACA,WAAA,OACA,YAAA,EAAA,IAAA,IAAA,eACA,iBAAA,ctCpGA,OAAA,kBACA,QAAA,GsCyGA,uBdrGE,iBAAA,sEACA,iBAAA,iEACA,iBAAA,uFAAA,iBAAA,kEACA,OAAA,+GACA,kBAAA,ScoGF,wBACE,MAAA,EACA,KAAA,Kd1GA,iBAAA,sEACA,iBAAA,iEACA,iBAAA,uFAAA,iBAAA,kEACA,OAAA,+GACA,kBAAA,S7C6wMJ,wB2DlqME,wBAEE,MAAA,KACA,gBAAA,KACA,QAAA,EtCxHF,OAAA,kBACA,QAAA,GrB8xMF,0CACA,2CAFA,6B2DpsMA,6BAuCI,SAAA,SACA,IAAA,IACA,QAAA,EACA,QAAA,aACA,WAAA,M3DmqMJ,0C2D9sMA,6BA+CI,KAAA,IACA,YAAA,M3DmqMJ,2C2DntMA,6BAoDI,MAAA,IACA,aAAA,M3DmqMJ,6B2DxtMA,6BAyDI,MAAA,KACA,OAAA,KACA,YAAA,MACA,YAAA,EAIA,oCACE,QAAA,QAIF,oCACE,QAAA,QAUN,qBACE,SAAA,SACA,OAAA,KACA,KAAA,IACA,QAAA,GACA,MAAA,IACA,aAAA,EACA,YAAA,KACA,WAAA,OACA,WAAA,KATF,wBAYI,QAAA,aACA,MAAA,KACA,OAAA,KACA,OAAA,IACA,YAAA,OACA,OAAA,QAUA,iBAAA,OACA,iBAAA,cAEA,OAAA,IAAA,MAAA,KACA,cAAA,KA/BJ,6BAmCI,MAAA,KACA,OAAA,KACA,OAAA,EACA,iBAAA,KAOJ,kBACE,SAAA,SACA,MAAA,IACA,OAAA,KACA,KAAA,IACA,QAAA,GACA,YAAA,KACA,eAAA,KACA,MAAA,KACA,WAAA,OACA,YAAA,EAAA,IAAA,IAAA,eAEA,uBACE,YAAA,KAMJ,oCAGE,0C3D+nMA,2CAEA,6BADA,6B2D3nMI,MAAA,KACA,OAAA,KACA,WAAA,MACA,UAAA,KARJ,0C3DwoMA,6B2D5nMI,YAAA,MAZJ,2C3D4oMA,6B2D5nMI,aAAA,MAKJ,kBACE,MAAA,IACA,KAAA,IACA,eAAA,KAIF,qBACE,OAAA,M3D0oMJ,qCADA,sCADA,mBADA,oBAXA,gB4D73ME,iB5Dm4MF,uBADA,wBADA,iBADA,kBADA,wBADA,yBASA,mCADA,oCAqBA,oBADA,qBADA,oBADA,qBAXA,WADA,YAOA,uBADA,wBADA,qBADA,sBADA,cADA,eAOA,aADA,cAGA,kBADA,mBAjBA,WADA,Y4Dl4MI,QAAA,MACA,QAAA,I5Dm6MJ,qCADA,mB4Dh6ME,gB5D65MF,uBADA,iBADA,wBAIA,mCAUA,oBADA,oBANA,WAGA,uBADA,qBADA,cAGA,aACA,kBATA,W4D75MI,MAAA,K5BNJ,c6BVE,QAAA,MACA,aAAA,KACA,YAAA,K7BWF,YACE,MAAA,gBAEF,WACE,MAAA,eAQF,MACE,QAAA,eAEF,MACE,QAAA,gBAEF,WACE,WAAA,OAEF,W8BzBE,KAAA,CAAA,CAAA,EAAA,EACA,MAAA,YACA,YAAA,KACA,iBAAA,YACA,OAAA,E9B8BF,QACE,QAAA,eAOF,OACE,SAAA,M+BjCF,cACE,MAAA,a/D88MF,YADA,YADA,Y+Dt8MA,YClBE,QAAA,ehEs+MF,kBACA,mBACA,yBALA,kBACA,mBACA,yBALA,kBACA,mBACA,yB+Dz8MA,kB/Dq8MA,mBACA,yB+D17ME,QAAA,eAIA,yBAAA,YCjDA,QAAA,gBACA,iBAAU,QAAA,gBACV,cAAU,QAAA,oBhE4/MV,cgE3/MA,cACU,QAAA,sBDkDV,yBAAA,kBACE,QAAA,iBAIF,yBAAA,mBACE,QAAA,kBAIF,yBAAA,yBACE,QAAA,wBAKF,+CAAA,YCtEA,QAAA,gBACA,iBAAU,QAAA,gBACV,cAAU,QAAA,oBhE0hNV,cgEzhNA,cACU,QAAA,sBDuEV,+CAAA,kBACE,QAAA,iBAIF,+CAAA,mBACE,QAAA,kBAIF,+CAAA,yBACE,QAAA,wBAKF,gDAAA,YC3FA,QAAA,gBACA,iBAAU,QAAA,gBACV,cAAU,QAAA,oBhEwjNV,cgEvjNA,cACU,QAAA,sBD4FV,gDAAA,kBACE,QAAA,iBAIF,gDAAA,mBACE,QAAA,kBAIF,gDAAA,yBACE,QAAA,wBAKF,0BAAA,YChHA,QAAA,gBACA,iBAAU,QAAA,gBACV,cAAU,QAAA,oBhEslNV,cgErlNA,cACU,QAAA,sBDiHV,0BAAA,kBACE,QAAA,iBAIF,0BAAA,mBACE,QAAA,kBAIF,0BAAA,yBACE,QAAA,wBAKF,yBAAA,WC7HA,QAAA,gBDkIA,+CAAA,WClIA,QAAA,gBDuIA,gDAAA,WCvIA,QAAA,gBD4IA,0BAAA,WC5IA,QAAA,gBDuJF,eCvJE,QAAA,eD0JA,aAAA,eClKA,QAAA,gBACA,oBAAU,QAAA,gBACV,iBAAU,QAAA,oBhE2oNV,iBgE1oNA,iBACU,QAAA,sBDkKZ,qBACE,QAAA,eAEA,aAAA,qBACE,QAAA,iBAGJ,sBACE,QAAA,eAEA,aAAA,sBACE,QAAA,kBAGJ,4BACE,QAAA,eAEA,aAAA,4BACE,QAAA,wBAKF,aAAA,cCrLA,QAAA","sourcesContent":["/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: none;\n text-decoration: underline;\n text-decoration: underline dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff2\") format(\"woff2\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\") format(\"svg\");\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: 400;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: \"\\2014 \\00A0\";\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: \"\";\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: \"\\00A0 \\2014\";\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n.row-no-gutters [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1,\n .col-sm-2,\n .col-sm-3,\n .col-sm-4,\n .col-sm-5,\n .col-sm-6,\n .col-sm-7,\n .col-sm-8,\n .col-sm-9,\n .col-sm-10,\n .col-sm-11,\n .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1,\n .col-md-2,\n .col-md-3,\n .col-md-4,\n .col-md-5,\n .col-md-6,\n .col-md-7,\n .col-md-8,\n .col-md-9,\n .col-md-10,\n .col-md-11,\n .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1,\n .col-lg-2,\n .col-lg-3,\n .col-lg-4,\n .col-lg-5,\n .col-lg-6,\n .col-lg-7,\n .col-lg-8,\n .col-lg-9,\n .col-lg-10,\n .col-lg-11,\n .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: 0.01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: 700;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n -webkit-appearance: none;\n appearance: none;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n opacity: 0.65;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n background-image: none;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n background-image: none;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n background-image: none;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n background-image: none;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n background-image: none;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n background-image: none;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: 400;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: 400;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: 400;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-right: 15px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-right: -15px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: 0.2em 0.6em 0.3em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #eeeeee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: 0.2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 12px;\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: \"\\2039\";\n}\n.carousel-control .icon-next:before {\n content: \"\\203a\";\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","// stylelint-disable\n\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// 1. Remove the bottom border in Chrome 57- and Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n//\n\nabbr[title] {\n border-bottom: none; // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: none;\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n -moz-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n -webkit-box-shadow: none !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff2\") format(\"woff2\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\") format(\"svg\");\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: 400;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: \"\\2014 \\00A0\";\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: \"\";\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: \"\\00A0 \\2014\";\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n.row-no-gutters [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1,\n .col-sm-2,\n .col-sm-3,\n .col-sm-4,\n .col-sm-5,\n .col-sm-6,\n .col-sm-7,\n .col-sm-8,\n .col-sm-9,\n .col-sm-10,\n .col-sm-11,\n .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1,\n .col-md-2,\n .col-md-3,\n .col-md-4,\n .col-md-5,\n .col-md-6,\n .col-md-7,\n .col-md-8,\n .col-md-9,\n .col-md-10,\n .col-md-11,\n .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1,\n .col-lg-2,\n .col-lg-3,\n .col-lg-4,\n .col-lg-5,\n .col-lg-6,\n .col-lg-7,\n .col-lg-8,\n .col-lg-9,\n .col-lg-10,\n .col-lg-11,\n .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: 0.01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: 700;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n -ms-touch-action: manipulation;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n opacity: 0.65;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n background-image: none;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n background-image: none;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n background-image: none;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n background-image: none;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n background-image: none;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n background-image: none;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: 400;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n -o-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n -o-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n -o-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: 400;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: 400;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n border-top: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-right: 15px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-right: -15px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: 0.2em 0.6em 0.3em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@-o-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n -webkit-background-size: 40px 40px;\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #eeeeee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: 0.2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: -webkit-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 12px;\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: -webkit-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: \"\\2039\";\n}\n.carousel-control .icon-next:before {\n content: \"\\203a\";\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","// stylelint-disable declaration-no-important, selector-no-qualifying-type\n\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important; // Black prints faster: h5bp.com/s\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n}\n","// stylelint-disable value-list-comma-newline-after, value-list-comma-space-after, indentation, declaration-colon-newline-after, font-family-no-missing-generic-family-keyword\n\n//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"@{icon-font-path}@{icon-font-name}.eot\");\n src: url(\"@{icon-font-path}@{icon-font-name}.eot?#iefix\") format(\"embedded-opentype\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff2\") format(\"woff2\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff\") format(\"woff\"),\n url(\"@{icon-font-path}@{icon-font-name}.ttf\") format(\"truetype\"),\n url(\"@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}\") format(\"svg\");\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// https://getbootstrap.com/docs/3.4/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: https://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// stylelint-disable media-feature-name-no-vendor-prefix, media-feature-parentheses-space-inside, media-feature-name-no-unknown, indentation, at-rule-name-space-after\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","// stylelint-disable selector-list-comma-newline-after, selector-no-qualifying-type\n\n//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: 400;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n padding: .2em;\n background-color: @state-warning-bg;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: \"\\2014 \\00A0\"; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: \"\"; }\n &:after {\n content: \"\\00A0 \\2014\"; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n color: @pre-color;\n word-break: break-all;\n word-wrap: break-word;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n padding-right: ceil((@gutter / 2));\n padding-left: floor((@gutter / 2));\n margin-right: auto;\n margin-left: auto;\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-right: floor((@gutter / -2));\n margin-left: ceil((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-right: floor((@grid-gutter-width / 2));\n padding-left: ceil((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-no-qualifying-type\n\n//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n\n // Table cell sizing\n //\n // Reset default table behavior\n\n col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-column;\n float: none;\n }\n\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-cell;\n float: none;\n }\n }\n}\n\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\n\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n min-height: .01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n overflow-x: auto;\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * .75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","// stylelint-disable selector-no-qualifying-type, property-no-vendor-prefix, media-feature-name-no-vendor-prefix\n\n//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: 700;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\ninput[type=\"search\"] {\n // Override content-box in Normalize (* isn't specific enough)\n .box-sizing(border-box);\n\n // Search inputs in iOS\n //\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n -webkit-appearance: none;\n appearance: none;\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n\n // Apply same disabled cursor tweak as for inputs\n // Some special care is needed because <label>s don't inherit their parent's `cursor`.\n //\n // Note: Neither radios nor checkboxes can be readonly.\n &[disabled],\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on `<select>`s in IE10+.\n &::-ms-expand {\n background-color: transparent;\n border: 0;\n }\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n//\n// Note that as of 9.3, iOS doesn't support `week`.\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n &.form-control {\n line-height: @input-height-base;\n }\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n // These are used on elements with <label> descendants\n &.disabled,\n fieldset[disabled] & {\n label {\n cursor: @cursor-disabled;\n }\n }\n\n label {\n min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n vertical-align: middle;\n cursor: pointer;\n\n // These are used directly on <label>s\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n min-height: (@line-height-computed + @font-size-base);\n // Size it appropriately next to real form controls\n padding-top: (@padding-base-vertical + 1);\n padding-bottom: (@padding-base-vertical + 1);\n // Remove default margin from `p`\n margin-bottom: 0;\n\n &.input-lg,\n &.input-sm {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n//\n// The `.form-group-* form-control` variations are sadly duplicated to avoid the\n// issue documented in https://github.com/twbs/bootstrap/issues/15074.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);\n}\n.form-group-sm {\n .form-control {\n height: @input-height-small;\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n border-radius: @input-border-radius-small;\n }\n select.form-control {\n height: @input-height-small;\n line-height: @input-height-small;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-small;\n min-height: (@line-height-computed + @font-size-small);\n padding: (@padding-small-vertical + 1) @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n }\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);\n}\n.form-group-lg {\n .form-control {\n height: @input-height-large;\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n border-radius: @input-border-radius-large;\n }\n select.form-control {\n height: @input-height-large;\n line-height: @input-height-large;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-large;\n min-height: (@line-height-computed + @font-size-large);\n padding: (@padding-large-vertical + 1) @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n }\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2; // Ensure icon is above input groups\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: @input-height-large;\n height: @input-height-large;\n line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: @input-height-small;\n height: @input-height-small;\n line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n// Reposition feedback icon if input has visible label above\n.has-feedback label {\n\n & ~ .form-control-feedback {\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n }\n &.sr-only ~ .form-control-feedback {\n top: 0;\n }\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n // Make static controls behave like regular ones\n .form-control-static {\n display: inline-block;\n }\n\n .input-group {\n display: inline-table;\n vertical-align: middle;\n\n .input-group-addon,\n .input-group-btn,\n .form-control {\n width: auto;\n }\n }\n\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match.\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n\n label {\n padding-left: 0;\n }\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n\n // Re-override the feedback icon.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of radios and checkboxes\n //\n // Labels also get some reset styles, but that is scoped to a media query below.\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n margin-top: 0;\n margin-bottom: 0;\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n // Reset spacing and right align labels, but scope to media queries so that\n // labels on narrow viewports stack the same as a default form example.\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n margin-bottom: 0;\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n right: floor((@grid-gutter-width / 2));\n }\n\n // Form group sizes\n //\n // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n // inputs and labels within a `.form-group`.\n .form-group-lg {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-large-vertical + 1);\n font-size: @font-size-large;\n }\n }\n }\n .form-group-sm {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-small-vertical + 1);\n font-size: @font-size-small;\n }\n }\n }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline,\n &.radio label,\n &.checkbox label,\n &.radio-inline label,\n &.checkbox-inline label {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n background-color: @background-color;\n border-color: @border-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n background-image: none;\n outline: 0;\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `<a>` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n font-weight: 400;\n color: @link-color;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n background-image: none;\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n @opacity-ie: (@opacity * 100); // IE8 filter\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n opacity: @opacity;\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n list-style: none;\n background-color: @dropdown-bg;\n background-clip: padding-box;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0, 0, 0, .175));\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: 400;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n\n &:hover,\n &:focus {\n color: @dropdown-link-hover-color;\n text-decoration: none;\n background-color: @dropdown-link-hover-bg;\n }\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n background-color: @dropdown-link-active-bg;\n outline: 0;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n cursor: @cursor-disabled;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n right: 0;\n left: auto; // Reset the default from `.dropdown-menu`\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n content: \"\";\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","// stylelint-disable selector-no-qualifying-type */\n\n//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-left-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-top-right-radius: @radius;\n border-bottom-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-top-left-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: 400;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","// stylelint-disable selector-no-qualifying-type, selector-max-type\n\n//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n padding-left: 0; // Override default ul/ol\n margin-bottom: 0;\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n cursor: @cursor-disabled;\n background-color: transparent;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n cursor: default;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n margin-bottom: 5px;\n text-align: center;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-max-combinators, selector-max-class, declaration-no-important, selector-no-qualifying-type\n\n//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n overflow-x: visible;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n\n // Fix the top/bottom navbars when screen real estate supports it\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n height: @navbar-height;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-right: @navbar-padding-horizontal;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n padding: 10px @navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-right: @navbar-padding-horizontal;\n margin-left: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n\n // Dropdown menu items\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n\n // Dropdowns\n > .open > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n padding: 0 5px;\n color: @breadcrumb-color;\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n margin-left: -1px;\n line-height: @line-height-base;\n color: @pagination-color;\n text-decoration: none;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n cursor: default;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n cursor: @cursor-disabled;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n text-align: center;\n list-style: none;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n cursor: @cursor-disabled;\n background-color: @pager-bg;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n line-height: @badge-line-height;\n color: @badge-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n padding-right: (@grid-gutter-width / 2);\n padding-left: (@grid-gutter-width / 2);\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-right: (@jumbotron-padding * 2);\n padding-left: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-right: auto;\n margin-left: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n color: inherit; // Specified for the h4 to prevent conflicts of changing @headings-color\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n// The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissable,\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n color: @text-color;\n background-color: @background;\n border-color: @border;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","// stylelint-disable at-rule-no-vendor-prefix\n\n//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n overflow: hidden;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0, 0, 0, .1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0, 0, 0, .15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// stylelint-disable value-no-vendor-prefix, selector-max-id\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n padding-left: 0; // reset padding because ul and ol\n margin-bottom: 20px;\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n color: @list-group-disabled-color;\n cursor: @cursor-disabled;\n background-color: @list-group-disabled-bg;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Interactive list items\n//\n// Use anchor or button elements instead of `li`s or `div`s to create interactive items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item,\nbutton.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n color: @list-group-link-hover-color;\n text-decoration: none;\n background-color: @list-group-hover-bg;\n }\n}\n\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a&,\n button& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-max-combinators, no-duplicate-selectors\n\n//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0, 0, 0, .05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a,\n > small,\n > .small,\n > small > a,\n > .small > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group,\n > .panel-collapse > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n > .panel-heading + .panel-collapse > .list-group {\n .list-group-item:first-child {\n .border-top-radius(0);\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n\n caption {\n padding-right: @panel-body-padding;\n padding-left: @panel-body-padding;\n }\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n border-top-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n border-bottom-left-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive,\n > .table + .panel-body,\n > .table-responsive + .panel-body {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n margin-bottom: 0;\n border: 0;\n }\n}\n\n\n// Collapsible panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n\n + .panel-collapse > .panel-body,\n + .panel-collapse > .list-group {\n border-top: 1px solid @panel-inner-border;\n }\n }\n\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n }\n}\n\n// Modifier class for 16:9 aspect ratio\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n\n// Modifier class for 4:3 aspect ratio\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, .15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","// stylelint-disable property-no-vendor-prefix\n\n//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n background-clip: padding-box;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0, 0, 0, .5));\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n &:extend(.clearfix all);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n margin-left: 5px;\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0, 0, 0, .5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-small;\n\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top {\n padding: @tooltip-arrow-width 0;\n margin-top: -3px;\n }\n &.right {\n padding: 0 @tooltip-arrow-width;\n margin-left: 3px;\n }\n &.bottom {\n padding: @tooltip-arrow-width 0;\n margin-top: 3px;\n }\n &.left {\n padding: 0 @tooltip-arrow-width;\n margin-left: -3px;\n }\n\n // Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n right: @tooltip-arrow-width;\n bottom: 0;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n",".reset-text() {\n font-family: @font-family-base;\n // We deliberately do NOT reset font-size.\n font-style: normal;\n font-weight: 400;\n line-height: @line-height-base;\n line-break: auto;\n text-align: left; // Fallback for where `start` is not supported\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-base;\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0, 0, 0, .2));\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n\n // Arrows\n // .arrow is outer, .arrow:after is inner\n > .arrow {\n border-width: @popover-arrow-outer-width;\n\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n\n &:after {\n content: \"\";\n border-width: @popover-arrow-width;\n }\n }\n\n &.top > .arrow {\n bottom: -@popover-arrow-outer-width;\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n border-bottom-width: 0;\n &:after {\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n content: \" \";\n border-top-color: @popover-arrow-color;\n border-bottom-width: 0;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n border-left-width: 0;\n &:after {\n bottom: -@popover-arrow-width;\n left: 1px;\n content: \" \";\n border-right-color: @popover-arrow-color;\n border-left-width: 0;\n }\n }\n &.bottom > .arrow {\n top: -@popover-arrow-outer-width;\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n &:after {\n top: 1px;\n margin-left: -@popover-arrow-width;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n right: 1px;\n bottom: -@popover-arrow-width;\n content: \" \";\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n }\n }\n}\n\n.popover-title {\n padding: 8px 14px;\n margin: 0; // reset heading margin\n font-size: @font-size-base;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n","// stylelint-disable media-feature-name-no-unknown\n\n//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n\n > .item {\n position: relative;\n display: none;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n\n // WebKit CSS3 transforms for supported devices\n @media all and (transform-3d), (-webkit-transform-3d) {\n .transition-transform(~\"0.6s ease-in-out\");\n .backface-visibility(~\"hidden\");\n .perspective(1000px);\n\n &.next,\n &.active.right {\n .translate3d(100%, 0, 0);\n left: 0;\n }\n &.prev,\n &.active.left {\n .translate3d(-100%, 0, 0);\n left: 0;\n }\n &.next.left,\n &.prev.right,\n &.active {\n .translate3d(0, 0, 0);\n left: 0;\n }\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: @carousel-control-width;\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug\n .opacity(@carousel-control-opacity);\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0, 0, 0, .5); @end-color: rgba(0, 0, 0, .0001));\n }\n &.right {\n right: 0;\n left: auto;\n #gradient > .horizontal(@start-color: rgba(0, 0, 0, .0001); @end-color: rgba(0, 0, 0, .5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n color: @carousel-control-color;\n text-decoration: none;\n outline: 0;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n }\n\n .icon-prev {\n &:before {\n content: \"\\2039\";// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: \"\\203a\";// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0, 0, 0, 0); // IE9\n\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n }\n\n .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: (@carousel-control-font-size * 1.5);\n height: (@carousel-control-font-size * 1.5);\n margin-top: (@carousel-control-font-size / -2);\n font-size: (@carousel-control-font-size * 1.5);\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: (@carousel-control-font-size / -2);\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: (@carousel-control-font-size / -2);\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n display: table; // 2\n content: \" \"; // 1\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n","// stylelint-disable font-family-name-quotes, font-family-no-missing-generic-family-keyword\n\n// CSS image replacement\n//\n// Heads up! v3 launched with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (has been removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","// stylelint-disable declaration-no-important, at-rule-no-vendor-prefix\n\n//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: https://getbootstrap.com/docs/3.4/getting-started/#support-ie10-width\n// Source: https://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: https://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// stylelint-disable declaration-no-important\n\n.responsive-visibility() {\n display: block !important;\n table& { display: table !important; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]} \ No newline at end of file diff --git a/themes/bootstrap3/js/account_ajax.js b/themes/bootstrap3/js/account_ajax.js new file mode 100644 index 0000000000000000000000000000000000000000..76d069e94c58e19fa929a6653abf03c523da357c --- /dev/null +++ b/themes/bootstrap3/js/account_ajax.js @@ -0,0 +1,242 @@ +/*global userIsLoggedIn, VuFind */ +VuFind.register('account', function Account() { + // Retrieved statuses + var LOADING = -1 * Math.PI; // waiting for request + var MISSING = -2 * Math.PI; // no data available + var INACTIVE = -3 * Math.PI; // status element missing + var _statuses = {}; + + // Account Icons + var ICON_LEVELS = { + "NONE": 0, + "GOOD": 1, + "WARNING": 2, + "DANGER": 3 + }; + var _accountIcons = {}; + _accountIcons[ICON_LEVELS.NONE] = "fa fa-user-circle"; + _accountIcons[ICON_LEVELS.GOOD] = "fa fa-bell text-success"; + _accountIcons[ICON_LEVELS.WARNING] = "fa fa-bell text-warning"; + _accountIcons[ICON_LEVELS.DANGER] = "fa fa-exclamation-triangle text-danger"; + + var _submodules = []; + + var _sessionDataPrefix = "vf-account-status-"; + var _save = function _save(module) { + sessionStorage.setItem( + _sessionDataPrefix + module, + JSON.stringify(_statuses[module]) + ); + }; + + // Clearing save forces AJAX update next page load + var clearCache = function clearCache(name) { + if (typeof name === "undefined") { + for (var sub in _submodules) { + if (_submodules.hasOwnProperty(sub)) { + clearCache(sub); + } + } + } else { + sessionStorage.removeItem(_sessionDataPrefix + name); + } + }; + + var _getStatus = function _getStatus(module) { + return (typeof _statuses[module] === "undefined") ? LOADING : _statuses[module]; + }; + + var _render = function _render() { + var accountStatus = ICON_LEVELS.NONE; + for (var sub in _submodules) { + if (_submodules.hasOwnProperty(sub)) { + var $element = $(_submodules[sub].selector); + if (!$element) { + _statuses[sub] = INACTIVE; + continue; + } + var status = _getStatus(sub); + if (status === MISSING) { + $element.addClass('hidden'); + } else { + $element.removeClass('hidden'); + if (status === LOADING) { + $element.html('<i class="fa fa-spin fa-spinner"></i>'); + } else { + var moduleStatus = _submodules[sub].render($element, _statuses[sub], ICON_LEVELS); + if (moduleStatus > accountStatus) { + accountStatus = moduleStatus; + } + } + } + } + } + $("#account-icon").attr("class", _accountIcons[accountStatus]); + if (accountStatus > ICON_LEVELS.NONE) { + $("#account-icon") + .attr("data-toggle", "tooltip") + .attr("data-placement", "bottom") + .attr("title", VuFind.translate("account_has_alerts")) + .tooltip(); + } else { + $("#account-icon").tooltip("destroy"); + } + }; + var _ajaxLookup = function _ajaxLookup(module) { + $.ajax({ + url: VuFind.path + '/AJAX/JSON?method=' + _submodules[module].ajaxMethod, + dataType: 'json' + }) + .done(function ajaxLookupDone(response) { + _statuses[module] = response.data; + }) + .fail(function ajaxLookupFail() { + _statuses[module] = MISSING; + }) + .always(function ajaxLookupAlways() { + _save(module); + _render(); + }); + }; + + var _load = function _load(module) { + var $element = $(_submodules[module].selector); + if (!$element) { + _statuses[module] = INACTIVE; + } else { + var json = sessionStorage.getItem(_sessionDataPrefix + module); + var session = typeof json === "undefined" ? null : JSON.parse(json); + if ( + session === null || + session === LOADING || + session === MISSING + ) { + _statuses[module] = LOADING; + _ajaxLookup(module); + } else { + _statuses[module] = session; + } + _render(); + } + }; + + var init = function init() { + // Update information when certain actions are performed + $('#cancelHold, #renewals').submit(clearCache); + }; + + var register = function register(name, module) { + if (typeof _submodules[name] === "undefined") { + _submodules[name] = typeof module == 'function' ? module() : module; + } + var $el = $(_submodules[name].selector); + if ($el.length > 0) { + $el.removeClass("hidden"); + _statuses[name] = LOADING; + _load(name); + } else { + _statuses[name] = INACTIVE; + } + }; + + return { + init: init, + clearCache: clearCache, + // if user is logged out, clear cache instead of register + register: userIsLoggedIn ? register : clearCache + }; +}); + +$(document).ready(function registerAccountAjax() { + + VuFind.account.register("fines", { + selector: ".fines-status", + ajaxMethod: "getUserFines", + render: function render($element, status, ICON_LEVELS) { + if (status.value === 0) { + $element.addClass("hidden"); + return ICON_LEVELS.NONE; + } + $element.html('<span class="badge overdue">' + status.display + '</span>'); + return ICON_LEVELS.DANGER; + } + }); + + VuFind.account.register("checkedOut", { + selector: ".checkedout-status", + ajaxMethod: "getUserTransactions", + render: function render($element, status, ICON_LEVELS) { + var html = ''; + var level = ICON_LEVELS.NONE; + if (status.ok > 0) { + html += '<span class="badge ok" data-toggle="tooltip" title="' + VuFind.translate('Checked Out Items') + '">' + status.ok + '</span>'; + } + if (status.warn > 0) { + html += '<span class="badge warn" data-toggle="tooltip" title="' + VuFind.translate('renew_item_due_tooltip') + '">' + status.warn + '</span>'; + level = ICON_LEVELS.WARNING; + } + if (status.overdue > 0) { + html += '<span class="badge overdue" data-toggle="tooltip" title="' + VuFind.translate('renew_item_overdue_tooltip') + '">' + status.overdue + '</span>'; + level = ICON_LEVELS.DANGER; + } + $element.html(html); + $('[data-toggle="tooltip"]', $element).tooltip(); + return level; + } + }); + + VuFind.account.register("holds", { + selector: ".holds-status", + ajaxMethod: "getUserHolds", + render: function render($element, status, ICON_LEVELS) { + var level = ICON_LEVELS.NONE; + if (status.available > 0) { + $element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('hold_available') + '"></i>'); + level = ICON_LEVELS.GOOD; + } else if (status.in_transit > 0) { + $element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>'); + } else { + $element.addClass("holds-status hidden"); + } + $('[data-toggle="tooltip"]', $element).tooltip(); + return level; + } + }); + + VuFind.account.register("illRequests", { + selector: ".illrequests-status", + ajaxMethod: "getUserILLRequests", + render: function render($element, status, ICON_LEVELS) { + var level = ICON_LEVELS.NONE; + if (status.available > 0) { + $element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('ill_request_available') + '"></i>'); + level = ICON_LEVELS.GOOD; + } else if (status.in_transit > 0) { + $element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>'); + } else { + $element.addClass("holds-status hidden"); + } + $('[data-toggle="tooltip"]', $element).tooltip(); + return level; + } + }); + + VuFind.account.register("storageRetrievalRequests", { + selector: ".storageretrievalrequests-status", + ajaxMethod: "getUserStorageRetrievalRequests", + render: function render($element, status, ICON_LEVELS) { + var level = ICON_LEVELS.NONE; + if (status.available > 0) { + $element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('storage_retrieval_request_available') + '"></i>'); + level = ICON_LEVELS.GOOD; + } else if (status.in_transit > 0) { + $element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>'); + } else { + $element.addClass("holds-status hidden"); + } + $('[data-toggle="tooltip"]', $element).tooltip(); + return level; + } + }); + +}); diff --git a/themes/bootstrap3/js/channels.js b/themes/bootstrap3/js/channels.js index c67f839d4b6fbd482b2ac1f47b8219347cdf26a2..ef04974f6dd4c992fb33d0c6f9871e3c80f518f5 100644 --- a/themes/bootstrap3/js/channels.js +++ b/themes/bootstrap3/js/channels.js @@ -127,6 +127,8 @@ VuFind.register('channels', function Channels() { .prependTo($(op).parent(".channel-wrapper")); } + var bindChannelAddMenu; // circular dependency fix for jshint + function selectAddedChannel(e) { $.ajax(e.target.href).done(function addChannelAjaxDone(data) { var list = $(e.target).closest('.dropdown-menu'); @@ -160,7 +162,7 @@ VuFind.register('channels', function Channels() { return false; } - function bindChannelAddMenu(iteration, channel) { + bindChannelAddMenu = function bindChannelAddMenuFunc(iteration, channel) { var scope = $(channel).parent(".channel-wrapper"); $(scope).find('.channel-add-menu .dropdown-menu a').click(selectAddedChannel); $(scope).find('.channel-add-menu .add-btn').click(function addChannels(e) { @@ -169,7 +171,7 @@ VuFind.register('channels', function Channels() { links[i].click(); } }); - } + }; function init () { $('.channel').each(setupChannelSlider); diff --git a/themes/bootstrap3/js/check_save_statuses.js b/themes/bootstrap3/js/check_save_statuses.js index 07ff265e6ed05921596e364075b7337c8011877c..8eb0f8f6a71f682bf4e206021fa1d31d5fce1c9d 100644 --- a/themes/bootstrap3/js/check_save_statuses.js +++ b/themes/bootstrap3/js/check_save_statuses.js @@ -60,8 +60,9 @@ function runSaveAjaxForQueue() { displaySaveStatus(response.data.statuses[id], saveStatusEls[id]); // Remove populated ids from the queue - for (var j = 0; j < saveStatusObjs; j++) { - if (saveStatusObjs[j].id === id) { + for (var j = saveStatusObjs.length - 1; j >= 0; j--) { + var parts = id.split('|'); + if (saveStatusObjs[j].id === parts[1] && saveStatusObjs[j].source === parts[0]) { saveStatusObjs.splice(j, 1); } } diff --git a/themes/bootstrap3/js/common.js b/themes/bootstrap3/js/common.js index 707461a01badbdab7d04ce5b915a95acf5460ed3..e2c29a85b79418717dd159d750b7c07af2bdfa9c 100644 --- a/themes/bootstrap3/js/common.js +++ b/themes/bootstrap3/js/common.js @@ -31,10 +31,11 @@ var VuFind = (function VuFind() { if (_submodules.indexOf(name) === -1) { _submodules.push(name); this[name] = typeof module == 'function' ? module() : module; - } - // If the object has already initialized, we should auto-init on register: - if (_initialized && this[name].init) { - this[name].init(); + + // If the object has already initialized, we should auto-init on register: + if (_initialized && this[name].init) { + this[name].init(); + } } }; var init = function init() { @@ -177,16 +178,6 @@ function getUrlRoot(url) { } return urlroot; } -function facetSessionStorage(e) { - var source = $('#result0 .hiddenSource').val(); - var id = e.target.id; - var key = 'sidefacet-' + source + id; - if (!sessionStorage.getItem(key)) { - sessionStorage.setItem(key, document.getElementById(id).className); - } else { - sessionStorage.removeItem(key); - } -} // Phone number validation function phoneNumberFormHandler(numID, regionCode) { @@ -240,21 +231,11 @@ function bulkFormHandler(event, data) { // Ready functions function setupOffcanvas() { - if ($('.sidebar').length > 0) { - $('[data-toggle="offcanvas"]').click(function offcanvasClick() { + if ($('.sidebar').length > 0 && $(document.body).hasClass("offcanvas")) { + $('[data-toggle="offcanvas"]').click(function offcanvasClick(e) { + e.preventDefault(); $('body.offcanvas').toggleClass('active'); - var active = $('body.offcanvas').hasClass('active'); - var right = $('body.offcanvas').hasClass('offcanvas-right'); - if ((active && !right) || (!active && right)) { - $('.offcanvas-toggle .fa').removeClass('fa-chevron-right').addClass('fa-chevron-left'); - } else { - $('.offcanvas-toggle .fa').removeClass('fa-chevron-left').addClass('fa-chevron-right'); - } - $('.offcanvas-toggle .fa').attr('title', VuFind.translate(active ? 'sidebar_close' : 'sidebar_expand')); }); - $('[data-toggle="offcanvas"]').click().click(); - } else { - $('[data-toggle="offcanvas"]').addClass('hidden'); } } @@ -264,11 +245,23 @@ function setupAutocomplete() { if (searchbox.length < 1) { return; } + // Auto-submit based on config + var acCallback = function ac_cb_noop() {}; + if (searchbox.hasClass("ac-auto-submit")) { + acCallback = function autoSubmitAC(item, input) { + input.val(item.value); + $("#searchForm").submit(); + return false; + }; + } // Search autocomplete searchbox.autocomplete({ rtl: $(document.body).hasClass("rtl"), maxResults: 10, loadingString: VuFind.translate('loading') + '...', + // Auto-submit selected item + callback: acCallback, + // AJAX call for autocomplete results handler: function vufindACHandler(input, cb) { var query = input.val(); var searcher = extractClassParams(input); @@ -347,38 +340,6 @@ function keyboardShortcuts() { } } -/** - * Setup facets - */ -function setupFacets() { - // Advanced facets - $('.facetAND a,.facetOR a').click(function facetBlocking() { - $(this).closest('.collapse').html('<div class="facet">' + VuFind.translate('loading') + '...</div>'); - window.location.assign($(this).attr('href')); - }); - - // Side facet status saving - $('.facet-group .collapse').each(function openStoredFacets(index, item) { - var source = $('#result0 .hiddenSource').val(); - var storedItem = sessionStorage.getItem('sidefacet-' + source + item.id); - if (storedItem) { - var saveTransition = $.support.transition; - try { - $.support.transition = false; - if ((' ' + storedItem + ' ').indexOf(' in ') > -1) { - $(item).collapse('show'); - } else { - $(item).collapse('hide'); - } - } finally { - $.support.transition = saveTransition; - } - } - }); - $('.facet-group').on('shown.bs.collapse', facetSessionStorage); - $('.facet-group').on('hidden.bs.collapse', facetSessionStorage); -} - function setupIeSupport() { // Disable Bootstrap modal focus enforce on IE since it breaks Recaptcha. // Cannot use conditional comments since IE 11 doesn't support them but still has @@ -453,8 +414,6 @@ $(document).ready(function commonDocReady() { $.getJSON(VuFind.path + '/AJAX/JSON', {method: 'keepAlive'}); } - setupFacets(); - // retain filter sessionStorage $('.searchFormKeepFilters').click(function retainFiltersInSessionStorage() { sessionStorage.setItem('vufind_retain_filters', this.checked ? 'true' : 'false'); diff --git a/themes/bootstrap3/js/doi.js b/themes/bootstrap3/js/doi.js new file mode 100644 index 0000000000000000000000000000000000000000..6361b5a0aba0734b1e63e60e12b6f03484bf8ff2 --- /dev/null +++ b/themes/bootstrap3/js/doi.js @@ -0,0 +1,65 @@ +/*global Hunt, VuFind */ +VuFind.register('doi', function Doi() { + function embedDoiLinks(el) { + var element = $(el); + var doi = []; + var elements = element.hasClass('doiLink') ? element : element.find('.doiLink'); + elements.each(function extractDoiData(i, doiLinkEl) { + var currentDoi = $(doiLinkEl).data('doi'); + if (doi.indexOf(currentDoi) === -1) { + doi[doi.length] = currentDoi; + } + }); + if (doi.length === 0) { + return; + } + var url = VuFind.path + '/AJAX/JSON?' + $.param({ + method: 'doiLookup', + doi: doi, + }); + $.ajax({ + dataType: 'json', + url: url + }) + .done(function embedDoiLinksDone(response) { + elements.each(function populateDoiLinks(x, doiEl) { + var currentDoi = $(doiEl).data('doi'); + if ("undefined" !== typeof response.data[currentDoi]) { + $(doiEl).empty(); + for (var i = 0; i < response.data[currentDoi].length; i++) { + var newLink = $('<a />'); + newLink.attr('href', response.data[currentDoi][i].link); + newLink.text(' ' + response.data[currentDoi][i].label); + if (typeof response.data[currentDoi][i].icon !== 'undefined') { + var icon = $('<img />'); + icon.attr('src', response.data[currentDoi][i].icon); + icon.attr('class', 'doi-icon'); + $(doiEl).append(icon); + } + $(doiEl).append(newLink); + $(doiEl).append("<br />"); + } + } + }); + }); + } + + // Assign actions to the OpenURL links. This can be called with a container e.g. when + // combined results fetched with AJAX are loaded. + function init(_container) { + var container = _container || $('body'); + // assign action to the openUrlWindow link class + if (typeof Hunt === 'undefined') { + embedDoiLinks(container); + } else { + new Hunt( + container.find('.doiLink').toArray(), + { enter: embedDoiLinks } + ); + } + } + return { + init: init, + embedDoiLinks: embedDoiLinks + }; +}); diff --git a/themes/bootstrap3/js/embedGBS.js b/themes/bootstrap3/js/embedGBS.js index 515a6fca77b7be78268304c174d0c782592808f2..79e63b58e0a8979cbc4645498608946360bf4b61 100644 --- a/themes/bootstrap3/js/embedGBS.js +++ b/themes/bootstrap3/js/embedGBS.js @@ -1,14 +1,11 @@ /*global getBibKeyString, google */ - -// we don't need to wait for dom ready since lang is in the dom root -var lang = document.documentElement.getAttribute('lang'); -google.load("books", "0", { language: lang }); - -function initialize() { - var bibkeys = getBibKeyString().split(/\s+/); - var viewer = new google.books.DefaultViewer(document.getElementById('gbsViewer')); - viewer.load(bibkeys); -} - -google.setOnLoadCallback(initialize); - +$(document).ready(function activateGooglePreview() { + var lang = document.documentElement.getAttribute('lang'); + google.books.load({ language: lang }); + function initialize() { + var bibkeys = getBibKeyString().split(/\s+/); + var viewer = new google.books.DefaultViewer(document.getElementById('gbsViewer')); + viewer.load(bibkeys); + } + google.books.setOnLoadCallback(initialize); +}); \ No newline at end of file diff --git a/themes/bootstrap3/js/embedded_record.js b/themes/bootstrap3/js/embedded_record.js index 6d39891392f0de0f7f1439c80097e8a81dafea0a..d776276eefa099f4ad7bfd0ce09cbf7af31581b3 100644 --- a/themes/bootstrap3/js/embedded_record.js +++ b/themes/bootstrap3/js/embedded_record.js @@ -206,9 +206,6 @@ VuFind.register('embedded', function embedded() { var result; var i; var j; - if (!storage) { - return; - } hiddenIds = $('.hiddenId'); for (i = 0; i < items.length; i++) { parts = items[i].split(_SEPERATOR); diff --git a/themes/bootstrap3/js/facets.js b/themes/bootstrap3/js/facets.js index b3a48e0b007aba5dbe4b863b4b232f43c734b9f8..77829a5d1b66192efba03046878789aa41b1b29d 100644 --- a/themes/bootstrap3/js/facets.js +++ b/themes/bootstrap3/js/facets.js @@ -33,7 +33,7 @@ function buildFacetNodes(data, currentPath, allowExclude, excludeTitle, counts) if (!this.isApplied && counts) { $('<span/>') .addClass('badge') - .text( + .html( this.count.toString().replace(/\B(?=(\d{3})+\b)/g, VuFind.translate('number_thousands_separator')) ) .appendTo($html); @@ -72,6 +72,29 @@ function buildFacetNodes(data, currentPath, allowExclude, excludeTitle, counts) return json; } +function buildFacetTree(treeNode, facetData, inSidebar) { + // Enable keyboard navigation also when a screen reader is active + treeNode.bind('select_node.jstree', VuFind.sideFacets.showLoadingOverlay); + + var currentPath = treeNode.data('path'); + var allowExclude = treeNode.data('exclude'); + var excludeTitle = treeNode.data('exclude-title'); + + var results = buildFacetNodes(facetData, currentPath, allowExclude, excludeTitle, inSidebar); + treeNode.find('.fa-spinner').parent().remove(); + if (inSidebar) { + treeNode.on('loaded.jstree open_node.jstree', function treeNodeOpen(/*e, data*/) { + treeNode.find('ul.jstree-container-ul > li.jstree-node').addClass('list-group-item'); + treeNode.find('a.exclude').click(VuFind.sideFacets.showLoadingOverlay); + }); + } + treeNode.jstree({ + 'core': { + 'data': results + } + }); +} + function initFacetTree(treeNode, inSidebar) { var loaded = treeNode.data('loaded'); @@ -80,20 +103,9 @@ function initFacetTree(treeNode, inSidebar) } treeNode.data('loaded', true); - // Enable keyboard navigation also when a screen reader is active - treeNode.bind('select_node.jstree', function selectNode(event, data) { - $(this).closest('.collapse').html('<div class="facet">' + VuFind.translate('loading') + '...</div>'); - window.location = data.node.data.url; - event.preventDefault(); - return false; - }); - var source = treeNode.data('source'); var facet = treeNode.data('facet'); var operator = treeNode.data('operator'); - var currentPath = treeNode.data('path'); - var allowExclude = treeNode.data('exclude'); - var excludeTitle = treeNode.data('exclude-title'); var sort = treeNode.data('sort'); var query = window.location.href.split('?')[1]; @@ -111,24 +123,7 @@ function initFacetTree(treeNode, inSidebar) facetOperator: operator }, function getFacetData(response/*, textStatus*/) { - var results = buildFacetNodes(response.data.facets, currentPath, allowExclude, excludeTitle, inSidebar); - treeNode.find('.fa-spinner').parent().remove(); - if (inSidebar) { - treeNode.on('loaded.jstree open_node.jstree', function treeNodeOpen(/*e, data*/) { - treeNode.find('ul.jstree-container-ul > li.jstree-node').addClass('list-group-item'); - treeNode.find('a.exclude').click(function excludeLinkClick(e) { - $(this).closest('.collapse').html('<div class="facet">' + VuFind.translate('loading') + '...</div>'); - window.location = this.href; - e.preventDefault(); - return false; - }); - }); - } - treeNode.jstree({ - 'core': { - 'data': results - } - }); + buildFacetTree(treeNode, response.data.facets, inSidebar); } ); } @@ -147,6 +142,135 @@ function collapseTopFacets() { }); } +/* --- Side Facets --- */ +VuFind.register('sideFacets', function SideFacets() { + function showLoadingOverlay(e, data) { + e.preventDefault(); + var overlay = '<div class="facet-loading-overlay">' + + '<span class="facet-loading-overlay-label">' + VuFind.translate('loading') + + "...</span></div>"; + $(this).closest(".collapse").append(overlay); + // This callback operates both as a click handler and a JSTree callback; + // if the data element is undefined, we assume we are handling a click. + var href = typeof data === "undefined" || typeof data.node.data.url === "undefined" + ? $(this).attr('href') : data.node.data.url; + window.location.assign(href); + return false; + } + + function activateFacetBlocking(context) { + var finalContext = (typeof context === "undefined") ? $(document.body) : context; + finalContext.find('a.facet:not(.narrow-toggle),.facet a').click(showLoadingOverlay); + } + + function activateSingleAjaxFacetContainer() { + var $container = $(this); + var facetList = []; + var $facets = $container.find('div.collapse.in[data-facet], .checkbox-filter[data-facet]'); + $facets.each(function addFacet() { + if (!$(this).data('loaded')) { + facetList.push($(this).data('facet')); + } + }); + if (facetList.length === 0) { + return; + } + var urlParts = window.location.href.split('?'); + var query = urlParts.length > 1 ? urlParts[1] : ''; + var request = { + method: 'getSideFacets', + searchClassId: $container.data('searchClassId'), + location: $container.data('location'), + configIndex: $container.data('configIndex'), + query: query, + enabledFacets: facetList + }; + $container.find('.facet-load-indicator').removeClass('hidden'); + $.getJSON(VuFind.path + '/AJAX/JSON?' + query, request) + .done(function onGetSideFacetsDone(response) { + $.each(response.data.facets, function initFacet(facet, facetData) { + var containerSelector = typeof facetData.checkboxCount !== 'undefined' + ? '.checkbox-filter' : ':not(.checkbox-filter)'; + var $facetContainer = $container.find(containerSelector + '[data-facet="' + facet + '"]'); + $facetContainer.data('loaded', 'true'); + if (typeof facetData.checkboxCount !== 'undefined') { + if (facetData.checkboxCount !== null) { + $facetContainer.find('.avail-count').text( + facetData.checkboxCount.toString().replace(/\B(?=(\d{3})+\b)/g, VuFind.translate('number_thousands_separator')) + ); + } + } else if (typeof facetData.html !== 'undefined') { + $facetContainer.html(facetData.html); + activateFacetBlocking($facetContainer); + } else { + var treeNode = $facetContainer.find('.jstree-facet'); + VuFind.emit('VuFind.sidefacets.treenodeloaded', {node: treeNode}); + + buildFacetTree(treeNode, facetData.list, true); + } + $facetContainer.find('.facet-load-indicator').remove(); + }); + VuFind.lightbox.bind($('.sidebar')); + VuFind.emit('VuFind.sidefacets.loaded'); + }) + .fail(function onGetSideFacetsFail() { + $container.find('.facet-load-indicator').remove(); + $container.find('.facet-load-failed').removeClass('hidden'); + }); + } + + function loadAjaxSideFacets() { + $('.side-facets-container-ajax').each(activateSingleAjaxFacetContainer); + } + + function facetSessionStorage(e) { + var source = $('#result0 .hiddenSource').val(); + var id = e.target.id; + var key = 'sidefacet-' + source + id; + if (!sessionStorage.getItem(key)) { + sessionStorage.setItem(key, document.getElementById(id).className); + } else { + sessionStorage.removeItem(key); + } + } + + function init() { + // Display "loading" message after user clicks facet: + activateFacetBlocking(); + + // Side facet status saving + $('.facet-group .collapse').each(function openStoredFacets(index, item) { + var source = $('#result0 .hiddenSource').val(); + var storedItem = sessionStorage.getItem('sidefacet-' + source + item.id); + if (storedItem) { + var saveTransition = $.support.transition; + try { + $.support.transition = false; + if ((' ' + storedItem + ' ').indexOf(' in ') > -1) { + $(item).collapse('show'); + } else { + $(item).collapse('hide'); + } + } finally { + $.support.transition = saveTransition; + } + } + }); + $('.facet-group').on('shown.bs.collapse', facetSessionStorage); + $('.facet-group').on('hidden.bs.collapse', facetSessionStorage); + + // Side facets loaded with AJAX + $('.side-facets-container-ajax') + .find('div.collapse[data-facet]:not(.in)') + .on('shown.bs.collapse', function expandFacet() { + loadAjaxSideFacets(); + }); + loadAjaxSideFacets(); + } + + return { init: init, showLoadingOverlay: showLoadingOverlay }; +}); + /* --- Lightbox Facets --- */ VuFind.register('lightbox_facets', function LightboxFacets() { function lightboxFacetSorting() { @@ -155,11 +279,11 @@ VuFind.register('lightbox_facets', function LightboxFacets() { var sort = $(button).data('sort'); var list = $('#facet-list-' + sort); if (list.find('.js-facet-item').length === 0) { - list.find('.js-facet-next-page').text(VuFind.translate('loading') + '...'); + list.find('.js-facet-next-page').html(VuFind.translate('loading') + '...'); $.ajax(button.href + '&layout=lightbox') .done(function facetSortTitleDone(data) { list.prepend($('<span>' + data + '</span>').find('.js-facet-item')); - list.find('.js-facet-next-page').text(VuFind.translate('more') + ' ...'); + list.find('.js-facet-next-page').html(VuFind.translate('more') + ' ...'); }); } $('.full-facet-list').addClass('hidden'); @@ -182,7 +306,7 @@ VuFind.register('lightbox_facets', function LightboxFacets() { return false; } button.attr('disabled', 1); - button.text(VuFind.translate('loading') + '...'); + button.html(VuFind.translate('loading') + '...'); $.ajax(this.href + '&layout=lightbox') .done(function facetLightboxMoreDone(data) { var htmlDiv = $('<div>' + data + '</div>'); @@ -191,7 +315,7 @@ VuFind.register('lightbox_facets', function LightboxFacets() { if (list.length && htmlDiv.find('.js-facet-next-page').length) { button.attr('data-page', page + 1); button.attr('href', button.attr('href').replace(/facetpage=\d+/, 'facetpage=' + (page + 1))); - button.text(VuFind.translate('more') + ' ...'); + button.html(VuFind.translate('more') + ' ...'); button.removeAttr('disabled'); } else { button.remove(); diff --git a/themes/bootstrap3/js/lib/accessible-carousels.js b/themes/bootstrap3/js/lib/accessible-carousels.js deleted file mode 100644 index a8c9307f38e740db95fb219cc018f26d2c02b970..0000000000000000000000000000000000000000 --- a/themes/bootstrap3/js/lib/accessible-carousels.js +++ /dev/null @@ -1,388 +0,0 @@ -// Carousel Extension -// =============================== - -/** Adapted: - * - from https://github.com/paypal/bootstrap-accessibility-plugin/blob/master/src/js/carousel.js - * - for Slick: http://kenwheeler.github.io/slick/ - * - for VuFind: https://github.com/vufind-org/vufind - * - by Chris Hallberg - */ - -$(".carousel").each(function(index) { - // This function positions a highlight box around the tabs in the tablist to use in focus styling - - function setTablistHighlightBox() { - var $tab, - offset, - height, - width, - highlightBox = {}; - - highlightBox.top = 0; - highlightBox.left = 32000; - highlightBox.height = 0; - highlightBox.width = 0; - - for (var i = 0; i < $tabs.length; i++) { - $tab = $tabs[i]; - offset = $($tab).offset(); - height = $($tab).height(); - width = $($tab).width(); - - // console.log(" Top: " + offset.top + " Left: " + offset.left + " Height: " + height + " Width: " + width) - - if (highlightBox.top < offset.top) { - highlightBox.top = Math.round(offset.top); - } - - if (highlightBox.height < height) { - highlightBox.height = Math.round(height); - } - - if (highlightBox.left > offset.left) { - highlightBox.left = Math.round(offset.left); - } - - var w = offset.left - highlightBox.left + Math.round(width); - - if (highlightBox.width < w) { - highlightBox.width = w; - } - } // end for - - // console.log("[HIGHLIGHT] Top: " + highlightBox.top + " Left: " + highlightBox.left + " Height: " + highlightBox.height + " Width: " + highlightBox.width) - - $tablistHighlight.style.top = highlightBox.top - 2 + "px"; - $tablistHighlight.style.left = highlightBox.left - 2 + "px"; - $tablistHighlight.style.height = highlightBox.height + 7 + "px"; - $tablistHighlight.style.width = highlightBox.width + 8 + "px"; - } // end function - - var $this = $(this), - $prev = $this.find('.slick-prev'), - $next = $this.find('.slick-next'), - $tablist = $this.find(".slick-dots"), - $tabs = $this.find(".slick-dots button"), - $tabpanels = $this.find(".item"), - $tabpanel, - $tablistHighlight, - $pauseCarousel, - $complementaryLandmark, - $tab, - $is_paused = false, - offset, - height, - width, - i, - id_title = "id_title", - id_desc = "id_desc"; - - $tablist.attr("role", "tablist"); - - $tabs.focus(function() { - $this.carousel("pause"); - $is_paused = true; - $pauseCarousel.innerHTML = "Play Carousel"; - $(this) - .parent() - .addClass("active"); - // $(this).addClass('focus') - setTablistHighlightBox(); - $($tablistHighlight).addClass("focus"); - $(this) - .parents(".carousel") - .addClass("contrast"); - }); - - $tabs.blur(function(event) { - $(this) - .parent() - .removeClass("active"); - // $(this).removeClass('focus') - $($tablistHighlight).removeClass("focus"); - $(this) - .parents(".carousel") - .removeClass("contrast"); - }); - - for (i = 0; i < $tabpanels.length; i++) { - $tabpanel = $tabpanels[i]; - $tabpanel.setAttribute("role", "tabpanel"); - $tabpanel.setAttribute("id", "tabpanel-" + index + "-" + i); - $tabpanel.setAttribute("aria-labelledby", "tab-" + index + "-" + i); - } - - if (typeof $this.attr("role") !== "string") { - $this.attr("role", "complementary"); - $this.attr("aria-labelledby", id_title); - $this.attr("aria-describedby", id_desc); - $this.prepend( - '<p id="' + - id_desc + - '" class="sr-only">A carousel is a rotating set of images, rotation stops on keyboard focus on carousel tab controls or hovering the mouse pointer over images. Use the tabs or the previous and next buttons to change the displayed slide.</p>' - ); - $this.prepend( - '<h2 id="' + - id_title + - '" class="sr-only">Carousel content with ' + - $tabpanels.length + - " slides.</h2>" - ); - } - - for (i = 0; i < $tabs.length; i++) { - $tab = $tabs[i]; - - $tab.setAttribute("role", "tab"); - $tab.setAttribute("id", "tab-" + index + "-" + i); - $tab.setAttribute("aria-controls", "tabpanel-" + index + "-" + i); - - var tpId = "#tabpanel-" + index + "-" + i; - var caption = $this - .find(tpId) - .find("h1") - .text(); - - if (typeof caption !== "string" || caption.length === 0) - caption = $this.find(tpId).text(); - if (typeof caption !== "string" || caption.length === 0) - caption = $this - .find(tpId) - .find("h3") - .text(); - if (typeof caption !== "string" || caption.length === 0) - caption = $this - .find(tpId) - .find("h4") - .text(); - if (typeof caption !== "string" || caption.length === 0) - caption = $this - .find(tpId) - .find("h5") - .text(); - if (typeof caption !== "string" || caption.length === 0) - caption = $this - .find(tpId) - .find("h6") - .text(); - if (typeof caption !== "string" || caption.length === 0) - caption = "no title"; - - // console.log("CAPTION: " + caption ) - - var tabName = document.createElement("span"); - tabName.setAttribute("class", "sr-only"); - tabName.innerHTML = "Slide " + (i + 1); - if (caption) tabName.innerHTML += ": " + caption; - $tab.appendChild(tabName); - } - - // create div for focus styling of tablist - $tablistHighlight = document.createElement("div"); - $tablistHighlight.className = "carousel-tablist-highlight"; - document.body.appendChild($tablistHighlight); - - // create button for screen reader users to stop rotation of carousel - - // create button for screen reader users to pause carousel for virtual mode review - $complementaryLandmark = document.createElement("aside"); - $complementaryLandmark.setAttribute("class", "carousel-aside-pause"); - $complementaryLandmark.setAttribute( - "aria-label", - "carousel pause/play control" - ); - $this.prepend($complementaryLandmark); - - $pauseCarousel = document.createElement("button"); - $pauseCarousel.className = "carousel-pause-button"; - $pauseCarousel.innerHTML = "Pause Carousel"; - $pauseCarousel.setAttribute( - "title", - "Pause/Play carousel button can be used by screen reader users to stop carousel animations" - ); - $($complementaryLandmark).append($pauseCarousel); - - $($pauseCarousel).click(function() { - if ($is_paused) { - $pauseCarousel.innerHTML = "Pause Carousel"; - $this.carousel("cycle"); - $is_paused = false; - } else { - $pauseCarousel.innerHTML = "Play Carousel"; - $this.carousel("pause"); - $is_paused = true; - } - }); - $($pauseCarousel).focus(function() { - $(this).addClass("focus"); - }); - - $($pauseCarousel).blur(function() { - $(this).removeClass("focus"); - }); - - setTablistHighlightBox(); - - $(window).resize(function() { - setTablistHighlightBox(); - }); - - // Add space bar behavior to prev and next buttons for SR compatibility - $prev.attr("aria-label", "Previous Slide"); - $prev.keydown(function(e) { - var k = e.which || e.keyCode; - if (/(13|32)/.test(k)) { - e.preventDefault(); - e.stopPropagation(); - $prev.trigger("click"); - } - }); - - $prev.focus(function() { - $(this) - .parents(".carousel") - .addClass("contrast"); - }); - - $prev.blur(function() { - $(this) - .parents(".carousel") - .removeClass("contrast"); - }); - - $next.attr("aria-label", "Next Slide"); - $next.keydown(function(e) { - var k = e.which || e.keyCode; - if (/(13|32)/.test(k)) { - e.preventDefault(); - e.stopPropagation(); - $next.trigger("click"); - } - }); - - $next.focus(function() { - $(this) - .parents(".carousel") - .addClass("contrast"); - }); - - $next.blur(function() { - $(this) - .parents(".carousel") - .removeClass("contrast"); - }); - - $(".carousel-inner a").focus(function() { - $(this) - .parents(".carousel") - .addClass("contrast"); - }); - - $(".carousel-inner a").blur(function() { - $(this) - .parents(".carousel") - .removeClass("contrast"); - }); - - $tabs.each(function() { - var item = $(this); - if (item.hasClass("active")) { - item.attr({ "aria-selected": "true", tabindex: "0" }); - } else { - item.attr({ "aria-selected": "false", tabindex: "-1" }); - } - }); -}); - -var slideCarousel = $.fn.carousel.Constructor.prototype.slide; -$.fn.carousel.Constructor.prototype.slide = function(type, next) { - var $element = this.$element, - $active = $element.find("[role=tabpanel].active"), - $next = next || $active[type](), - $tab, - $tab_count = $element.find("[role=tabpanel]").size(), - $prev_side = $element.find('[data-slide="prev"]'), - $next_side = $element.find('[data-slide="next"]'), - $index = 0, - $prev_index = $tab_count - 1, - $next_index = 1, - $id; - - if ($next && $next.attr("id")) { - $id = $next.attr("id"); - $index = $id.lastIndexOf("-"); - if ($index >= 0) $index = parseInt($id.substring($index + 1), 10); - - $prev_index = $index - 1; - if ($prev_index < 1) $prev_index = $tab_count - 1; - - $next_index = $index + 1; - if ($next_index >= $tab_count) $next_index = 0; - } - - $prev_side.attr( - "aria-label", - "Show slide " + ($prev_index + 1) + " of " + $tab_count - ); - $next_side.attr( - "aria-label", - "Show slide " + ($next_index + 1) + " of " + $tab_count - ); - - slideCarousel.apply(this, arguments); - - $active.one("bsTransitionEnd", function() { - var $tab; - - $tab = $element.find('li[aria-controls="' + $active.attr("id") + '"]'); - if ($tab) $tab.attr({ "aria-selected": false, tabIndex: "-1" }); - - $tab = $element.find('li[aria-controls="' + $next.attr("id") + '"]'); - if ($tab) $tab.attr({ "aria-selected": true, tabIndex: "0" }); - }); -}; - -var $this; -$.fn.carousel.Constructor.prototype.keydown = function(e) { - $this = $this || $(this); - if (this instanceof Node) $this = $(this); - - function selectTab(index) { - if (index >= $tabs.length) return; - if (index < 0) return; - - $carousel.carousel(index); - setTimeout(function() { - $tabs[index].focus(); - // $this.prev().focus() - }, 150); - } - - var $carousel = $(e.target).closest(".carousel"), - $tabs = $carousel.find("[role=tab]"), - k = e.which || e.keyCode, - index; - - if (!/(37|38|39|40)/.test(k)) return; - - index = $tabs.index($tabs.filter(".active")); - if (k == 37 || k == 38) { - // Up - index--; - selectTab(index); - } - - if (k == 39 || k == 40) { - // Down - index++; - selectTab(index); - } - - e.preventDefault(); - e.stopPropagation(); -}; -$(document).on( - "keydown.carousel.data-api", - "li[role=tab]", - $.fn.carousel.Constructor.prototype.keydown -); diff --git a/themes/bootstrap3/js/lib/autocomplete.js b/themes/bootstrap3/js/lib/autocomplete.js index cb6e6ee04e1b005cffefe4490c2185877bdc3c0d..29665dbf85e9947fd9800f4bd94821d1f9393e64 100644 --- a/themes/bootstrap3/js/lib/autocomplete.js +++ b/themes/bootstrap3/js/lib/autocomplete.js @@ -134,16 +134,16 @@ } }; var _defaultStaticSort = function _defaultStaticSort(a, b) { - // .bind(lcterm) return a.match.indexOf(this) - b.match.indexOf(this); }; var _staticGroups = function _staticGroups(lcterm) { var matches = []; + function isTermMatch(_item) { + return _item.match.match(lcterm); + } for (var i = 0; i < options.static.groups.length; i++) { if (typeof options.static.groups[i].label !== 'undefined') { - var mitems = options.static.groups[i].items.filter(function staticLabelledGroupFilter(_item) { - return _item.match.match(lcterm); - }); + var mitems = options.static.groups[i].items.filter(isTermMatch); if (mitems.length > 0) { if (typeof options.staticSort === 'function') { mitems.sort(options.staticSort); @@ -156,9 +156,7 @@ }); } } else { - var ms = options.static.groups[i].filter(function staticGroupFilter(_item) { - return _item.match.match(lcterm); - }); + var ms = options.static.groups[i].filter(isTermMatch); if (ms.length > 0) { if (typeof options.staticSort === 'function') { ms.sort(options.staticSort); diff --git a/themes/bootstrap3/js/lightbox.js b/themes/bootstrap3/js/lightbox.js index 065af6315564af831e93629f32952dd7fd253834..07b5e4ad592e9ada619d3b0390acc19c6541cf64 100644 --- a/themes/bootstrap3/js/lightbox.js +++ b/themes/bootstrap3/js/lightbox.js @@ -70,7 +70,7 @@ VuFind.register('lightbox', function Lightbox() { var _constrainLink; var _formSubmit; function render(content) { - if (!content.match) { + if (typeof content !== "string") { return; } // Isolate successes @@ -134,7 +134,10 @@ VuFind.register('lightbox', function Lightbox() { obj.url = parts[0].indexOf('?') < 0 ? parts[0] + '?' : parts[0] + '&'; - obj.url += 'layout=lightbox&lbreferer=' + encodeURIComponent(_currentUrl); + obj.url += 'layout=lightbox'; + if (_currentUrl) { + obj.url += '&lbreferer=' + encodeURIComponent(_currentUrl); + } obj.url += parts.length < 2 ? '' : '#' + parts[1]; } _xhr = $.ajax(obj); @@ -350,6 +353,29 @@ VuFind.register('lightbox', function Lightbox() { $(form).find('[type=submit]').click(_storeClickedStatus); $('[type="submit"][form="' + form.id + '"]').click(_storeClickedStatus); }); + + // Display images in the lightbox + $('[data-lightbox-image]', el).each(function lightboxOpenImage(i, link) { + $(link).unbind("click", _constrainLink); + $(link).bind("click", function lightboxImageRender(event) { + event.preventDefault(); + var url = link.dataset.lightboxHref || link.href || link.src; + var imageCheck = $.ajax({ + url: url, + method: "HEAD" + }); + imageCheck.done(function lightboxImageCheckDone(content, status, jq_xhr) { + if ( + jq_xhr.status === 200 && + jq_xhr.getResponseHeader("content-type").substr(0, 5) === "image" + ) { + render('<div class="lightbox-image"><img src="' + url + '"/></div>'); + } else { + location.href = url; + } + }); + }); + }); } function reset() { diff --git a/themes/bootstrap3/js/map_tab_leaflet.js b/themes/bootstrap3/js/map_tab_leaflet.js index 9d7087466b1c99a0b026250e4a49f41d1ad1d03f..b1dc8a6299e982ab6877ac0dc8b79362fb9ba756 100644 --- a/themes/bootstrap3/js/map_tab_leaflet.js +++ b/themes/bootstrap3/js/map_tab_leaflet.js @@ -3,7 +3,6 @@ //Coordinate order: Storage and Query: WENS ; Display: WSEN function loadMapTab(mapData, mapGraticule, basemap) { - var init = true; var basemapLayer = new L.TileLayer(basemap[0], {attribution: basemap[1]}); var geoFeatureGroup = L.featureGroup(); // Define styles for icons @@ -21,7 +20,7 @@ function loadMapTab(mapData, mapGraticule, basemap) { }); $('#map-canvas').show(); - init = function drawMap() { + var init = function drawMap() { var featureCount = mapData.length; var label, label_name, label_coords, split_coords; var i = 0; @@ -51,7 +50,7 @@ function loadMapTab(mapData, mapGraticule, basemap) { var south = mapData[i][1]; var east = mapData[i][2]; var north = mapData[i][3]; - + // Create features var geoFeature; if (west === east && north === south) { @@ -108,5 +107,4 @@ function loadMapTab(mapData, mapGraticule, basemap) { } }; init(); - init = false; } diff --git a/themes/bootstrap3/js/preview.js b/themes/bootstrap3/js/preview.js index 677118850de673eaac37e9275da2211914d30368..49b1f927f3a7e0620cfb1fb3490838219a6e3756 100644 --- a/themes/bootstrap3/js/preview.js +++ b/themes/bootstrap3/js/preview.js @@ -72,7 +72,7 @@ function processGBSBookInfo(booksInfo) { if (viewOptions.tab.indexOf(booksInfo[bibkey].preview) >= 0 && (booksInfo[bibkey].embeddable)) { // make tab visible - $('ul.nav-tabs li.hidden a.preview').parent().removeClass('hidden'); + $('ul.nav-tabs li.hidden[data-tab="preview"]').removeClass('hidden'); } } } @@ -112,9 +112,7 @@ function setIndexOf() { throw new TypeError(); } var t = Object(this); - /*jslint bitwise: false*/ - var len = t.length >>> 0; - /*jslint bitwise: true*/ + var len = t.length; if (len === 0) { return -1; } diff --git a/themes/bootstrap3/js/vendor/bootstrap.min.js b/themes/bootstrap3/js/vendor/bootstrap.min.js index 9bcd2fccaed9442f1460191d6670ca5e8e08520c..4cd8219908a1c948fea35236de0dbe8a90c0d231 100644 --- a/themes/bootstrap3/js/vendor/bootstrap.min.js +++ b/themes/bootstrap3/js/vendor/bootstrap.min.js @@ -1,7 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under the MIT license */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){ -this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3<e[0])throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(),function(n){"use strict";n.fn.emulateTransitionEnd=function(t){var e=!1,i=this;n(this).one("bsTransitionEnd",function(){e=!0});return setTimeout(function(){e||n(i).trigger(n.support.transition.end)},t),this},n(function(){n.support.transition=function o(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(t.style[i]!==undefined)return{end:e[i]};return!1}(),n.support.transition&&(n.event.special.bsTransitionEnd={bindType:n.support.transition.end,delegateType:n.support.transition.end,handle:function(t){if(n(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}})})}(jQuery),function(s){"use strict";var e='[data-dismiss="alert"]',a=function(t){s(t).on("click",e,this.close)};a.VERSION="3.4.0",a.TRANSITION_DURATION=150,a.prototype.close=function(t){var e=s(this),i=e.attr("data-target");i||(i=(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),i="#"===i?[]:i;var o=s(document).find(i);function n(){o.detach().trigger("closed.bs.alert").remove()}t&&t.preventDefault(),o.length||(o=e.closest(".alert")),o.trigger(t=s.Event("close.bs.alert")),t.isDefaultPrevented()||(o.removeClass("in"),s.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(a.TRANSITION_DURATION):n())};var t=s.fn.alert;s.fn.alert=function o(i){return this.each(function(){var t=s(this),e=t.data("bs.alert");e||t.data("bs.alert",e=new a(this)),"string"==typeof i&&e[i].call(t)})},s.fn.alert.Constructor=a,s.fn.alert.noConflict=function(){return s.fn.alert=t,this},s(document).on("click.bs.alert.data-api",e,a.prototype.close)}(jQuery),function(s){"use strict";var n=function(t,e){this.$element=s(t),this.options=s.extend({},n.DEFAULTS,e),this.isLoading=!1};function i(o){return this.each(function(){var t=s(this),e=t.data("bs.button"),i="object"==typeof o&&o;e||t.data("bs.button",e=new n(this,i)),"toggle"==o?e.toggle():o&&e.setState(o)})}n.VERSION="3.4.0",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(t){var e="disabled",i=this.$element,o=i.is("input")?"val":"html",n=i.data();t+="Text",null==n.resetText&&i.data("resetText",i[o]()),setTimeout(s.proxy(function(){i[o](null==n[t]?this.options[t]:n[t]),"loadingText"==t?(this.isLoading=!0,i.addClass(e).attr(e,e).prop(e,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(e).removeAttr(e).prop(e,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var t=s.fn.button;s.fn.button=i,s.fn.button.Constructor=n,s.fn.button.noConflict=function(){return s.fn.button=t,this},s(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(t){var e=s(t.target).closest(".btn");i.call(e,"toggle"),s(t.target).is('input[type="radio"], input[type="checkbox"]')||(t.preventDefault(),e.is("input,button")?e.trigger("focus"):e.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(t){s(t.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(t.type))})}(jQuery),function(p){"use strict";var c=function(t,e){this.$element=p(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=e,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",p.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",p.proxy(this.pause,this)).on("mouseleave.bs.carousel",p.proxy(this.cycle,this))};function r(n){return this.each(function(){var t=p(this),e=t.data("bs.carousel"),i=p.extend({},c.DEFAULTS,t.data(),"object"==typeof n&&n),o="string"==typeof n?n:i.slide;e||t.data("bs.carousel",e=new c(this,i)),"number"==typeof n?e.to(n):o?e[o]():i.interval&&e.pause().cycle()})}c.VERSION="3.4.0",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},c.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(p.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},c.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e);if(("prev"==t&&0===i||"next"==t&&i==this.$items.length-1)&&!this.options.wrap)return e;var o=(i+("prev"==t?-1:1))%this.$items.length;return this.$items.eq(o)},c.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(i<t?"next":"prev",this.$items.eq(t))},c.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&p.support.transition&&(this.$element.trigger(p.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(t,e){var i=this.$element.find(".item.active"),o=e||this.getItemForDirection(t,i),n=this.interval,s="next"==t?"left":"right",a=this;if(o.hasClass("active"))return this.sliding=!1;var r=o[0],l=p.Event("slide.bs.carousel",{relatedTarget:r,direction:s});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=p(this.$indicators.children()[this.getItemIndex(o)]);h&&h.addClass("active")}var d=p.Event("slid.bs.carousel",{relatedTarget:r,direction:s});return p.support.transition&&this.$element.hasClass("slide")?(o.addClass(t),"object"==typeof o&&o.length&&o[0].offsetWidth,i.addClass(s),o.addClass(s),i.one("bsTransitionEnd",function(){o.removeClass([t,s].join(" ")).addClass("active"),i.removeClass(["active",s].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger(d)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(i.removeClass("active"),o.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var t=p.fn.carousel;p.fn.carousel=r,p.fn.carousel.Constructor=c,p.fn.carousel.noConflict=function(){return p.fn.carousel=t,this};var e=function(t){var e=p(this),i=e.attr("href");i&&(i=i.replace(/.*(?=#[^\s]+$)/,""));var o=e.attr("data-target")||i,n=p(document).find(o);if(n.hasClass("carousel")){var s=p.extend({},n.data(),e.data()),a=e.attr("data-slide-to");a&&(s.interval=!1),r.call(n,s),a&&n.data("bs.carousel").to(a),t.preventDefault()}};p(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),p(window).on("load",function(){p('[data-ride="carousel"]').each(function(){var t=p(this);r.call(t,t.data())})})}(jQuery),function(a){"use strict";var r=function(t,e){this.$element=a(t),this.options=a.extend({},r.DEFAULTS,e),this.$trigger=a('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"");return a(document).find(i)}function l(o){return this.each(function(){var t=a(this),e=t.data("bs.collapse"),i=a.extend({},r.DEFAULTS,t.data(),"object"==typeof o&&o);!e&&i.toggle&&/show|hide/.test(o)&&(i.toggle=!1),e||t.data("bs.collapse",e=new r(this,i)),"string"==typeof o&&e[o]()})}r.VERSION="3.4.0",r.TRANSITION_DURATION=350,r.DEFAULTS={toggle:!0},r.prototype.dimension=function(){return this.$element.hasClass("width")?"width":"height"},r.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var t,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(t=e.data("bs.collapse"))&&t.transitioning)){var i=a.Event("show.bs.collapse");if(this.$element.trigger(i),!i.isDefaultPrevented()){e&&e.length&&(l.call(e,"hide"),t||e.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var n=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return n.call(this);var s=a.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",a.proxy(n,this)).emulateTransitionEnd(r.TRANSITION_DURATION)[o](this.$element[0][s])}}}},r.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var t=a.Event("hide.bs.collapse");if(this.$element.trigger(t),!t.isDefaultPrevented()){var e=this.dimension();this.$element[e](this.$element[e]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var i=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!a.support.transition)return i.call(this);this.$element[e](0).one("bsTransitionEnd",a.proxy(i,this)).emulateTransitionEnd(r.TRANSITION_DURATION)}}},r.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},r.prototype.getParent=function(){return a(document).find(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(t,e){var i=a(e);this.addAriaAndCollapsedClass(n(i),i)},this)).end()},r.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var t=a.fn.collapse;a.fn.collapse=l,a.fn.collapse.Constructor=r,a.fn.collapse.noConflict=function(){return a.fn.collapse=t,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(t){var e=a(this);e.attr("data-target")||t.preventDefault();var i=n(e),o=i.data("bs.collapse")?"toggle":e.data();l.call(i,o)})}(jQuery),function(a){"use strict";var r='[data-toggle="dropdown"]',o=function(t){a(t).on("click.bs.dropdown",this.toggle)};function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i=e&&a(document).find(e);return i&&i.length?i:t.parent()}function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).each(function(){var t=a(this),e=l(t),i={relatedTarget:this};e.hasClass("open")&&(o&&"click"==o.type&&/input|textarea/i.test(o.target.tagName)&&a.contains(e[0],o.target)||(e.trigger(o=a.Event("hide.bs.dropdown",i)),o.isDefaultPrevented()||(t.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",i)))))}))}o.VERSION="3.4.0",o.prototype.toggle=function(t){var e=a(this);if(!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(s(),!o){"ontouchstart"in document.documentElement&&!i.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",s);var n={relatedTarget:this};if(i.trigger(t=a.Event("show.bs.dropdown",n)),t.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),i.toggleClass("open").trigger(a.Event("shown.bs.dropdown",n))}return!1}},o.prototype.keydown=function(t){if(/(38|40|27|32)/.test(t.which)&&!/input|textarea/i.test(t.target.tagName)){var e=a(this);if(t.preventDefault(),t.stopPropagation(),!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(!o&&27!=t.which||o&&27==t.which)return 27==t.which&&i.find(r).trigger("focus"),e.trigger("click");var n=i.find(".dropdown-menu li:not(.disabled):visible a");if(n.length){var s=n.index(t.target);38==t.which&&0<s&&s--,40==t.which&&s<n.length-1&&s++,~s||(s=0),n.eq(s).trigger("focus")}}}};var t=a.fn.dropdown;a.fn.dropdown=function e(i){return this.each(function(){var t=a(this),e=t.data("bs.dropdown");e||t.data("bs.dropdown",e=new o(this)),"string"==typeof i&&e[i].call(t)})},a.fn.dropdown.Constructor=o,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=t,this},a(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",r,o.prototype.toggle).on("keydown.bs.dropdown.data-api",r,o.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",o.prototype.keydown)}(jQuery),function(a){"use strict";var s=function(t,e){this.options=e,this.$body=a(document.body),this.$element=a(t),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.fixedContent=".navbar-fixed-top, .navbar-fixed-bottom",this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.modal"),i=a.extend({},s.DEFAULTS,t.data(),"object"==typeof o&&o);e||t.data("bs.modal",e=new s(this,i)),"string"==typeof o?e[o](n):i.show&&e.show(n)})}s.VERSION="3.4.0",s.TRANSITION_DURATION=300,s.BACKDROP_TRANSITION_DURATION=150,s.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},s.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},s.prototype.show=function(i){var o=this,t=a.Event("show.bs.modal",{relatedTarget:i});this.$element.trigger(t),this.isShown||t.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){o.$element.one("mouseup.dismiss.bs.modal",function(t){a(t.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var t=a.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),t&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:i});t?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(s.TRANSITION_DURATION):o.$element.trigger("focus").trigger(e)}))},s.prototype.hide=function(t){t&&t.preventDefault(),t=a.Event("hide.bs.modal"),this.$element.trigger(t),this.isShown&&!t.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(s.TRANSITION_DURATION):this.hideModal())},s.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(t){document===t.target||this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},s.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},s.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},s.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},s.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},s.prototype.backdrop=function(t){var e=this,i=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=a.support.transition&&i;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+i).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(t){this.ignoreBackdropClick?this.ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide())},this)),o&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!t)return;o?this.$backdrop.one("bsTransitionEnd",t).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var n=function(){e.removeBackdrop(),t&&t()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",n).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):n()}else t&&t()},s.prototype.handleUpdate=function(){this.adjustDialog()},s.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},s.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"";var n=this.scrollbarWidth;this.bodyIsOverflowing&&(this.$body.css("padding-right",t+n),a(this.fixedContent).each(function(t,e){var i=e.style.paddingRight,o=a(e).css("padding-right");a(e).data("padding-right",i).css("padding-right",parseFloat(o)+n+"px")}))},s.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad),a(this.fixedContent).each(function(t,e){var i=a(e).data("padding-right");a(e).removeData("padding-right"),e.style.paddingRight=i||""})},s.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var t=a.fn.modal;a.fn.modal=r,a.fn.modal.Constructor=s,a.fn.modal.noConflict=function(){return a.fn.modal=t,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(t){var e=a(this),i=e.attr("href"),o=e.attr("data-target")||i&&i.replace(/.*(?=#[^\s]+$)/,""),n=a(document).find(o),s=n.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(i)&&i},n.data(),e.data());e.is("a")&&t.preventDefault(),n.one("show.bs.modal",function(t){t.isDefaultPrevented()||n.one("hidden.bs.modal",function(){e.is(":visible")&&e.trigger("focus")})}),r.call(n,s,this)})}(jQuery),function(g){"use strict";var m=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};m.VERSION="3.4.0",m.TRANSITION_DURATION=150,m.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){return(t=g.extend({},this.getDefaults(),this.$element.data(),t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-d<c.top?"bottom":"right"==s&&l.right+h>c.width?"left":"left"==s&&l.left-h<c.left?"right":s,o.removeClass(p).addClass(s)}var f=this.getCalculatedOffset(s,l,h,d);this.applyPlacement(f,s);var u=function(){var t=i.hoverState;i.$element.trigger("shown.bs."+i.type),i.hoverState=null,"out"==t&&i.leave(i)};g.support.transition&&this.$tip.hasClass("fade")?o.one("bsTransitionEnd",u).emulateTransitionEnd(m.TRANSITION_DURATION):u()}},m.prototype.applyPlacement=function(t,e){var i=this.tip(),o=i[0].offsetWidth,n=i[0].offsetHeight,s=parseInt(i.css("margin-top"),10),a=parseInt(i.css("margin-left"),10);isNaN(s)&&(s=0),isNaN(a)&&(a=0),t.top+=s,t.left+=a,g.offset.setOffset(i[0],g.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},t),0),i.addClass("in");var r=i[0].offsetWidth,l=i[0].offsetHeight;"top"==e&&l!=n&&(t.top=t.top+n-l);var h=this.getViewportAdjustedDelta(e,t,r,l);h.left?t.left+=h.left:t.top+=h.top;var d=/top|bottom/.test(e),p=d?2*h.left-o+r:2*h.top-n+l,c=d?"offsetWidth":"offsetHeight";i.offset(t),this.replaceArrow(p,i[0][c],d)},m.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},m.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find(".tooltip-inner")[this.options.html?"html":"text"](e),t.removeClass("fade in top bottom left right")},m.prototype.hide=function(t){var e=this,i=g(this.$tip),o=g.Event("hide.bs."+this.type);function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),t&&t()}if(this.$element.trigger(o),!o.isDefaultPrevented())return i.removeClass("in"),g.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",n).emulateTransitionEnd(m.TRANSITION_DURATION):n(),this.hoverState=null,this},m.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},m.prototype.hasContent=function(){return this.getTitle()},m.prototype.getPosition=function(t){var e=(t=t||this.$element)[0],i="BODY"==e.tagName,o=e.getBoundingClientRect();null==o.width&&(o=g.extend({},o,{width:o.right-o.left,height:o.bottom-o.top}));var n=window.SVGElement&&e instanceof window.SVGElement,s=i?{top:0,left:0}:n?null:t.offset(),a={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},r=i?{width:g(window).width(),height:g(window).height()}:null;return g.extend({},o,a,r,s)},m.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},m.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})};var t=g.fn.tooltip;g.fn.tooltip=function e(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=t,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.0",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();t.find(".popover-title")[this.options.html?"html":"text"](e),t.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof i?"html":"append":"text"](i),t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.0",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(n[t+1]===undefined||e<n[t+1])&&this.activate(s[t])},n.prototype.activate=function(t){this.activeTarget=t,this.clear();var e=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',i=s(e).parents("li").addClass("active");i.parent(".dropdown-menu").length&&(i=i.closest("li.dropdown").addClass("active")),i.trigger("activate.bs.scrollspy")},n.prototype.clear=function(){s(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var t=s.fn.scrollspy;s.fn.scrollspy=e,s.fn.scrollspy.Constructor=n,s.fn.scrollspy.noConflict=function(){return s.fn.scrollspy=t,this},s(window).on("load.bs.scrollspy.data-api",function(){s('[data-spy="scroll"]').each(function(){var t=s(this);e.call(t,t.data())})})}(jQuery),function(r){"use strict";var a=function(t){this.element=r(t)};function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab");e||t.data("bs.tab",e=new a(this)),"string"==typeof i&&e[i]()})}a.VERSION="3.4.0",a.TRANSITION_DURATION=150,a.prototype.show=function(){var t=this.element,e=t.closest("ul:not(.dropdown-menu)"),i=t.data("target");if(i||(i=(i=t.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),!t.parent("li").hasClass("active")){var o=e.find(".active:last a"),n=r.Event("hide.bs.tab",{relatedTarget:t[0]}),s=r.Event("show.bs.tab",{relatedTarget:o[0]});if(o.trigger(n),t.trigger(s),!s.isDefaultPrevented()&&!n.isDefaultPrevented()){var a=r(document).find(i);this.activate(t.closest("li"),e),this.activate(a,a.parent(),function(){o.trigger({type:"hidden.bs.tab",relatedTarget:t[0]}),t.trigger({type:"shown.bs.tab",relatedTarget:o[0]})})}}},a.prototype.activate=function(t,e,i){var o=e.find("> .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.0",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<i&&"top";if("bottom"==this.affixed)return null!=i?!(n+this.unpin<=s.top)&&"bottom":!(n+a<=t-o)&&"bottom";var r=null==this.affixed,l=r?n:s.top;return null!=i&&n<=i?"top":null!=o&&t-o<=l+(r?a:e)&&"bottom"},h.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(h.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},h.prototype.checkPositionWithEventLoop=function(){setTimeout(l.proxy(this.checkPosition,this),1)},h.prototype.checkPosition=function(){if(this.$element.is(":visible")){var t=this.$element.height(),e=this.options.offset,i=e.top,o=e.bottom,n=Math.max(l(document).height(),l(document.body).height());"object"!=typeof e&&(o=i=e),"function"==typeof i&&(i=e.top(this.$element)),"function"==typeof o&&(o=e.bottom(this.$element));var s=this.getState(n,t,i,o);if(this.affixed!=s){null!=this.unpin&&this.$element.css("top","");var a="affix"+(s?"-"+s:""),r=l.Event(a+".bs.affix");if(this.$element.trigger(r),r.isDefaultPrevented())return;this.affixed=s,this.unpin="bottom"==s?this.getPinnedOffset():null,this.$element.removeClass(h.RESET).addClass(a).trigger(a.replace("affix","affixed")+".bs.affix")}"bottom"==s&&this.$element.offset({top:n-t-o})}};var t=l.fn.affix;l.fn.affix=i,l.fn.affix.Constructor=h,l.fn.affix.noConflict=function(){return l.fn.affix=t,this},l(window).on("load",function(){l('[data-spy="affix"]').each(function(){var t=l(this),e=t.data();e.offset=e.offset||{},null!=e.offsetBottom&&(e.offset.bottom=e.offsetBottom),null!=e.offsetTop&&(e.offset.top=e.offsetTop),i.call(t,e)})})}(jQuery); \ No newline at end of file diff --git a/themes/bootstrap3/js/vendor/leaflet/leaflet.latlng-graticule.js b/themes/bootstrap3/js/vendor/leaflet/leaflet.latlng-graticule.js index b6033bd4f2cb8d20fdf9a41738fc5660383858b0..e05b424babd122c836b8052bcd6283dc754650a8 100644 --- a/themes/bootstrap3/js/vendor/leaflet/leaflet.latlng-graticule.js +++ b/themes/bootstrap3/js/vendor/leaflet/leaflet.latlng-graticule.js @@ -1,546 +1,543 @@ +/* eslint-disable indent,semi */ /** * Create a Canvas as ImageOverlay to draw the Lat/Lon Graticule, * and show the axis tick label on the edge of the map. * Author: lanwei@cloudybay.com.tw - * Github Repo: https://github.com/cloudybay/leaflet.latlng-graticule * - * Edits to original code - lmgonzales 2017-12-28 - * changed L:9 from L.Layer.extend to L.LayerGroup.extend - * removed L:10 includes: L.Mixin.Events, + * Edits to original code - lmgonzales 2018-10-26 + * changed L:19 from L.Layer.extend to L.LayerGroup.extend + * removed L:20 includes: L.Mixin.Events, * - * Notes about versioning: - * Source code is version 1.1 - * https://github.com/cloudybay/leaflet.latlng-graticule/releases/tag/v1.1 + * Notes about versioning: + * Source code is version 1.1, commit ad96a41 (25 Jul 2018) + * https://github.com/cloudybay/leaflet.latlng-graticule/commit/ad96a419c6da71e4effa911856ada59a9f0c2ca6 * */ (function (window, document, undefined) { -L.LatLngGraticule = L.LayerGroup.extend({ - - options: { - showLabel: true, - opacity: 1, - weight: 0.8, - color: '#aaa', - font: '12px Verdana', - lngLineCurved: 0, - latLineCurved: 0, - zoomInterval: [ - {start: 2, end: 2, interval: 40}, - {start: 3, end: 3, interval: 20}, - {start: 4, end: 4, interval: 10}, - {start: 5, end: 7, interval: 5}, - {start: 8, end: 20, interval: 1} - ] - }, - - initialize: function (options) { - L.setOptions(this, options); - - var defaultFontName = 'Verdana'; - var _ff = this.options.font.split(' '); - if (_ff.length < 2) { - this.options.font += ' ' + defaultFontName; - } + // Change - lmgonzales - 2018-10-26 + // Commenting out the original code because browser throws deprecated function warnings. + // L.LatLngGraticule = L.Layer.extend({ + // includes: L.Mixin.Events, + // Fix is to apply the following line of code: + L.LatLngGraticule = L.LayerGroup.extend({ + options: { + showLabel: true, + opacity: 1, + weight: 0.8, + color: '#aaa', + font: '12px Verdana', + dashArray: [0,0], + lngLineCurved: 0, + latLineCurved: 0, + zoomInterval: [ + {start: 2, end: 2, interval: 40}, + {start: 3, end: 3, interval: 20}, + {start: 4, end: 4, interval: 10}, + {start: 5, end: 7, interval: 5}, + {start: 8, end: 20, interval: 1} + ] + }, + + initialize: function (options) { + L.setOptions(this, options); + + var defaultFontName = 'Verdana'; + var _ff = this.options.font.split(' '); + if (_ff.length < 2) { + this.options.font += ' ' + defaultFontName; + } - if (!this.options.fontColor) { - this.options.fontColor = this.options.color; - } + if (!this.options.fontColor) { + this.options.fontColor = this.options.color; + } - if (this.options.zoomInterval) { - if (this.options.zoomInterval.latitude) { - this.options.latInterval = this.options.zoomInterval.latitude; - if (!this.options.zoomInterval.longitude) { - this.options.lngInterval = this.options.zoomInterval.latitude; + if (this.options.zoomInterval) { + if (this.options.zoomInterval.latitude) { + this.options.latInterval = this.options.zoomInterval.latitude; + if (!this.options.zoomInterval.longitude) { + this.options.lngInterval = this.options.zoomInterval.latitude; + } } - } - if (this.options.zoomInterval.longitude) { - this.options.lngInterval = this.options.zoomInterval.longitude; - if (!this.options.zoomInterval.latitude) { - this.options.latInterval = this.options.zoomInterval.longitude; + if (this.options.zoomInterval.longitude) { + this.options.lngInterval = this.options.zoomInterval.longitude; + if (!this.options.zoomInterval.latitude) { + this.options.latInterval = this.options.zoomInterval.longitude; + } + } + if (!this.options.latInterval) { + this.options.latInterval = this.options.zoomInterval; + } + if (!this.options.lngInterval) { + this.options.lngInterval = this.options.zoomInterval; } } - if (!this.options.latInterval) { - this.options.latInterval = this.options.zoomInterval; - } - if (!this.options.lngInterval) { - this.options.lngInterval = this.options.zoomInterval; - } - } - }, + }, - onAdd: function (map) { - this._map = map; + onAdd: function (map) { + this._map = map; - if (!this._container) { - this._initCanvas(); - } - - map._panes.overlayPane.appendChild(this._container); + if (!this._canvas) { + this._initCanvas(); + } - map.on('viewreset', this._reset, this); - map.on('move', this._reset, this); - map.on('moveend', this._reset, this); + map._panes.overlayPane.appendChild(this._canvas); - if (map.options.zoomAnimation && L.Browser.any3d) { - map.on('zoomanim', this._animateZoom, this); - } + map.on('viewreset', this._reset, this); + map.on('move', this._reset, this); + map.on('moveend', this._reset, this); - this._reset(); - }, + if (map.options.zoomAnimation && L.Browser.any3d) { + map.on('zoomanim', this._animateZoom, this); + } - onRemove: function (map) { - map.getPanes().overlayPane.removeChild(this._container); + this._reset(); + }, - map.off('viewreset', this._reset, this); - map.off('move', this._reset, this); - map.off('moveend', this._reset, this); + onRemove: function (map) { + L.DomUtil.remove(this._canvas); - if (map.options.zoomAnimation) { - map.off('zoomanim', this._animateZoom, this); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - this._updateOpacity(); - return this; - }, - - bringToFront: function () { - if (this._canvas) { - this._map._panes.overlayPane.appendChild(this._canvas); - } - return this; - }, + map.off('viewreset', this._reset, this); + map.off('move', this._reset, this); + map.off('moveend', this._reset, this); - bringToBack: function () { - var pane = this._map._panes.overlayPane; - if (this._canvas) { - pane.insertBefore(this._canvas, pane.firstChild); - } - return this; - }, + if (map.options.zoomAnimation) { + map.off('zoomanim', this._animateZoom, this); + } + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + this._updateOpacity(); + return this; + }, + + bringToFront: function () { + if (this._canvas) { + //this._map._panes.overlayPane.appendChild(this._canvas); + } + return this; + }, - getAttribution: function () { - return this.options.attribution; - }, + bringToBack: function () { + var pane = this._map._panes.overlayPane; + if (this._canvas) { + //pane.insertBefore(this._canvas, pane.firstChild); + } + return this; + }, - _initCanvas: function () { - this._container = L.DomUtil.create('div', 'leaflet-image-layer'); + getAttribution: function () { + return this.options.attribution; + }, - this._canvas = L.DomUtil.create('canvas', ''); + _initCanvas: function () { - if (this._map.options.zoomAnimation && L.Browser.any3d) { - L.DomUtil.addClass(this._canvas, 'leaflet-zoom-animated'); - } else { - L.DomUtil.addClass(this._canvas, 'leaflet-zoom-hide'); - } + this._canvas = L.DomUtil.create('canvas', ''); - this._updateOpacity(); + if (this._map.options.zoomAnimation && L.Browser.any3d) { + L.DomUtil.addClass(this._canvas, 'leaflet-zoom-animated'); + } else { + L.DomUtil.addClass(this._canvas, 'leaflet-zoom-hide'); + } - this._container.appendChild(this._canvas); + this._updateOpacity(); - L.extend(this._canvas, { - onselectstart: L.Util.falseFn, - onmousemove: L.Util.falseFn, - onload: L.bind(this._onCanvasLoad, this) - }); - }, - _animateZoom: function (e) { - var map = this._map, - container = this._container, - canvas = this._canvas, - scale = map.getZoomScale(e.zoom), - nw = map.containerPointToLatLng([0, 0]), - se = map.containerPointToLatLng([canvas.width, canvas.height]), + L.extend(this._canvas, { + onselectstart: L.Util.falseFn, + onmousemove: L.Util.falseFn, + onload: L.bind(this._onCanvasLoad, this) + }); + }, - topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), - size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), - origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); + _animateZoom: function (e) { + var map = this._map, + canvas = this._canvas, + scale = map.getZoomScale(e.zoom), + nw = map.containerPointToLatLng([0, 0]), + se = map.containerPointToLatLng([canvas.width, canvas.height]), + topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), + size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), + origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); - container.style[L.DomUtil.TRANSFORM] = - L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; - }, + L.DomUtil.setTransform(canvas, origin, scale); + }, - _reset: function () { - var container = this._container, - canvas = this._canvas, - size = this._map.getSize(), - lt = this._map.containerPointToLayerPoint([0, 0]); + _reset: function () { + var canvas = this._canvas, + size = this._map.getSize(), + lt = this._map.containerPointToLayerPoint([0, 0]); - L.DomUtil.setPosition(container, lt); + L.DomUtil.setPosition(canvas, lt); - container.style.width = size.x + 'px'; - container.style.height = size.y + 'px'; + canvas.width = size.x; + canvas.height = size.y; + canvas.style.width = size.x + 'px'; + canvas.style.height = size.y + 'px'; - canvas.width = size.x; - canvas.height = size.y; - canvas.style.width = size.x + 'px'; - canvas.style.height = size.y + 'px'; + this.__calcInterval(); - this.__calcInterval(); + this.__draw(true); + }, - this.__draw(true); - }, + _onCanvasLoad: function () { + this.fire('load'); + }, - _onCanvasLoad: function () { - this.fire('load'); - }, + _updateOpacity: function () { + L.DomUtil.setOpacity(this._canvas, this.options.opacity); + }, - _updateOpacity: function () { - L.DomUtil.setOpacity(this._canvas, this.options.opacity); - }, + __format_lat: function(lat) { + if (this.options.latFormatTickLabel) { + return this.options.latFormatTickLabel(lat); + } - __format_lat: function(lat) { - if (this.options.latFormatTickLabel) { - return this.options.latFormatTickLabel(lat); - } + // todo: format type of float + if (lat < 0) { + return '' + (lat*-1) + 'S'; + } + else if (lat > 0) { + return '' + lat + 'N'; + } + return '' + lat; + }, - // todo: format type of float - if (lat < 0) { - return '' + (lat*-1) + 'S'; - } - else if (lat > 0) { - return '' + lat + 'N'; - } - return '' + lat; - }, + __format_lng: function(lng) { + if (this.options.lngFormatTickLabel) { + return this.options.lngFormatTickLabel(lng); + } - __format_lng: function(lng) { - if (this.options.lngFormatTickLabel) { - return this.options.lngFormatTickLabel(lng); - } + // todo: format type of float + if (lng > 180) { + return '' + (360 - lng) + 'W'; + } + else if (lng > 0 && lng < 180) { + return '' + lng + 'E'; + } + else if (lng < 0 && lng > -180) { + return '' + (lng*-1) + 'W'; + } + else if (lng == -180) { + return '' + (lng*-1); + } + else if (lng < -180) { + return '' + (360 + lng) + 'W'; + } + return '' + lng; + }, - // todo: format type of float - if (lng > 180) { - return '' + (360 - lng) + 'W'; - } - else if (lng > 0 && lng < 180) { - return '' + lng + 'E'; - } - else if (lng < 0 && lng > -180) { - return '' + (lng*-1) + 'W'; - } - else if (lng == -180) { - return '' + (lng*-1); - } - else if (lng < -180) { - return '' + (360 + lng) + 'W'; - } - return '' + lng; - }, - - __calcInterval: function() { - var zoom = this._map.getZoom(); - if (this._currZoom != zoom) { - this._currLngInterval = 0; - this._currLatInterval = 0; - this._currZoom = zoom; - } + __calcInterval: function() { + var zoom = this._map.getZoom(); + if (this._currZoom != zoom) { + this._currLngInterval = 0; + this._currLatInterval = 0; + this._currZoom = zoom; + } - var interv; + var interv; - if (!this._currLngInterval) { - try { - for (var idx in this.options.lngInterval) { - var dict = this.options.lngInterval[idx]; - if (dict.start <= zoom) { - if (dict.end && dict.end >= zoom) { - this._currLngInterval = dict.interval; - break; + if (!this._currLngInterval) { + try { + for (var idx in this.options.lngInterval) { + var dict = this.options.lngInterval[idx]; + if (dict.start <= zoom) { + if (dict.end && dict.end >= zoom) { + this._currLngInterval = dict.interval; + break; + } } } } + catch(e) { + this._currLngInterval = 0; + } } - catch(e) { - this._currLngInterval = 0; - } - } - if (!this._currLatInterval) { - try { - for (var idx in this.options.latInterval) { - var dict = this.options.latInterval[idx]; - if (dict.start <= zoom) { - if (dict.end && dict.end >= zoom) { - this._currLatInterval = dict.interval; - break; + if (!this._currLatInterval) { + try { + for (var idx in this.options.latInterval) { + var dict = this.options.latInterval[idx]; + if (dict.start <= zoom) { + if (dict.end && dict.end >= zoom) { + this._currLatInterval = dict.interval; + break; + } } } } + catch(e) { + this._currLatInterval = 0; + } } - catch(e) { - this._currLatInterval = 0; - } - } - }, + }, - __draw: function(label) { - function _parse_px_to_int(txt) { - if (txt.length > 2) { - if (txt.charAt(txt.length-2) == 'p') { - txt = txt.substr(0, txt.length-2); + __draw: function(label) { + function _parse_px_to_int(txt) { + if (txt.length > 2) { + if (txt.charAt(txt.length-2) == 'p') { + txt = txt.substr(0, txt.length-2); + } } - } - try { - return parseInt(txt, 10); - } - catch(e) {} - return 0; - }; - - var self = this, - canvas = this._canvas, - map = this._map, - curvedLon = this.options.lngLineCurved, - curvedLat = this.options.latLineCurved; - - if (L.Browser.canvas && map) { - if (!this._currLngInterval || !this._currLatInterval) { - this.__calcInterval(); - } + try { + return parseInt(txt, 10); + } + catch(e) {} + return 0; + }; - var latInterval = this._currLatInterval, - lngInterval = this._currLngInterval; + var self = this, + canvas = this._canvas, + map = this._map, + curvedLon = this.options.lngLineCurved, + curvedLat = this.options.latLineCurved; - var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.lineWidth = this.options.weight; - ctx.strokeStyle = this.options.color; - ctx.fillStyle = this.options.fontColor; + if (L.Browser.canvas && map) { + if (!this._currLngInterval || !this._currLatInterval) { + this.__calcInterval(); + } - if (this.options.font) { - ctx.font = this.options.font; - } - var txtWidth = ctx.measureText('0').width; - var txtHeight = 12; - try { - var _font_size = ctx.font.split(' ')[0]; - txtHeight = _parse_px_to_int(_font_size); - } - catch(e) {} + var latInterval = this._currLatInterval, + lngInterval = this._currLngInterval; - var ww = canvas.width, - hh = canvas.height; + var ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.lineWidth = this.options.weight; + ctx.strokeStyle = this.options.color; + ctx.fillStyle = this.options.fontColor; + ctx.setLineDash(this.options.dashArray); - var lt = map.containerPointToLatLng(L.point(0, 0)); - var rt = map.containerPointToLatLng(L.point(ww, 0)); - var rb = map.containerPointToLatLng(L.point(ww, hh)); + if (this.options.font) { + ctx.font = this.options.font; + } + var txtWidth = ctx.measureText('0').width; + var txtHeight = 12; + try { + var _font_size = ctx.font.split(' ')[0]; + txtHeight = _parse_px_to_int(_font_size); + } + catch(e) {} - var _lat_b = rb.lat, - _lat_t = lt.lat; - var _lon_l = lt.lng, - _lon_r = rt.lng; + var ww = canvas.width, + hh = canvas.height; - var _point_per_lat = (_lat_t - _lat_b) / (hh * 0.2); - if (isNaN(_point_per_lat)) { - return; - } + var lt = map.containerPointToLatLng(L.point(0, 0)); + var rt = map.containerPointToLatLng(L.point(ww, 0)); + var rb = map.containerPointToLatLng(L.point(ww, hh)); - if (_point_per_lat < 1) { _point_per_lat = 1; } - if (_lat_b < -90) { - _lat_b = -90; - } - else { - _lat_b = parseInt(_lat_b - _point_per_lat, 10); - } + var _lat_b = rb.lat, + _lat_t = lt.lat; + var _lon_l = lt.lng, + _lon_r = rt.lng; - if (_lat_t > 90) { - _lat_t = 90; - } - else { - _lat_t = parseInt(_lat_t + _point_per_lat, 10); - } + var _point_per_lat = (_lat_t - _lat_b) / (hh * 0.2); + if (isNaN(_point_per_lat)) { + return; + } - var _point_per_lon = (_lon_r - _lon_l) / (ww * 0.2); - if (_point_per_lon < 1) { _point_per_lon = 1; } - if (_lon_l > 0 && _lon_r < 0) { - _lon_r += 360; - } - _lon_r = parseInt(_lon_r + _point_per_lon, 10); - _lon_l = parseInt(_lon_l - _point_per_lon, 10); - - var ll, latstr, lngstr, _lon_delta = 0.5; - function __draw_lat_line(self, lat_tick) { - ll = self._latLngToCanvasPoint(L.latLng(lat_tick, _lon_l)); - latstr = self.__format_lat(lat_tick); - txtWidth = ctx.measureText(latstr).width; - - if (curvedLat) { - if (typeof(curvedLat) == 'number') { - _lon_delta = curvedLat; - } + if (_point_per_lat < 1) { _point_per_lat = 1; } + if (_lat_b < -90) { + _lat_b = -90; + } + else { + _lat_b = parseInt(_lat_b - _point_per_lat, 10); + } - var __lon_left = _lon_l, __lon_right = _lon_r; - if (ll.x > 0) { - var __lon_left = map.containerPointToLatLng(L.point(0, ll.y)); - __lon_left = __lon_left.lng - _point_per_lon; - ll.x = 0; - } - var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); - if (rr.x < ww) { - __lon_right = map.containerPointToLatLng(L.point(ww, rr.y)); - __lon_right = __lon_right.lng + _point_per_lon; - if (__lon_left > 0 && __lon_right < 0) { - __lon_right += 360; + if (_lat_t > 90) { + _lat_t = 90; + } + else { + _lat_t = parseInt(_lat_t + _point_per_lat, 10); + } + + var _point_per_lon = (_lon_r - _lon_l) / (ww * 0.2); + if (_point_per_lon < 1) { _point_per_lon = 1; } + if (_lon_l > 0 && _lon_r < 0) { + _lon_r += 360; + } + _lon_r = parseInt(_lon_r + _point_per_lon, 10); + _lon_l = parseInt(_lon_l - _point_per_lon, 10); + + var ll, latstr, lngstr, _lon_delta = 0.5; + function __draw_lat_line(self, lat_tick) { + ll = self._latLngToCanvasPoint(L.latLng(lat_tick, _lon_l)); + latstr = self.__format_lat(lat_tick); + txtWidth = ctx.measureText(latstr).width; + + if (curvedLat) { + if (typeof(curvedLat) == 'number') { + _lon_delta = curvedLat; } - } - ctx.beginPath(); - ctx.moveTo(ll.x, ll.y); - var _prev_p = null; - for (var j=__lon_left; j<=__lon_right; j+=_lon_delta) { - rr = self._latLngToCanvasPoint(L.latLng(lat_tick, j)); - ctx.lineTo(rr.x, rr.y); - - if (self.options.showLabel && label && _prev_p != null) { - if (_prev_p.x < 0 && rr.x >= 0) { - var _s = (rr.x - 0) / (rr.x - _prev_p.x); - var _y = rr.y - ((rr.y - _prev_p.y) * _s); - ctx.fillText(latstr, 0, _y + (txtHeight/2)); - } - else if (_prev_p.x <= (ww-txtWidth) && rr.x > (ww-txtWidth)) { - var _s = (rr.x - ww) / (rr.x - _prev_p.x); - var _y = rr.y - ((rr.y - _prev_p.y) * _s); - ctx.fillText(latstr, ww-txtWidth, _y + (txtHeight/2)-2); + var __lon_left = _lon_l, __lon_right = _lon_r; + if (ll.x > 0) { + var __lon_left = map.containerPointToLatLng(L.point(0, ll.y)); + __lon_left = __lon_left.lng - _point_per_lon; + ll.x = 0; + } + var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); + if (rr.x < ww) { + __lon_right = map.containerPointToLatLng(L.point(ww, rr.y)); + __lon_right = __lon_right.lng + _point_per_lon; + if (__lon_left > 0 && __lon_right < 0) { + __lon_right += 360; } } - _prev_p = {x:rr.x, y:rr.y, lon:j, lat:i}; - } - ctx.stroke(); - } - else { - var __lon_right = _lon_r; - var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); - if (curvedLon) { - __lon_right = map.containerPointToLatLng(L.point(0, rr.y)); - __lon_right = __lon_right.lng; - rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); + ctx.beginPath(); + ctx.moveTo(ll.x, ll.y); + var _prev_p = null; + for (var j=__lon_left; j<=__lon_right; j+=_lon_delta) { + rr = self._latLngToCanvasPoint(L.latLng(lat_tick, j)); + ctx.lineTo(rr.x, rr.y); + + if (self.options.showLabel && label && _prev_p != null) { + if (_prev_p.x < 0 && rr.x >= 0) { + var _s = (rr.x - 0) / (rr.x - _prev_p.x); + var _y = rr.y - ((rr.y - _prev_p.y) * _s); + ctx.fillText(latstr, 0, _y + (txtHeight/2)); + } + else if (_prev_p.x <= (ww-txtWidth) && rr.x > (ww-txtWidth)) { + var _s = (rr.x - ww) / (rr.x - _prev_p.x); + var _y = rr.y - ((rr.y - _prev_p.y) * _s); + ctx.fillText(latstr, ww-txtWidth, _y + (txtHeight/2)-2); + } + } - var __lon_left = map.containerPointToLatLng(L.point(ww, rr.y)); - __lon_left = __lon_left.lng; - ll = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_left)); + _prev_p = {x:rr.x, y:rr.y, lon:j, lat:i}; + } + ctx.stroke(); } + else { + var __lon_right = _lon_r; + var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); + if (curvedLon) { + __lon_right = map.containerPointToLatLng(L.point(0, rr.y)); + __lon_right = __lon_right.lng; + rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); + + var __lon_left = map.containerPointToLatLng(L.point(ww, rr.y)); + __lon_left = __lon_left.lng; + ll = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_left)); + } - ctx.beginPath(); - ctx.moveTo(ll.x+1, ll.y); - ctx.lineTo(rr.x-1, rr.y); - ctx.stroke(); - if (self.options.showLabel && label) { - var _yy = ll.y + (txtHeight/2)-2; - ctx.fillText(latstr, 0, _yy); - ctx.fillText(latstr, ww-txtWidth, _yy); + ctx.beginPath(); + ctx.moveTo(ll.x+1, ll.y); + ctx.lineTo(rr.x-1, rr.y); + ctx.stroke(); + if (self.options.showLabel && label) { + var _yy = ll.y + (txtHeight/2)-2; + ctx.fillText(latstr, 0, _yy); + ctx.fillText(latstr, ww-txtWidth, _yy); + } } - } - }; + }; - if (latInterval > 0) { - for (var i=latInterval; i<=_lat_t; i+=latInterval) { - if (i >= _lat_b) { - __draw_lat_line(this, i); + if (latInterval > 0) { + for (var i=latInterval; i<=_lat_t; i+=latInterval) { + if (i >= _lat_b) { + __draw_lat_line(this, i); + } } - } - for (var i=0; i>=_lat_b; i-=latInterval) { - if (i <= _lat_t) { - __draw_lat_line(this, i); + for (var i=0; i>=_lat_b; i-=latInterval) { + if (i <= _lat_t) { + __draw_lat_line(this, i); + } } } - } - - function __draw_lon_line(self, lon_tick) { - lngstr = self.__format_lng(lon_tick); - txtWidth = ctx.measureText(lngstr).width; - var bb = self._latLngToCanvasPoint(L.latLng(_lat_b, lon_tick)); - if (curvedLon) { - if (typeof(curvedLon) == 'number') { - _lat_delta = curvedLon; - } + function __draw_lon_line(self, lon_tick) { + lngstr = self.__format_lng(lon_tick); + txtWidth = ctx.measureText(lngstr).width; + var bb = self._latLngToCanvasPoint(L.latLng(_lat_b, lon_tick)); - ctx.beginPath(); - ctx.moveTo(bb.x, bb.y); - var _prev_p = null; - for (var j=_lat_b; j<_lat_t; j+=_lat_delta) { - var tt = self._latLngToCanvasPoint(L.latLng(j, lon_tick)); - ctx.lineTo(tt.x, tt.y); + if (curvedLon) { + if (typeof(curvedLon) == 'number') { + _lat_delta = curvedLon; + } - if (self.options.showLabel && label && _prev_p != null) { - if (_prev_p.y > 8 && tt.y <= 8) { - ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight); - } - else if (_prev_p.y >= hh && tt.y < hh) { - ctx.fillText(lngstr, tt.x - (txtWidth/2), hh-2); + ctx.beginPath(); + ctx.moveTo(bb.x, bb.y); + var _prev_p = null; + for (var j=_lat_b; j<_lat_t; j+=_lat_delta) { + var tt = self._latLngToCanvasPoint(L.latLng(j, lon_tick)); + ctx.lineTo(tt.x, tt.y); + + if (self.options.showLabel && label && _prev_p != null) { + if (_prev_p.y > 8 && tt.y <= 8) { + ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight); + } + else if (_prev_p.y >= hh && tt.y < hh) { + ctx.fillText(lngstr, tt.x - (txtWidth/2), hh-2); + } } - } - _prev_p = {x:tt.x, y:tt.y, lon:lon_tick, lat:j}; - } - ctx.stroke(); - } - else { - var __lat_top = _lat_t; - var tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); - if (curvedLat) { - __lat_top = map.containerPointToLatLng(L.point(tt.x, 0)); - __lat_top = __lat_top.lat; - if (__lat_top > 90) { __lat_top = 90; } - tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); - - var __lat_bottom = map.containerPointToLatLng(L.point(bb.x, hh)); - __lat_bottom = __lat_bottom.lat; - if (__lat_bottom < -90) { __lat_bottom = -90; } - bb = self._latLngToCanvasPoint(L.latLng(__lat_bottom, lon_tick)); + _prev_p = {x:tt.x, y:tt.y, lon:lon_tick, lat:j}; + } + ctx.stroke(); } + else { + var __lat_top = _lat_t; + var tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); + if (curvedLat) { + __lat_top = map.containerPointToLatLng(L.point(tt.x, 0)); + __lat_top = __lat_top.lat; + if (__lat_top > 90) { __lat_top = 90; } + tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); + + var __lat_bottom = map.containerPointToLatLng(L.point(bb.x, hh)); + __lat_bottom = __lat_bottom.lat; + if (__lat_bottom < -90) { __lat_bottom = -90; } + bb = self._latLngToCanvasPoint(L.latLng(__lat_bottom, lon_tick)); + } - ctx.beginPath(); - ctx.moveTo(tt.x, tt.y+1); - ctx.lineTo(bb.x, bb.y-1); - ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(tt.x, tt.y+1); + ctx.lineTo(bb.x, bb.y-1); + ctx.stroke(); - if (self.options.showLabel && label) { - ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight+1); - ctx.fillText(lngstr, bb.x - (txtWidth/2), hh-3); + if (self.options.showLabel && label) { + ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight+1); + ctx.fillText(lngstr, bb.x - (txtWidth/2), hh-3); + } } - } - }; + }; - if (lngInterval > 0) { - for (var i=lngInterval; i<=_lon_r; i+=lngInterval) { - if (i >= _lon_l) { - __draw_lon_line(this, i); + if (lngInterval > 0) { + for (var i=lngInterval; i<=_lon_r; i+=lngInterval) { + if (i >= _lon_l) { + __draw_lon_line(this, i); + } } - } - for (var i=0; i>=_lon_l; i-=lngInterval) { - if (i <= _lon_r) { - __draw_lon_line(this, i); + for (var i=0; i>=_lon_l; i-=lngInterval) { + if (i <= _lon_r) { + __draw_lon_line(this, i); + } } } } - } - }, + }, - _latLngToCanvasPoint: function(latlng) { - map = this._map; - var projectedPoint = map.project(L.latLng(latlng)); - projectedPoint._subtract(map.getPixelOrigin()); - return L.point(projectedPoint).add(map._getMapPanePos()); - } + _latLngToCanvasPoint: function(latlng) { + var map = this._map; + var projectedPoint = map.project(L.latLng(latlng)); + projectedPoint._subtract(map.getPixelOrigin()); + return L.point(projectedPoint).add(map._getMapPanePos()); + } -}); + }); -L.latlngGraticule = function (options) { - return new L.LatLngGraticule(options); -}; + L.latlngGraticule = function (options) { + return new L.LatLngGraticule(options); + }; -}(this, document)); + }(this, document)); diff --git a/themes/bootstrap3/less/bootstrap.less b/themes/bootstrap3/less/bootstrap.less index 6a8482e821feea7929dc06b4f8cbea4e5078f9e3..531431ca39cdff011a4e06f95f3dddfeb4e8b840 100644 --- a/themes/bootstrap3/less/bootstrap.less +++ b/themes/bootstrap3/less/bootstrap.less @@ -9,6 +9,7 @@ @import "components/alphabrowse"; @import "components/autocomplete"; @import "components/channels"; +@import "components/form"; @import "components/icons"; @import "components/js-tree"; @import "components/lightbox"; @@ -119,6 +120,10 @@ footer { padding-right: 0; } } +.flex { display: flex; } +.rtl .flex { flex-direction: row-reverse; } +.flex-col { flex: 0 1 100%; } +.flex-none { flex: none; } /* ------ Form Errors ------ */ .has-error {margin-bottom: 0;} @@ -231,18 +236,77 @@ footer { padding: 10px 15px; &:hover, &:focus { background-color: @nav-link-hover-bg; } - - .badge { float: right; } +} +.myresearch-menu .flex { display: flex; } +.myresearch-menu a:hover { + background-color: @gray-lighter; + outline: dotted 1px #000; } .myresearch-menu a.active { background-color: @brand-primary; color: #fff; - - .badge { - background-color: #fff; - color: @gray-darker; - } } +.myresearch-menu .active .badge { + background-color: #fff; + color: @gray-darker; +} +.myresearch-menu a > .badge { float: right; } +.myresearch-menu .status { + float: right; + display: flex; + flex: none; +} +.myresearch-menu .status .ok, +.myresearch-menu .status.ok { color: @state-success-text; } +.myresearch-menu .status .warn, +.myresearch-menu .status.warn { color: @state-warning-text; } +.myresearch-menu .status .overdue, +.myresearch-menu .status.overdue { color: @state-danger-text; } +.myresearch-menu .badge.ok { background-color: @state-success-bg; } +.myresearch-menu .badge.warn { background-color: @state-warning-bg; } +.myresearch-menu .badge.overdue { background-color: @state-danger-bg; } + +.checkedout-status .badge { + border-radius: 2px; + margin: 0 2px; + border: 1px solid; /* color inherited from bootstrap */ + height: 20px; +} +.active .status .badge { + color: #fff; + background-color: transparent; + border: 1px solid #fff; +} +.myresearch-menu .active .ok { + background-color: @state-success-text; + border-color: @state-success-bg; +} +.myresearch-menu .active .warn { + background-color: @state-warning-text; + border-color: @state-warning-bg; +} +.myresearch-menu .active .overdue { + background-color: @state-danger-text; + border-color: @state-danger-bg; +} +.myresearch-menu .active .warn { background-color: @state-warning-text; } +.myresearch-menu .active .overdue { background-color: @state-danger-text; } +.myresearch-menu .active .text-success { color: @state-success-bg; } +.myresearch-menu .active .text-warning { color: @state-warning-bg; } +.myresearch-menu .active .text-danger { color: @state-danger-bg; } + +.logoutOptions.with-dropdown a { padding-right: .5rem; } +#login-dropdown a { + margin-right: .5rem; + padding-left: .5rem; + padding-right: .5rem; +} +#login-dropdown .dropdown-menu { width: 250px; } +#login-dropdown .dropdown-menu h4 { display: none; } +#login-dropdown .dropdown-menu .myresearch-menu { display: none; } +#login-dropdown .dropdown-menu .account-menu { display: block; } + +/* --- PubDateVis --- */ .list-edit-container { .clearfix(); } /* ------ PubDateVis ------ */ diff --git a/themes/bootstrap3/less/components/form.less b/themes/bootstrap3/less/components/form.less new file mode 100644 index 0000000000000000000000000000000000000000..5a67b247fb004365778008ac06ddae6b3d05f2a9 --- /dev/null +++ b/themes/bootstrap3/less/components/form.less @@ -0,0 +1,21 @@ +form { + textarea:invalid, + input:invalid { + box-shadow: 0 0 2px 1px rgba(255, 0, 0, 0.9); + } + .form-info { + font-weight: bold; + margin: 20px 0; + } + .info { + margin: 10px 0; + } + .form-group ul { + padding: 0; + margin-left: 15px; + margin-top: 5px; + } + .form-group label.required::before { + content: '* '; + } +} diff --git a/themes/bootstrap3/less/components/icons.less b/themes/bootstrap3/less/components/icons.less index ed654a6ed50f84aae44d12426c570c701cda0035..751dfbcd26d889176ecb36577a05820cb45cd6a8 100644 --- a/themes/bootstrap3/less/components/icons.less +++ b/themes/bootstrap3/less/components/icons.less @@ -1,7 +1,11 @@ /** * Assign catalog formats to Font Awesome icons */ - +.doi-icon { + height: 1em; + width: 14px; + filter: brightness(50%); +} // Alias .fa-printer:before {content: "\f02f";} // .fa-print // Search Icons diff --git a/themes/bootstrap3/less/components/lightbox.less b/themes/bootstrap3/less/components/lightbox.less index d24c96b3f65bd1b6465a5a7d7725c13d54a5722c..d7adf7a0bfd9a6bc76819e5e0af496c9ebb7130f 100644 --- a/themes/bootstrap3/less/components/lightbox.less +++ b/themes/bootstrap3/less/components/lightbox.less @@ -43,4 +43,7 @@ body.rtl .modal-loading { float: left; } // Utility classes .lightbox-only { display: none; } -#modal .lightbox-only { display: initial; } \ No newline at end of file +#modal .lightbox-only { display: initial; } + +// Image display +.lightbox-image { text-align: center; } \ No newline at end of file diff --git a/themes/bootstrap3/less/components/offcanvas.less b/themes/bootstrap3/less/components/offcanvas.less index d6620248847a94505f503eb70b6b8c1b8e5e08a8..4b4a7876ba6437c3d8059a2c99a79ea07373e57e 100644 --- a/themes/bootstrap3/less/components/offcanvas.less +++ b/themes/bootstrap3/less/components/offcanvas.less @@ -1,88 +1,118 @@ -@offcanvas-offset: 75vw; // Width of open menu -@offcanvas-padding: 30px; // Body offset when offcanvas active, also width of toggle +@offcanvas-offset: 80vw; // Width of open menu -.offcanvas-overlay, -.offcanvas-toggle { display: none; } +.offcanvas-overlay { display: none; } + +.search-filter-toggle { + &:extend(.btn); + &:extend(.btn-default); + margin-top: 1rem; + margin-bottom: 1rem; +} + +.close-offcanvas, +.search-filter-toggle { display: none; } @media screen and (max-width: 767px) { + .close-offcanvas::before, + .close-offcanvas::after, + .search-filter-toggle::before, + .search-filter-toggle::after { + display: inline-block; + width: 16px; + font: normal normal normal 14px/1 FontAwesome; + } + + .offcanvas .close-offcanvas { display: block; } + .search-filter-toggle { + &:extend(.btn); + &:extend(.btn-default); + margin-top: 1rem; + margin-bottom: 1rem; + } + body.offcanvas { overflow-x: hidden; /* Prevent scroll on narrow devices */ - .sidebar { - position: fixed; - height: 100%; - top: 0; - width: @offcanvas-offset; - padding-left: 0; - padding-right: 0; - overflow-y: auto; - h4 { padding-left: @padding-base-horizontal; } - .checkbox { margin-left: 20px + @padding-base-horizontal; } - .list-group, .list-group-item { - border-left: 0; - border-right: 0; - border-radius: 0 !important; - } - } - &.active { overflow-y: hidden; } + transition: margin .5s; + } + .offcanvas-overlay { + display: none; + position: fixed; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,.3); + z-index: 3; + opacity: 0; + transition: opacity .5s; + cursor: pointer; + } + .offcanvas .offcanvas-overlay { display: block; } + + .offcanvas-left { + .sidebar { left: -@offcanvas-offset; } + .offcanvas-overlay { right: -100%; } + .offcanvas-toggle { left: 0; } + } + .offcanvas-right { + .sidebar { right: -@offcanvas-offset; } + .offcanvas-overlay { left: -100%; } + .offcanvas-toggle { right: 0; } + } + .offcanvas .sidebar { + position: fixed; + height: 100%; + top: 0; + width: @offcanvas-offset; + padding: 1rem; + overflow-y: auto; + background-color: #fff; + transition: left .5s, right .5s; + + .search-sort { padding-bottom: 1rem; } + } + .offcanvas.active { + overflow-y: hidden; &.offcanvas-left { - padding-left: @offcanvas-padding - @grid-gutter-width/2; - & .main { background: #FFF; } - &.active { - margin-left: @offcanvas-offset; - margin-right: -@offcanvas-offset; - .sidebar { left: 0; } - .offcanvas-overlay { right: -@offcanvas-offset; } - .offcanvas-toggle { left: @offcanvas-offset; } - } - .sidebar { left: -@offcanvas-offset; } - .offcanvas-overlay { right: -100%; } - .offcanvas-toggle { left: 0; } + margin-left: @offcanvas-offset; + margin-right: -@offcanvas-offset; + .sidebar { left: 0; } + .offcanvas-overlay { right: -@offcanvas-offset; } + .offcanvas-toggle { left: @offcanvas-offset; } } &.offcanvas-right { - padding-right: @offcanvas-padding - @grid-gutter-width/2; - & .main > .container { background: #FFF; } - &.active { - margin-left: -@offcanvas-offset; - margin-right: @offcanvas-offset; - .sidebar { right: 0; } - .offcanvas-overlay { left: -@offcanvas-offset; } - .offcanvas-toggle { right: @offcanvas-offset; } - } - .sidebar { right: -@offcanvas-offset; } - .offcanvas-overlay { left: -100%; } - .offcanvas-toggle { right: 0; } + margin-left: -@offcanvas-offset; + margin-right: @offcanvas-offset; + .sidebar { right: 0; } + .offcanvas-overlay { left: -@offcanvas-offset; } + .offcanvas-toggle { right: @offcanvas-offset; } } .offcanvas-overlay { - display: block; - position: fixed; - top: 0; - width: 100%; - height: 100%; - background-color: rgba(0,0,0,.3); - z-index: 3; + opacity: 1; + transition: opacity .5s; } - .offcanvas-toggle { - display: block; - position: fixed; - top: 0; - width: calc(@offcanvas-padding - 5px); - height: 100%; - border-left: 1px solid @gray-lighter; - border-right: 1px solid @gray-lighter; - line-height: 90vh; // Center vertically - text-align: center; - background-color: #fff; - z-index: 5; + } + + /* Button arrows */ + .offcanvas-left { + .close-offcanvas::after { content: "\f105"; } + .search-filter-toggle::before { content: "\f100"; } + } + .offcanvas-right { + .close-offcanvas::before { content: "\f104"; } + .search-filter-toggle::after { content: "\f101"; } + } + .rtl /* right to left */ { + &.offcanvas-left { + .close-offcanvas::after { content: none; } + .close-offcanvas::before { content: "\f105"; } + .search-filter-toggle::before { content: none; } + .search-filter-toggle::after { content: "\f100"; } } - .offcanvas-overlay, - .offcanvas-toggle, - .offcanvas-toggle * { cursor: pointer; } - &,.sidebar, - .offcanvas-overlay, - .offcanvas-toggle { - -webkit-transition: all .25s ease-out; - -o-transition: all .25s ease-out; - transition: all .25s ease-out; + &.offcanvas-right { + .close-offcanvas::before { content: none; } + .close-offcanvas::after { content: "\f104"; } + .search-filter-toggle::after { content: none; } + .search-filter-toggle::before { content: "\f101"; } } } } diff --git a/themes/bootstrap3/less/components/search.less b/themes/bootstrap3/less/components/search.less index acb510013ab2ec71298d4d468e04914fdc3ab850..53cfc094de839024d1d84b392f52b1d69e450df5 100644 --- a/themes/bootstrap3/less/components/search.less +++ b/themes/bootstrap3/less/components/search.less @@ -40,8 +40,8 @@ header .container.navbar { margin-bottom: 0; } } .search-stats { display: block; - padding-top: 1rem; - padding-bottom: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; } @media (min-width: 768px) { diff --git a/themes/bootstrap3/less/components/sidebar.less b/themes/bootstrap3/less/components/sidebar.less index d63c21b5d50d3fd6d667755f53ede11960bda1cd..b27cedde1e06a5a932f04bf796871bbd5722989f 100644 --- a/themes/bootstrap3/less/components/sidebar.less +++ b/themes/bootstrap3/less/components/sidebar.less @@ -18,15 +18,16 @@ .collapse, .collapsing, & > .facet { + position: relative; border-left: 1px solid @list-group-border; border-right: 1px solid @list-group-border; } & > .facet:first-child { border-top: 1px solid @list-group-border; } } - .facet, -.facet-group .title { +.facet-group .title, +.facet-load-indicator { display: flex; padding: .5rem; width: 100%; @@ -40,7 +41,8 @@ .badge { flex-shrink: 0; max-height: 19px; - line-height: 1.1rem; + line-height: 1.2; + vertical-align: baseline; } .exclude { @@ -49,7 +51,8 @@ padding-left: 0.5rem; } } -.facet { +.facet-group .facet, +.facet-load-indicator { border-bottom: 1px solid @list-group-border; } .facet-group .title { @@ -59,11 +62,23 @@ font-weight: bold; text-align: inherit; } - -.top-facets { - margin-left: -.5rem; - margin-right: -.5rem; +.facet-loading-overlay { + position: absolute; + top: 0; + left: 0; + display: flex; + width: 100%; + height: 100%; + align-items: center; + justify-content: center; + background-color: rgba(0,0,0,0.4); +} +.facet-loading-overlay-label { + padding: 1px .5rem; + color: #fff; + background-color: #000; } + .top-facets .facet, .top-facets .narrow-toggle, .top-facets > strong { @@ -74,10 +89,18 @@ white-space: nowrap; } .top-facets .narrow-toggle { text-decoration: underline; } +.top-facets .top-facet { + margin-top: 2px; + margin-bottom: 2px; + border: 1px solid @list-group-border; +} +.checkboxFilter { + padding-bottom: 0.5rem; +} .checkbox-filter { - display: block; - padding-bottom: 1rem; + display: flex; + width: 100%; font-weight: bold; color: @text-color; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/alerts.less b/themes/bootstrap3/less/vendor/bootstrap/alerts.less index c4199db927e795b6d7d35a39d475ef3087e2dfec..bdd0df20250eed4363068b40f1fde8792f4da4fa 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/alerts.less +++ b/themes/bootstrap3/less/vendor/bootstrap/alerts.less @@ -15,8 +15,7 @@ // Headings for larger alerts h4 { margin-top: 0; - // Specified for the h4 to prevent conflicts of changing @headings-color - color: inherit; + color: inherit; // Specified for the h4 to prevent conflicts of changing @headings-color } // Provide class for links that match alerts @@ -39,7 +38,8 @@ // // Expand the right padding and account for the close button's positioning. -.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +// The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissable, .alert-dismissible { padding-right: (@alert-padding + 20); diff --git a/themes/bootstrap3/less/vendor/bootstrap/badges.less b/themes/bootstrap3/less/vendor/bootstrap/badges.less index 6ee16dca413ea6d846ed8dbaf07cf0d7d9724bc9..be7f8d0cc618a548818a686db7dae536772075a8 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/badges.less +++ b/themes/bootstrap3/less/vendor/bootstrap/badges.less @@ -10,11 +10,11 @@ padding: 3px 7px; font-size: @font-size-small; font-weight: @badge-font-weight; - color: @badge-color; line-height: @badge-line-height; - vertical-align: middle; - white-space: nowrap; + color: @badge-color; text-align: center; + white-space: nowrap; + vertical-align: middle; background-color: @badge-bg; border-radius: @badge-border-radius; diff --git a/themes/bootstrap3/less/vendor/bootstrap/bootstrap.less b/themes/bootstrap3/less/vendor/bootstrap/bootstrap.less index fff1594ce014ad988748afb90adc53392704d972..170c428bf792266700656cd112b4426c3a0b7ffc 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/bootstrap.less +++ b/themes/bootstrap3/less/vendor/bootstrap/bootstrap.less @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ diff --git a/themes/bootstrap3/less/vendor/bootstrap/breadcrumbs.less b/themes/bootstrap3/less/vendor/bootstrap/breadcrumbs.less index cb01d503fbe5f7615e53c989bbee20c07c86e7ef..e4e53961ad36c34b17873ed340c1b060c5bb9878 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/breadcrumbs.less +++ b/themes/bootstrap3/less/vendor/bootstrap/breadcrumbs.less @@ -14,9 +14,9 @@ display: inline-block; + li:before { - content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space padding: 0 5px; color: @breadcrumb-color; + content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/button-groups.less b/themes/bootstrap3/less/vendor/bootstrap/button-groups.less index 16db0c6135e79744f43b578edc0b79a10f74267c..0472800f16401273b66b8693735c6a8b4c0ec2c7 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/button-groups.less +++ b/themes/bootstrap3/less/vendor/bootstrap/button-groups.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type */ + // // Button groups // -------------------------------------------------- @@ -103,18 +105,18 @@ // Give the line between buttons some depth .btn-group > .btn + .dropdown-toggle { - padding-left: 8px; padding-right: 8px; + padding-left: 8px; } .btn-group > .btn-lg + .dropdown-toggle { - padding-left: 12px; padding-right: 12px; + padding-left: 12px; } // The clickable button for toggling the menu // Remove the gradient and set the same inset shadow as the :active state .btn-group.open .dropdown-toggle { - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); // Show no shadow for `.btn-link` since it has no other button styles. &.btn-link { @@ -205,8 +207,8 @@ border-collapse: separate; > .btn, > .btn-group { - float: none; display: table-cell; + float: none; width: 1%; } > .btn-group .btn { @@ -237,7 +239,7 @@ input[type="radio"], input[type="checkbox"] { position: absolute; - clip: rect(0,0,0,0); + clip: rect(0, 0, 0, 0); pointer-events: none; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/buttons.less b/themes/bootstrap3/less/vendor/bootstrap/buttons.less index 9cbb8f416faf2b53a56c358558a9c954ba28ab87..17f076bcfb6da411ea845b6117e309caedb843d6 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/buttons.less +++ b/themes/bootstrap3/less/vendor/bootstrap/buttons.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type + // // Buttons // -------------------------------------------------- @@ -11,12 +13,12 @@ margin-bottom: 0; // For input.btn font-weight: @btn-font-weight; text-align: center; + white-space: nowrap; vertical-align: middle; touch-action: manipulation; cursor: pointer; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid transparent; - white-space: nowrap; .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base); .user-select(none); @@ -38,9 +40,9 @@ &:active, &.active { - outline: 0; background-image: none; - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + outline: 0; + .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); } &.disabled, @@ -92,8 +94,8 @@ // Make a button look and behave like a link .btn-link { + font-weight: 400; color: @link-color; - font-weight: normal; border-radius: 0; &, diff --git a/themes/bootstrap3/less/vendor/bootstrap/carousel.less b/themes/bootstrap3/less/vendor/bootstrap/carousel.less index 252011e9e250811e000f2067d88d04ba34d6e80c..1a247958cc407b86773377495976e6783b92820d 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/carousel.less +++ b/themes/bootstrap3/less/vendor/bootstrap/carousel.less @@ -1,3 +1,5 @@ +// stylelint-disable media-feature-name-no-unknown + // // Carousel // -------------------------------------------------- @@ -10,12 +12,12 @@ .carousel-inner { position: relative; - overflow: hidden; width: 100%; + overflow: hidden; > .item { - display: none; position: relative; + display: none; .transition(.6s ease-in-out left); // Account for jankitude on images @@ -27,8 +29,8 @@ // WebKit CSS3 transforms for supported devices @media all and (transform-3d), (-webkit-transform-3d) { - .transition-transform(~'0.6s ease-in-out'); - .backface-visibility(~'hidden'); + .transition-transform(~"0.6s ease-in-out"); + .backface-visibility(~"hidden"); .perspective(1000px); &.next, @@ -93,34 +95,34 @@ .carousel-control { position: absolute; top: 0; - left: 0; bottom: 0; + left: 0; width: @carousel-control-width; - .opacity(@carousel-control-opacity); font-size: @carousel-control-font-size; color: @carousel-control-color; text-align: center; text-shadow: @carousel-text-shadow; background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug + .opacity(@carousel-control-opacity); // We can't have this transition here because WebKit cancels the carousel // animation if you trip this while in the middle of another animation. // Set gradients for backgrounds &.left { - #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); + #gradient > .horizontal(@start-color: rgba(0, 0, 0, .5); @end-color: rgba(0, 0, 0, .0001)); } &.right { - left: auto; right: 0; - #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); + left: auto; + #gradient > .horizontal(@start-color: rgba(0, 0, 0, .0001); @end-color: rgba(0, 0, 0, .5)); } // Hover/focus state &:hover, &:focus { - outline: 0; color: @carousel-control-color; text-decoration: none; + outline: 0; .opacity(.9); } @@ -131,9 +133,9 @@ .glyphicon-chevron-right { position: absolute; top: 50%; - margin-top: -10px; z-index: 5; display: inline-block; + margin-top: -10px; } .icon-prev, .glyphicon-chevron-left { @@ -147,21 +149,20 @@ } .icon-prev, .icon-next { - width: 20px; + width: 20px; height: 20px; - line-height: 1; font-family: serif; + line-height: 1; } - .icon-prev { &:before { - content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) + content: "\2039";// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) } } .icon-next { &:before { - content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) + content: "\203a";// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) } } } @@ -177,21 +178,18 @@ left: 50%; z-index: 15; width: 60%; - margin-left: -30%; padding-left: 0; - list-style: none; + margin-left: -30%; text-align: center; + list-style: none; li { display: inline-block; - width: 10px; + width: 10px; height: 10px; margin: 1px; text-indent: -999px; - border: 1px solid @carousel-indicator-border-color; - border-radius: 10px; cursor: pointer; - // IE8-9 hack for event handling // // Internet Explorer 8-9 does not support clicks on elements without a set @@ -202,12 +200,16 @@ // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we // set alpha transparency for the best results possible. background-color: #000 \9; // IE8 - background-color: rgba(0,0,0,0); // IE9 + background-color: rgba(0, 0, 0, 0); // IE9 + + border: 1px solid @carousel-indicator-border-color; + border-radius: 10px; } + .active { - margin: 0; - width: 12px; + width: 12px; height: 12px; + margin: 0; background-color: @carousel-indicator-active-bg; } } @@ -217,15 +219,16 @@ // Hidden by default for smaller viewports .carousel-caption { position: absolute; - left: 15%; right: 15%; bottom: 20px; + left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: @carousel-caption-color; text-align: center; text-shadow: @carousel-text-shadow; + & .btn { text-shadow: none; // No shadow for button elements in carousel-caption } @@ -258,8 +261,8 @@ // Show and left align the captions .carousel-caption { - left: 20%; right: 20%; + left: 20%; padding-bottom: 30px; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/close.less b/themes/bootstrap3/less/vendor/bootstrap/close.less index 6d5bfe087aed3342270b1de9d70d034c474a3779..48baf355fd2cdc044249b1ae2b74d41f26404a7f 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/close.less +++ b/themes/bootstrap3/less/vendor/bootstrap/close.less @@ -1,3 +1,5 @@ +// stylelint-disable property-no-vendor-prefix + // // Close icons // -------------------------------------------------- @@ -30,5 +32,6 @@ background: transparent; border: 0; -webkit-appearance: none; + appearance: none; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/code.less b/themes/bootstrap3/less/vendor/bootstrap/code.less index a08b4d48c4c8715dac93a5422f0d340ae9cc6bff..4e07976d5428907d1fe7a2aa2b62e1b6aff5d383 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/code.less +++ b/themes/bootstrap3/less/vendor/bootstrap/code.less @@ -27,12 +27,12 @@ kbd { color: @kbd-color; background-color: @kbd-bg; border-radius: @border-radius-small; - box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); kbd { padding: 0; font-size: 100%; - font-weight: bold; + font-weight: 700; box-shadow: none; } } @@ -44,9 +44,9 @@ pre { margin: 0 0 (@line-height-computed / 2); font-size: (@font-size-base - 1); // 14px to 13px line-height: @line-height-base; + color: @pre-color; word-break: break-all; word-wrap: break-word; - color: @pre-color; background-color: @pre-bg; border: 1px solid @pre-border-color; border-radius: @border-radius-base; diff --git a/themes/bootstrap3/less/vendor/bootstrap/component-animations.less b/themes/bootstrap3/less/vendor/bootstrap/component-animations.less index 0bcee910ac5f2c249cd6280d1e69fd03d178b24e..4e7cfd0b55ac2c2b472ddd55e69d0ea7aa01a86e 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/component-animations.less +++ b/themes/bootstrap3/less/vendor/bootstrap/component-animations.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type + // // Component animations // -------------------------------------------------- @@ -10,6 +12,7 @@ .fade { opacity: 0; .transition(opacity .15s linear); + &.in { opacity: 1; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/dropdowns.less b/themes/bootstrap3/less/vendor/bootstrap/dropdowns.less index f6876c1a9b2a8d7fb3574d090248f4762139c0c2..542c00461adcc54a5f282975fb2a3243458021b5 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/dropdowns.less +++ b/themes/bootstrap3/less/vendor/bootstrap/dropdowns.less @@ -10,10 +10,10 @@ height: 0; margin-left: 2px; vertical-align: middle; - border-top: @caret-width-base dashed; - border-top: @caret-width-base solid ~"\9"; // IE8 + border-top: @caret-width-base dashed; + border-top: @caret-width-base solid ~"\9"; // IE8 border-right: @caret-width-base solid transparent; - border-left: @caret-width-base solid transparent; + border-left: @caret-width-base solid transparent; } // The dropdown wrapper (div) @@ -38,15 +38,15 @@ min-width: 160px; padding: 5px 0; margin: 2px 0 0; // override default ul - list-style: none; font-size: @font-size-base; text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + list-style: none; background-color: @dropdown-bg; + background-clip: padding-box; border: 1px solid @dropdown-fallback-border; // IE8 fallback border: 1px solid @dropdown-border; border-radius: @border-radius-base; - .box-shadow(0 6px 12px rgba(0,0,0,.175)); - background-clip: padding-box; + .box-shadow(0 6px 12px rgba(0, 0, 0, .175)); // Aligns the dropdown menu to right // @@ -66,20 +66,17 @@ display: block; padding: 3px 20px; clear: both; - font-weight: normal; + font-weight: 400; line-height: @line-height-base; color: @dropdown-link-color; white-space: nowrap; // prevent links from randomly breaking onto new lines - } -} -// Hover/Focus state -.dropdown-menu > li > a { - &:hover, - &:focus { - text-decoration: none; - color: @dropdown-link-hover-color; - background-color: @dropdown-link-hover-bg; + &:hover, + &:focus { + color: @dropdown-link-hover-color; + text-decoration: none; + background-color: @dropdown-link-hover-bg; + } } } @@ -90,8 +87,8 @@ &:focus { color: @dropdown-link-active-color; text-decoration: none; - outline: 0; background-color: @dropdown-link-active-bg; + outline: 0; } } @@ -110,10 +107,10 @@ &:hover, &:focus { text-decoration: none; + cursor: @cursor-disabled; background-color: transparent; background-image: none; // Remove CSS gradient .reset-filter(); - cursor: @cursor-disabled; } } @@ -135,8 +132,8 @@ // Add extra class to `.dropdown-menu` to flip the alignment of the dropdown // menu with the parent. .dropdown-menu-right { - left: auto; // Reset the default from `.dropdown-menu` right: 0; + left: auto; // Reset the default from `.dropdown-menu` } // With v3, we enabled auto-flipping if you have a dropdown within a right // aligned nav component. To enable the undoing of that, we provide an override @@ -145,8 +142,8 @@ // This is only for left-aligning a dropdown menu within a `.navbar-right` or // `.pull-right` nav component. .dropdown-menu-left { - left: 0; right: auto; + left: 0; } // Dropdown section headers @@ -162,10 +159,10 @@ // Backdrop to catch body clicks on mobile, etc. .dropdown-backdrop { position: fixed; - left: 0; + top: 0; right: 0; bottom: 0; - top: 0; + left: 0; z-index: (@zindex-dropdown - 10); } @@ -184,10 +181,10 @@ .navbar-fixed-bottom .dropdown { // Reverse the caret .caret { + content: ""; border-top: 0; border-bottom: @caret-width-base dashed; border-bottom: @caret-width-base solid ~"\9"; // IE8 - content: ""; } // Different positioning for bottom up menu .dropdown-menu { diff --git a/themes/bootstrap3/less/vendor/bootstrap/forms.less b/themes/bootstrap3/less/vendor/bootstrap/forms.less index 9377d3846b9f46eac257ca6e4600598bd9e12f71..edf19bfb6d1324c45c151cb55ad5eff5ad14d0c9 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/forms.less +++ b/themes/bootstrap3/less/vendor/bootstrap/forms.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type, property-no-vendor-prefix, media-feature-name-no-vendor-prefix + // // Forms // -------------------------------------------------- @@ -8,13 +10,13 @@ // Restyle and baseline non-control form elements. fieldset { - padding: 0; - margin: 0; - border: 0; // Chrome and Firefox set a `min-width: min-content;` on fieldsets, // so we reset that to ensure it behaves more like a standard block element. // See https://github.com/twbs/bootstrap/issues/12359. min-width: 0; + padding: 0; + margin: 0; + border: 0; } legend { @@ -33,7 +35,7 @@ label { display: inline-block; max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) margin-bottom: 5px; - font-weight: bold; + font-weight: 700; } @@ -43,9 +45,18 @@ label { // is required to ensure optimum display with or without those classes to better // address browser inconsistencies. -// Override content-box in Normalize (* isn't specific enough) input[type="search"] { + // Override content-box in Normalize (* isn't specific enough) .box-sizing(border-box); + + // Search inputs in iOS + // + // This overrides the extra rounded corners on search inputs in iOS so that our + // `.form-control` class can properly style them. Note that this cannot simply + // be added to `.form-control` as it's not specific enough. For details, see + // https://github.com/twbs/bootstrap/issues/11586. + -webkit-appearance: none; + appearance: none; } // Position radios and checkboxes better @@ -54,6 +65,16 @@ input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; // IE8-9 line-height: normal; + + // Apply same disabled cursor tweak as for inputs + // Some special care is needed because <label>s don't inherit their parent's `cursor`. + // + // Note: Neither radios nor checkboxes can be readonly. + &[disabled], + &.disabled, + fieldset[disabled] & { + cursor: @cursor-disabled; + } } input[type="file"] { @@ -123,7 +144,7 @@ output { background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid @input-border; border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS. - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); // Customize the `:focus` state to imitate native WebKit styles. @@ -134,8 +155,8 @@ output { // Unstyle the caret on `<select>`s in IE10+. &::-ms-expand { - border: 0; background-color: transparent; + border: 0; } // Disabled and read-only inputs @@ -162,18 +183,6 @@ output { } -// Search inputs in iOS -// -// This overrides the extra rounded corners on search inputs in iOS so that our -// `.form-control` class can properly style them. Note that this cannot simply -// be added to `.form-control` as it's not specific enough. For details, see -// https://github.com/twbs/bootstrap/issues/11586. - -input[type="search"] { - -webkit-appearance: none; -} - - // Special styles for iOS temporal inputs // // In Mobile Safari, setting `display: block` on temporal inputs causes the @@ -226,11 +235,19 @@ input[type="search"] { margin-top: 10px; margin-bottom: 10px; + // These are used on elements with <label> descendants + &.disabled, + fieldset[disabled] & { + label { + cursor: @cursor-disabled; + } + } + label { min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text padding-left: 20px; margin-bottom: 0; - font-weight: normal; + font-weight: 400; cursor: pointer; } } @@ -239,8 +256,8 @@ input[type="search"] { .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { position: absolute; - margin-left: -20px; margin-top: 4px \9; + margin-left: -20px; } .radio + .radio, @@ -255,45 +272,20 @@ input[type="search"] { display: inline-block; padding-left: 20px; margin-bottom: 0; + font-weight: 400; vertical-align: middle; - font-weight: normal; cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; // space out consecutive inline controls -} -// Apply same disabled cursor tweak as for inputs -// Some special care is needed because <label>s don't inherit their parent's `cursor`. -// -// Note: Neither radios nor checkboxes can be readonly. -input[type="radio"], -input[type="checkbox"] { - &[disabled], + // These are used directly on <label>s &.disabled, fieldset[disabled] & { cursor: @cursor-disabled; } } -// These classes are used directly on <label>s -.radio-inline, -.checkbox-inline { - &.disabled, - fieldset[disabled] & { - cursor: @cursor-disabled; - } -} -// These classes are used on elements with <label> descendants -.radio, -.checkbox { - &.disabled, - fieldset[disabled] & { - label { - cursor: @cursor-disabled; - } - } +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; // space out consecutive inline controls } @@ -303,17 +295,17 @@ input[type="checkbox"] { // a horizontal form layout. .form-control-static { + min-height: (@line-height-computed + @font-size-base); // Size it appropriately next to real form controls padding-top: (@padding-base-vertical + 1); padding-bottom: (@padding-base-vertical + 1); // Remove default margin from `p` margin-bottom: 0; - min-height: (@line-height-computed + @font-size-base); &.input-lg, &.input-sm { - padding-left: 0; padding-right: 0; + padding-left: 0; } } @@ -556,9 +548,9 @@ input[type="checkbox"] { .checkbox, .radio-inline, .checkbox-inline { + padding-top: (@padding-base-vertical + 1); // Default padding plus a border margin-top: 0; margin-bottom: 0; - padding-top: (@padding-base-vertical + 1); // Default padding plus a border } // Account for padding we're adding to ensure the alignment and of help text // and other content below items @@ -576,9 +568,9 @@ input[type="checkbox"] { // labels on narrow viewports stack the same as a default form example. @media (min-width: @screen-sm-min) { .control-label { - text-align: right; - margin-bottom: 0; padding-top: (@padding-base-vertical + 1); // Default padding plus a border + margin-bottom: 0; + text-align: right; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/glyphicons.less b/themes/bootstrap3/less/vendor/bootstrap/glyphicons.less index 7bc5852d2c07fa416d11001a136a759199628ab3..522d5041f7cb3b381af29381cac1b6fbac7a6bef 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/glyphicons.less +++ b/themes/bootstrap3/less/vendor/bootstrap/glyphicons.less @@ -1,3 +1,5 @@ +// stylelint-disable value-list-comma-newline-after, value-list-comma-space-after, indentation, declaration-colon-newline-after, font-family-no-missing-generic-family-keyword + // // Glyphicons for Bootstrap // @@ -9,13 +11,13 @@ // Import the fonts @font-face { - font-family: 'Glyphicons Halflings'; - src: url('@{icon-font-path}@{icon-font-name}.eot'); - src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'), - url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'), - url('@{icon-font-path}@{icon-font-name}.woff') format('woff'), - url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'), - url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg'); + font-family: "Glyphicons Halflings"; + src: url("@{icon-font-path}@{icon-font-name}.eot"); + src: url("@{icon-font-path}@{icon-font-name}.eot?#iefix") format("embedded-opentype"), + url("@{icon-font-path}@{icon-font-name}.woff2") format("woff2"), + url("@{icon-font-path}@{icon-font-name}.woff") format("woff"), + url("@{icon-font-path}@{icon-font-name}.ttf") format("truetype"), + url("@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}") format("svg"); } // Catchall baseclass @@ -23,9 +25,9 @@ position: relative; top: 1px; display: inline-block; - font-family: 'Glyphicons Halflings'; + font-family: "Glyphicons Halflings"; font-style: normal; - font-weight: normal; + font-weight: 400; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/themes/bootstrap3/less/vendor/bootstrap/grid.less b/themes/bootstrap3/less/vendor/bootstrap/grid.less index e100655b70e38480e2029a7c945e5984d15c9784..574f462f51b1e4c65c372586dde9af669696e821 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/grid.less +++ b/themes/bootstrap3/less/vendor/bootstrap/grid.less @@ -40,6 +40,16 @@ .make-row(); } +.row-no-gutters { + margin-right: 0; + margin-left: 0; + + [class*="col-"] { + padding-right: 0; + padding-left: 0; + } +} + // Columns // diff --git a/themes/bootstrap3/less/vendor/bootstrap/input-groups.less b/themes/bootstrap3/less/vendor/bootstrap/input-groups.less index d0763db7fff5db46e0d3cf92e454f126d3c0c663..92b67da5c5e02810957d988492ef41ab818d96e7 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/input-groups.less +++ b/themes/bootstrap3/less/vendor/bootstrap/input-groups.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type + // // Input groups // -------------------------------------------------- @@ -12,8 +14,8 @@ // Undo padding and float of grid classes &[class*="col-"] { float: none; - padding-left: 0; padding-right: 0; + padding-left: 0; } .form-control { @@ -77,7 +79,7 @@ .input-group-addon { padding: @padding-base-vertical @padding-base-horizontal; font-size: @font-size-base; - font-weight: normal; + font-weight: 400; line-height: 1; color: @input-color; text-align: center; diff --git a/themes/bootstrap3/less/vendor/bootstrap/jumbotron.less b/themes/bootstrap3/less/vendor/bootstrap/jumbotron.less index 1d9b515b3861970b64adbcf07b17453257829997..cdf96baed608c287ab1319e0bdbce167ef771dbc 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/jumbotron.less +++ b/themes/bootstrap3/less/vendor/bootstrap/jumbotron.less @@ -4,7 +4,7 @@ .jumbotron { - padding-top: @jumbotron-padding; + padding-top: @jumbotron-padding; padding-bottom: @jumbotron-padding; margin-bottom: @jumbotron-padding; color: @jumbotron-color; @@ -27,9 +27,9 @@ .container &, .container-fluid & { - border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container - padding-left: (@grid-gutter-width / 2); padding-right: (@grid-gutter-width / 2); + padding-left: (@grid-gutter-width / 2); + border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container } .container { @@ -37,13 +37,13 @@ } @media screen and (min-width: @screen-sm-min) { - padding-top: (@jumbotron-padding * 1.6); + padding-top: (@jumbotron-padding * 1.6); padding-bottom: (@jumbotron-padding * 1.6); .container &, .container-fluid & { - padding-left: (@jumbotron-padding * 2); padding-right: (@jumbotron-padding * 2); + padding-left: (@jumbotron-padding * 2); } h1, diff --git a/themes/bootstrap3/less/vendor/bootstrap/labels.less b/themes/bootstrap3/less/vendor/bootstrap/labels.less index 9a5a27006a51f4ac0d350cf11060aa548cd6ef6b..cf0d48df3c1f4394a25dbe6cec0899e0f17a6d10 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/labels.less +++ b/themes/bootstrap3/less/vendor/bootstrap/labels.less @@ -6,7 +6,7 @@ display: inline; padding: .2em .6em .3em; font-size: 75%; - font-weight: bold; + font-weight: 700; line-height: 1; color: @label-color; text-align: center; diff --git a/themes/bootstrap3/less/vendor/bootstrap/list-group.less b/themes/bootstrap3/less/vendor/bootstrap/list-group.less index 216b91230ab6fa786b0a8d53bc2e60004baec147..f913629ccede9acf02068dd5f4ef4b12f4a62622 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/list-group.less +++ b/themes/bootstrap3/less/vendor/bootstrap/list-group.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type + // // List groups // -------------------------------------------------- @@ -9,8 +11,8 @@ .list-group { // No need to set list-style: none; since .list-group-item is block level - margin-bottom: 20px; padding-left: 0; // reset padding because ul and ol + margin-bottom: 20px; } @@ -35,44 +37,14 @@ margin-bottom: 0; .border-bottom-radius(@list-group-border-radius); } -} - - -// Interactive list items -// -// Use anchor or button elements instead of `li`s or `div`s to create interactive items. -// Includes an extra `.active` modifier class for showing selected items. - -a.list-group-item, -button.list-group-item { - color: @list-group-link-color; - - .list-group-item-heading { - color: @list-group-link-heading-color; - } - - // Hover state - &:hover, - &:focus { - text-decoration: none; - color: @list-group-link-hover-color; - background-color: @list-group-hover-bg; - } -} - -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item { // Disabled state &.disabled, &.disabled:hover, &.disabled:focus { - background-color: @list-group-disabled-bg; color: @list-group-disabled-color; cursor: @cursor-disabled; + background-color: @list-group-disabled-bg; // Force color to inherit for custom content .list-group-item-heading { @@ -105,6 +77,34 @@ button.list-group-item { } +// Interactive list items +// +// Use anchor or button elements instead of `li`s or `div`s to create interactive items. +// Includes an extra `.active` modifier class for showing selected items. + +a.list-group-item, +button.list-group-item { + color: @list-group-link-color; + + .list-group-item-heading { + color: @list-group-link-heading-color; + } + + // Hover state + &:hover, + &:focus { + color: @list-group-link-hover-color; + text-decoration: none; + background-color: @list-group-hover-bg; + } +} + +button.list-group-item { + width: 100%; + text-align: left; +} + + // Contextual variants // // Add modifier classes to change text and background color on individual items. diff --git a/themes/bootstrap3/less/vendor/bootstrap/media.less b/themes/bootstrap3/less/vendor/bootstrap/media.less index 8c835e861edf28f7c3c49f18caf09d626565e11d..e4ae44573e94448ab26984d10b0a273a7fc0ee17 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/media.less +++ b/themes/bootstrap3/less/vendor/bootstrap/media.less @@ -9,8 +9,8 @@ .media, .media-body { - zoom: 1; overflow: hidden; + zoom: 1; } .media-body { diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/alerts.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/alerts.less index 396196f438fd31e7757a0874ece4a99fe0cf9fd9..b27cc5d27be58df28c32dcc819d17a86bbae428c 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/alerts.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/alerts.less @@ -1,13 +1,14 @@ // Alerts .alert-variant(@background; @border; @text-color) { + color: @text-color; background-color: @background; border-color: @border; - color: @text-color; hr { border-top-color: darken(@border, 5%); } + .alert-link { color: darken(@text-color, 10%); } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/border-radius.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/border-radius.less index ca05dbf457000d122a3b8afcc3847e44cffea421..da7ea10e556641ed77a5ef90022fa7ef3cf26af8 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/border-radius.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/border-radius.less @@ -1,18 +1,18 @@ // Single side border-radius .border-top-radius(@radius) { + border-top-left-radius: @radius; border-top-right-radius: @radius; - border-top-left-radius: @radius; } .border-right-radius(@radius) { + border-top-right-radius: @radius; border-bottom-right-radius: @radius; - border-top-right-radius: @radius; } .border-bottom-radius(@radius) { border-bottom-right-radius: @radius; - border-bottom-left-radius: @radius; + border-bottom-left-radius: @radius; } .border-left-radius(@radius) { + border-top-left-radius: @radius; border-bottom-left-radius: @radius; - border-top-left-radius: @radius; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/buttons.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/buttons.less index b294d8c210e07ad3e1293863c3ab0c8a45c960c7..42d3c512ab9dff433eaa1a31a4e05edae06cfd4e 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/buttons.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/buttons.less @@ -12,33 +12,29 @@ &.focus { color: @color; background-color: darken(@background, 10%); - border-color: darken(@border, 25%); + border-color: darken(@border, 25%); } &:hover { color: @color; background-color: darken(@background, 10%); - border-color: darken(@border, 12%); + border-color: darken(@border, 12%); } &:active, &.active, .open > .dropdown-toggle& { color: @color; background-color: darken(@background, 10%); - border-color: darken(@border, 12%); + background-image: none; + border-color: darken(@border, 12%); &:hover, &:focus, &.focus { color: @color; background-color: darken(@background, 17%); - border-color: darken(@border, 25%); + border-color: darken(@border, 25%); } } - &:active, - &.active, - .open > .dropdown-toggle& { - background-image: none; - } &.disabled, &[disabled], fieldset[disabled] & { @@ -46,7 +42,7 @@ &:focus, &.focus { background-color: @background; - border-color: @border; + border-color: @border; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/center-block.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/center-block.less index d18d6de9ed6a7af49415277cb72e57b7dbd42d0f..627cfa3895942001381df70e14df9b7dbada7318 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/center-block.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/center-block.less @@ -2,6 +2,6 @@ .center-block() { display: block; - margin-left: auto; margin-right: auto; + margin-left: auto; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/clearfix.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/clearfix.less index 3f7a3820c1cf7756322917982646352e77119f46..f60fcf1625a8d0358e304b07133a2c6e508ad85b 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/clearfix.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/clearfix.less @@ -13,8 +13,8 @@ .clearfix() { &:before, &:after { - content: " "; // 1 display: table; // 2 + content: " "; // 1 } &:after { clear: both; diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/forms.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/forms.less index 6f55ed967082caf4ef515f88c9d591f95036a470..173dc99a0c5b4820acd9cedb2595b646391d01aa 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/forms.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/forms.less @@ -20,18 +20,18 @@ // Set the border and box shadow on specific inputs to match .form-control { border-color: @border-color; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work + .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); // Redeclare so transitions work &:focus { border-color: darken(@border-color, 10%); - @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%); + @shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px lighten(@border-color, 20%); .box-shadow(@shadow); } } // Set validation states also for addons .input-group-addon { color: @text-color; - border-color: @border-color; background-color: @background-color; + border-color: @border-color; } // Optional feedback icon .form-control-feedback { @@ -57,7 +57,7 @@ &:focus { border-color: @color; outline: 0; - .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); + .box-shadow(~"inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px @{color-rgba}"); } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/gradients.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/gradients.less index 0b88a89cc56a63effe45558845122b077de03979..b36f59165d35d07eaa0c25585fd0bb7c0cd089ea 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/gradients.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/gradients.less @@ -1,4 +1,4 @@ -// Gradients +// stylelint-disable value-no-vendor-prefix, selector-max-id #gradient { @@ -10,8 +10,8 @@ background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12 background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)", argb(@start-color), argb(@end-color))); // IE9 and down background-repeat: repeat-x; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down } // Vertical gradient, from top to bottom @@ -22,36 +22,36 @@ background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12 background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)", argb(@start-color), argb(@end-color))); // IE9 and down background-repeat: repeat-x; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down } .directional(@start-color: #555; @end-color: #333; @deg: 45deg) { - background-repeat: repeat-x; background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12 background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + background-repeat: repeat-x; } .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color); + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback background-repeat: no-repeat; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback } .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color); background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color); background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color); + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback background-repeat: no-repeat; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback } .radial(@inner-color: #555; @outer-color: #333) { background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color); background-image: radial-gradient(circle, @inner-color, @outer-color); background-repeat: no-repeat; } - .striped(@color: rgba(255,255,255,.15); @angle: 45deg) { + .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) { background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/grid-framework.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/grid-framework.less index 8c23eed24e60e5fca7d991d2de47019892530323..0c73c88b9ca23184f5e735d3b5632afddebdf9ac 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/grid-framework.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/grid-framework.less @@ -19,8 +19,8 @@ // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding - padding-left: ceil((@grid-gutter-width / 2)); padding-right: floor((@grid-gutter-width / 2)); + padding-left: ceil((@grid-gutter-width / 2)); } } .col(1); // kickstart it diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/grid.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/grid.less index df496d0b3c1a96f60ad996870bba4fd2cf388d33..a9554a42076a71f062e260bb79c95554bd354936 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/grid.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/grid.less @@ -4,17 +4,17 @@ // Centered container element .container-fixed(@gutter: @grid-gutter-width) { + padding-right: ceil((@gutter / 2)); + padding-left: floor((@gutter / 2)); margin-right: auto; margin-left: auto; - padding-left: floor((@gutter / 2)); - padding-right: ceil((@gutter / 2)); &:extend(.clearfix all); } // Creates a wrapper for a series of columns .make-row(@gutter: @grid-gutter-width) { - margin-left: ceil((@gutter / -2)); margin-right: floor((@gutter / -2)); + margin-left: ceil((@gutter / -2)); &:extend(.clearfix all); } @@ -24,8 +24,8 @@ float: left; width: percentage((@columns / @grid-columns)); min-height: 1px; - padding-left: (@gutter / 2); padding-right: (@gutter / 2); + padding-left: (@gutter / 2); } .make-xs-column-offset(@columns) { margin-left: percentage((@columns / @grid-columns)); @@ -41,8 +41,8 @@ .make-sm-column(@columns; @gutter: @grid-gutter-width) { position: relative; min-height: 1px; - padding-left: (@gutter / 2); padding-right: (@gutter / 2); + padding-left: (@gutter / 2); @media (min-width: @screen-sm-min) { float: left; @@ -69,8 +69,8 @@ .make-md-column(@columns; @gutter: @grid-gutter-width) { position: relative; min-height: 1px; - padding-left: (@gutter / 2); padding-right: (@gutter / 2); + padding-left: (@gutter / 2); @media (min-width: @screen-md-min) { float: left; @@ -97,8 +97,8 @@ .make-lg-column(@columns; @gutter: @grid-gutter-width) { position: relative; min-height: 1px; - padding-left: (@gutter / 2); padding-right: (@gutter / 2); + padding-left: (@gutter / 2); @media (min-width: @screen-lg-min) { float: left; diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/hide-text.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/hide-text.less index 2bb84a3b444fc158cd24ef77789c624d989fa8ed..9b21a105641bda8bcf33342443b41a38c55a9f9d 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/hide-text.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/hide-text.less @@ -1,3 +1,5 @@ +// stylelint-disable font-family-name-quotes, font-family-no-missing-generic-family-keyword + // CSS image replacement // // Heads up! v3 launched with only `.hide-text()`, but per our pattern for diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/image.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/image.less index f233cb3e199f21ac194212e10ebb1e12feb0682b..f0dde6be705a4a0e4012d8f61c8694bb829c3cbc 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/image.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/image.less @@ -1,7 +1,4 @@ -// Image Mixins -// - Responsive image -// - Retina image - +// stylelint-disable media-feature-name-no-vendor-prefix, media-feature-parentheses-space-inside, media-feature-name-no-unknown, indentation, at-rule-name-space-after // Responsive image // @@ -22,11 +19,11 @@ @media only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and ( min--moz-device-pixel-ratio: 2), - only screen and ( -o-min-device-pixel-ratio: 2/1), - only screen and ( min-device-pixel-ratio: 2), - only screen and ( min-resolution: 192dpi), - only screen and ( min-resolution: 2dppx) { + only screen and ( min--moz-device-pixel-ratio: 2), + only screen and ( -o-min-device-pixel-ratio: 2/1), + only screen and ( min-device-pixel-ratio: 2), + only screen and ( min-resolution: 192dpi), + only screen and ( min-resolution: 2dppx) { background-image: url("@{file-2x}"); background-size: @width-1x @height-1x; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/opacity.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/opacity.less index 33ed25ce6763de7f8ae195628c1eb168379d8435..32cf411fcd3b720e153e0f58947b324e83f6d2b6 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/opacity.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/opacity.less @@ -1,8 +1,7 @@ // Opacity .opacity(@opacity) { - opacity: @opacity; - // IE8 filter - @opacity-ie: (@opacity * 100); + @opacity-ie: (@opacity * 100); // IE8 filter filter: ~"alpha(opacity=@{opacity-ie})"; + opacity: @opacity; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/reset-text.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/reset-text.less index 58dd4d19b4d1f6c6731ae2dadd512eb62d9e7e81..a8754bd15655f572370ac279297d1490af30379e 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/reset-text.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/reset-text.less @@ -2,17 +2,17 @@ font-family: @font-family-base; // We deliberately do NOT reset font-size. font-style: normal; - font-weight: normal; - letter-spacing: normal; - line-break: auto; + font-weight: 400; line-height: @line-height-base; + line-break: auto; text-align: left; // Fallback for where `start` is not supported text-align: start; text-decoration: none; text-shadow: none; text-transform: none; - white-space: normal; + letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; + white-space: normal; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/resize.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/resize.less index 3acd3afdbacbb7f642e04f7ff434c18107faad69..c8513289a01f387175fd439a9baed0f76bad6fca 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/resize.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/resize.less @@ -1,6 +1,6 @@ // Resize anything .resizable(@direction) { - resize: @direction; // Options: horizontal, vertical, both overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` + resize: @direction; // Options: horizontal, vertical, both } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/responsive-visibility.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/responsive-visibility.less index ecf1e979fd25c27674d75e1ec6089ee53549dea5..74d67289d454b86840cfe8fbdb83d3235c28bf47 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/responsive-visibility.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/responsive-visibility.less @@ -1,7 +1,5 @@ -// Responsive utilities +// stylelint-disable declaration-no-important -// -// More easily include all the states for responsive-utilities.less. .responsive-visibility() { display: block !important; table& { display: table !important; } diff --git a/themes/bootstrap3/less/vendor/bootstrap/mixins/vendor-prefixes.less b/themes/bootstrap3/less/vendor/bootstrap/mixins/vendor-prefixes.less index 2b5e74b99ed685f4d5e780a9694b9903a59f257b..fd0a9972d6b1561675fc03f960c945bc718b7115 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/mixins/vendor-prefixes.less +++ b/themes/bootstrap3/less/vendor/bootstrap/mixins/vendor-prefixes.less @@ -1,3 +1,5 @@ +// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix + // Vendor Prefixes // // All vendor mixins are deprecated as of v3.2.0 due to the introduction of @@ -89,12 +91,12 @@ // Optional hyphenation .hyphens(@mode: auto) { - word-wrap: break-word; -webkit-hyphens: @mode; -moz-hyphens: @mode; -ms-hyphens: @mode; // IE10+ -o-hyphens: @mode; hyphens: @mode; + word-wrap: break-word; } // Placeholder text diff --git a/themes/bootstrap3/less/vendor/bootstrap/modals.less b/themes/bootstrap3/less/vendor/bootstrap/modals.less index 767ce36ba3763df166963a2e7e330c19f3b708b3..0e516e51af3d07ba0eb2ab82bcf91ace779092fa 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/modals.less +++ b/themes/bootstrap3/less/vendor/bootstrap/modals.less @@ -14,14 +14,14 @@ // Container that the modal scrolls within .modal { - display: none; - overflow: hidden; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: @zindex-modal; + display: none; + overflow: hidden; -webkit-overflow-scrolling: touch; // Prevent Chrome on Windows from adding a focus outline. For details, see @@ -51,11 +51,11 @@ .modal-content { position: relative; background-color: @modal-content-bg; + background-clip: padding-box; border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc) border: 1px solid @modal-content-border-color; border-radius: @border-radius-large; - .box-shadow(0 3px 9px rgba(0,0,0,.5)); - background-clip: padding-box; + .box-shadow(0 3px 9px rgba(0, 0, 0, .5)); // Remove focus outline from opened modal outline: 0; } @@ -108,8 +108,8 @@ // Properly space out buttons .btn + .btn { - margin-left: 5px; margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs + margin-left: 5px; } // but override that for button groups .btn-group .btn + .btn { @@ -138,7 +138,7 @@ margin: 30px auto; } .modal-content { - .box-shadow(0 5px 15px rgba(0,0,0,.5)); + .box-shadow(0 5px 15px rgba(0, 0, 0, .5)); } // Modal sizes diff --git a/themes/bootstrap3/less/vendor/bootstrap/navbar.less b/themes/bootstrap3/less/vendor/bootstrap/navbar.less index 6d751bb9ce0adfe6aac21bc69fbb9aa43880eae0..da95e37a30db21c70749f2ccc878c856d5c34ac2 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/navbar.less +++ b/themes/bootstrap3/less/vendor/bootstrap/navbar.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-max-combinators, selector-max-class, declaration-no-important, selector-no-qualifying-type + // // Navbars // -------------------------------------------------- @@ -48,11 +50,11 @@ // content for the user's viewport. .navbar-collapse { - overflow-x: visible; padding-right: @navbar-padding-horizontal; - padding-left: @navbar-padding-horizontal; + padding-left: @navbar-padding-horizontal; + overflow-x: visible; border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255,255,255,.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); &:extend(.clearfix all); -webkit-overflow-scrolling: touch; @@ -81,8 +83,8 @@ .navbar-fixed-top &, .navbar-static-top &, .navbar-fixed-bottom & { - padding-left: 0; padding-right: 0; + padding-left: 0; } } } @@ -96,6 +98,27 @@ max-height: 200px; } } + + // Fix the top/bottom navbars when screen real estate supports it + position: fixed; + right: 0; + left: 0; + z-index: @zindex-navbar-fixed; + + // Undo the rounded corners + @media (min-width: @grid-float-breakpoint) { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; // override .navbar defaults + border-width: 1px 0 0; } @@ -108,11 +131,11 @@ > .navbar-header, > .navbar-collapse { margin-right: -@navbar-padding-horizontal; - margin-left: -@navbar-padding-horizontal; + margin-left: -@navbar-padding-horizontal; @media (min-width: @grid-float-breakpoint) { margin-right: 0; - margin-left: 0; + margin-left: 0; } } } @@ -134,38 +157,15 @@ } } -// Fix the top/bottom navbars when screen real estate supports it -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: @zindex-navbar-fixed; - - // Undo the rounded corners - @media (min-width: @grid-float-breakpoint) { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; // override .navbar defaults - border-width: 1px 0 0; -} - // Brand/project name .navbar-brand { float: left; + height: @navbar-height; padding: @navbar-padding-vertical @navbar-padding-horizontal; font-size: @font-size-large; line-height: @line-height-computed; - height: @navbar-height; &:hover, &:focus { @@ -193,8 +193,8 @@ .navbar-toggle { position: relative; float: right; - margin-right: @navbar-padding-horizontal; padding: 9px 10px; + margin-right: @navbar-padding-horizontal; .navbar-vertical-align(34px); background-color: transparent; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 @@ -233,7 +233,7 @@ margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal; > li > a { - padding-top: 10px; + padding-top: 10px; padding-bottom: 10px; line-height: @line-height-computed; } @@ -270,7 +270,7 @@ > li { float: left; > a { - padding-top: @navbar-padding-vertical; + padding-top: @navbar-padding-vertical; padding-bottom: @navbar-padding-vertical; } } @@ -284,12 +284,12 @@ // our navbars. .navbar-form { - margin-left: -@navbar-padding-horizontal; - margin-right: -@navbar-padding-horizontal; padding: 10px @navbar-padding-horizontal; + margin-right: -@navbar-padding-horizontal; + margin-left: -@navbar-padding-horizontal; border-top: 1px solid transparent; border-bottom: 1px solid transparent; - @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); + @shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); .box-shadow(@shadow); // Mixin behavior for optimum display @@ -311,11 +311,11 @@ // Undo 100% width for pull classes @media (min-width: @grid-float-breakpoint) { width: auto; - border: 0; - margin-left: 0; - margin-right: 0; padding-top: 0; padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; .box-shadow(none); } } @@ -361,8 +361,8 @@ @media (min-width: @grid-float-breakpoint) { float: left; - margin-left: @navbar-padding-horizontal; margin-right: @navbar-padding-horizontal; + margin-left: @navbar-padding-horizontal; } } @@ -435,33 +435,15 @@ background-color: @navbar-default-link-disabled-bg; } } - } - .navbar-toggle { - border-color: @navbar-default-toggle-border-color; - &:hover, - &:focus { - background-color: @navbar-default-toggle-hover-bg; - } - .icon-bar { - background-color: @navbar-default-toggle-icon-bar-bg; - } - } - - .navbar-collapse, - .navbar-form { - border-color: @navbar-default-border; - } - - // Dropdown menu items - .navbar-nav { + // Dropdown menu items // Remove background color from open dropdown > .open > a { &, &:hover, &:focus { - background-color: @navbar-default-link-active-bg; color: @navbar-default-link-active-color; + background-color: @navbar-default-link-active-bg; } } @@ -496,6 +478,22 @@ } } + .navbar-toggle { + border-color: @navbar-default-toggle-border-color; + &:hover, + &:focus { + background-color: @navbar-default-toggle-hover-bg; + } + .icon-bar { + background-color: @navbar-default-toggle-icon-bar-bg; + } + } + + .navbar-collapse, + .navbar-form { + border-color: @navbar-default-border; + } + // Links in navbars // @@ -569,33 +567,14 @@ background-color: @navbar-inverse-link-disabled-bg; } } - } - - // Darken the responsive nav toggle - .navbar-toggle { - border-color: @navbar-inverse-toggle-border-color; - &:hover, - &:focus { - background-color: @navbar-inverse-toggle-hover-bg; - } - .icon-bar { - background-color: @navbar-inverse-toggle-icon-bar-bg; - } - } - .navbar-collapse, - .navbar-form { - border-color: darken(@navbar-inverse-bg, 7%); - } - - // Dropdowns - .navbar-nav { + // Dropdowns > .open > a { &, &:hover, &:focus { - background-color: @navbar-inverse-link-active-bg; color: @navbar-inverse-link-active-color; + background-color: @navbar-inverse-link-active-bg; } } @@ -636,6 +615,23 @@ } } + // Darken the responsive nav toggle + .navbar-toggle { + border-color: @navbar-inverse-toggle-border-color; + &:hover, + &:focus { + background-color: @navbar-inverse-toggle-hover-bg; + } + .icon-bar { + background-color: @navbar-inverse-toggle-icon-bar-bg; + } + } + + .navbar-collapse, + .navbar-form { + border-color: darken(@navbar-inverse-bg, 7%); + } + .navbar-link { color: @navbar-inverse-link-color; &:hover { diff --git a/themes/bootstrap3/less/vendor/bootstrap/navs.less b/themes/bootstrap3/less/vendor/bootstrap/navs.less index a3d11b136211f3ee4a4d3beeb19c5ffba203b15b..45df13ebe4746a61314fdffe22486ea6da0cd24b 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/navs.less +++ b/themes/bootstrap3/less/vendor/bootstrap/navs.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type, selector-max-type + // // Navs // -------------------------------------------------- @@ -7,8 +9,8 @@ // -------------------------------------------------- .nav { - margin-bottom: 0; padding-left: 0; // Override default ul/ol + margin-bottom: 0; list-style: none; &:extend(.clearfix all); @@ -35,8 +37,8 @@ &:focus { color: @nav-disabled-link-hover-color; text-decoration: none; - background-color: transparent; cursor: @cursor-disabled; + background-color: transparent; } } } @@ -97,10 +99,10 @@ &:hover, &:focus { color: @nav-tabs-active-link-hover-color; + cursor: default; background-color: @nav-tabs-active-link-hover-bg; border: 1px solid @nav-tabs-active-link-hover-border-color; border-bottom-color: transparent; - cursor: default; } } } @@ -163,8 +165,8 @@ > li { float: none; > a { - text-align: center; margin-bottom: 5px; + text-align: center; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/normalize.less b/themes/bootstrap3/less/vendor/bootstrap/normalize.less index 9dddf73ad2924561afa704701655f2cbc011d7df..68f9c21447bcdd28bbc70cb4c2c1e23edd19deb9 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/normalize.less +++ b/themes/bootstrap3/less/vendor/bootstrap/normalize.less @@ -1,3 +1,5 @@ +// stylelint-disable + /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ // @@ -104,11 +106,14 @@ a:hover { // ========================================================================== // -// Address styling not present in IE 8/9/10/11, Safari, and Chrome. +// 1. Remove the bottom border in Chrome 57- and Firefox 39-. +// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. // abbr[title] { - border-bottom: 1px dotted; + border-bottom: none; // 1 + text-decoration: underline; // 2 + text-decoration: underline dotted; // 2 } // diff --git a/themes/bootstrap3/less/vendor/bootstrap/pager.less b/themes/bootstrap3/less/vendor/bootstrap/pager.less index 41abaaadc5dc605c75de869dab943599ef31fbbd..e77ba550958a2e63242d9b53a6814570c2e2759f 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/pager.less +++ b/themes/bootstrap3/less/vendor/bootstrap/pager.less @@ -6,8 +6,8 @@ .pager { padding-left: 0; margin: @line-height-computed 0; - list-style: none; text-align: center; + list-style: none; &:extend(.clearfix all); li { display: inline; @@ -47,8 +47,8 @@ > a:focus, > span { color: @pager-disabled-color; - background-color: @pager-bg; cursor: @cursor-disabled; + background-color: @pager-bg; } } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/pagination.less b/themes/bootstrap3/less/vendor/bootstrap/pagination.less index 31f77aae4ed7bff3bfaac4f3acf393cfb24ad149..23b67cb263d7fdebe501e8237f1544e9ffc880b3 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/pagination.less +++ b/themes/bootstrap3/less/vendor/bootstrap/pagination.less @@ -14,12 +14,20 @@ position: relative; float: left; // Collapse white-space padding: @padding-base-vertical @padding-base-horizontal; + margin-left: -1px; line-height: @line-height-base; - text-decoration: none; color: @pagination-color; + text-decoration: none; background-color: @pagination-bg; border: 1px solid @pagination-border; - margin-left: -1px; + + &:hover, + &:focus { + z-index: 2; + color: @pagination-hover-color; + background-color: @pagination-hover-bg; + border-color: @pagination-hover-border; + } } &:first-child { > a, @@ -36,17 +44,6 @@ } } - > li > a, - > li > span { - &:hover, - &:focus { - z-index: 2; - color: @pagination-hover-color; - background-color: @pagination-hover-bg; - border-color: @pagination-hover-border; - } - } - > .active > a, > .active > span { &, @@ -54,9 +51,9 @@ &:focus { z-index: 3; color: @pagination-active-color; + cursor: default; background-color: @pagination-active-bg; border-color: @pagination-active-border; - cursor: default; } } @@ -68,9 +65,9 @@ > a:hover, > a:focus { color: @pagination-disabled-color; + cursor: @cursor-disabled; background-color: @pagination-disabled-bg; border-color: @pagination-disabled-border; - cursor: @cursor-disabled; } } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/panels.less b/themes/bootstrap3/less/vendor/bootstrap/panels.less index 65aa3a83f34356b0cee5f2bdd61afa976172ea22..f230a84a074000b719768e2ce3fd93a8531a3056 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/panels.less +++ b/themes/bootstrap3/less/vendor/bootstrap/panels.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-max-combinators, no-duplicate-selectors + // // Panels // -------------------------------------------------- @@ -9,7 +11,7 @@ background-color: @panel-bg; border: 1px solid transparent; border-radius: @panel-border-radius; - .box-shadow(0 1px 1px rgba(0,0,0,.05)); + .box-shadow(0 1px 1px rgba(0, 0, 0, .05)); } // Panel contents @@ -113,8 +115,8 @@ margin-bottom: 0; caption { - padding-left: @panel-body-padding; padding-right: @panel-body-padding; + padding-left: @panel-body-padding; } } // Add border top radius for first one @@ -147,8 +149,8 @@ > tbody:last-child, > tfoot:last-child { > tr:last-child { - border-bottom-left-radius: (@panel-border-radius - 1); border-bottom-right-radius: (@panel-border-radius - 1); + border-bottom-left-radius: (@panel-border-radius - 1); td:first-child, th:first-child { @@ -208,8 +210,8 @@ } } > .table-responsive { - border: 0; margin-bottom: 0; + border: 0; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/popovers.less b/themes/bootstrap3/less/vendor/bootstrap/popovers.less index 3a62a6455ac11c91fc20d63db2f49b9a7d872c15..3920eb5b0a6ffebfd2b4f9396cf8018c5c7338de 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/popovers.less +++ b/themes/bootstrap3/less/vendor/bootstrap/popovers.less @@ -15,99 +15,81 @@ // So reset our font and text properties to avoid inheriting weird values. .reset-text(); font-size: @font-size-base; - background-color: @popover-bg; background-clip: padding-box; border: 1px solid @popover-fallback-border-color; border: 1px solid @popover-border-color; border-radius: @border-radius-large; - .box-shadow(0 5px 10px rgba(0,0,0,.2)); + .box-shadow(0 5px 10px rgba(0, 0, 0, .2)); // Offset the popover to account for the popover arrow - &.top { margin-top: -@popover-arrow-width; } - &.right { margin-left: @popover-arrow-width; } - &.bottom { margin-top: @popover-arrow-width; } - &.left { margin-left: -@popover-arrow-width; } -} + &.top { margin-top: -@popover-arrow-width; } + &.right { margin-left: @popover-arrow-width; } + &.bottom { margin-top: @popover-arrow-width; } + &.left { margin-left: -@popover-arrow-width; } -.popover-title { - margin: 0; // reset heading margin - padding: 8px 14px; - font-size: @font-size-base; - background-color: @popover-title-bg; - border-bottom: 1px solid darken(@popover-title-bg, 5%); - border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0; -} + // Arrows + // .arrow is outer, .arrow:after is inner + > .arrow { + border-width: @popover-arrow-outer-width; -.popover-content { - padding: 9px 14px; -} - -// Arrows -// -// .arrow is outer, .arrow:after is inner + &, + &:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + } -.popover > .arrow { - &, - &:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + &:after { + content: ""; + border-width: @popover-arrow-width; + } } -} -.popover > .arrow { - border-width: @popover-arrow-outer-width; -} -.popover > .arrow:after { - border-width: @popover-arrow-width; - content: ""; -} -.popover { &.top > .arrow { + bottom: -@popover-arrow-outer-width; left: 50%; margin-left: -@popover-arrow-outer-width; - border-bottom-width: 0; border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback border-top-color: @popover-arrow-outer-color; - bottom: -@popover-arrow-outer-width; + border-bottom-width: 0; &:after { - content: " "; bottom: 1px; margin-left: -@popover-arrow-width; - border-bottom-width: 0; + content: " "; border-top-color: @popover-arrow-color; + border-bottom-width: 0; } } &.right > .arrow { top: 50%; left: -@popover-arrow-outer-width; margin-top: -@popover-arrow-outer-width; - border-left-width: 0; border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback border-right-color: @popover-arrow-outer-color; + border-left-width: 0; &:after { - content: " "; - left: 1px; bottom: -@popover-arrow-width; - border-left-width: 0; + left: 1px; + content: " "; border-right-color: @popover-arrow-color; + border-left-width: 0; } } &.bottom > .arrow { + top: -@popover-arrow-outer-width; left: 50%; margin-left: -@popover-arrow-outer-width; border-top-width: 0; border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback border-bottom-color: @popover-arrow-outer-color; - top: -@popover-arrow-outer-width; &:after { - content: " "; top: 1px; margin-left: -@popover-arrow-width; + content: " "; border-top-width: 0; border-bottom-color: @popover-arrow-color; } @@ -121,11 +103,24 @@ border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback border-left-color: @popover-arrow-outer-color; &:after { - content: " "; right: 1px; + bottom: -@popover-arrow-width; + content: " "; border-right-width: 0; border-left-color: @popover-arrow-color; - bottom: -@popover-arrow-width; } } } + +.popover-title { + padding: 8px 14px; + margin: 0; // reset heading margin + font-size: @font-size-base; + background-color: @popover-title-bg; + border-bottom: 1px solid darken(@popover-title-bg, 5%); + border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0; +} + +.popover-content { + padding: 9px 14px; +} diff --git a/themes/bootstrap3/less/vendor/bootstrap/print.less b/themes/bootstrap3/less/vendor/bootstrap/print.less index 66e54ab489ea278cab3ac847d59449b9bcea9020..80458c3683577251a263ffb7b37fdb8a3f81de35 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/print.less +++ b/themes/bootstrap3/less/vendor/bootstrap/print.less @@ -1,3 +1,5 @@ +// stylelint-disable declaration-no-important, selector-no-qualifying-type + /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ // ========================================================================== @@ -6,96 +8,94 @@ // ========================================================================== @media print { - *, - *:before, - *:after { - background: transparent !important; - color: #000 !important; // Black prints faster: h5bp.com/s - box-shadow: none !important; - text-shadow: none !important; - } - - a, - a:visited { - text-decoration: underline; - } - - a[href]:after { - content: " (" attr(href) ")"; - } - - abbr[title]:after { - content: " (" attr(title) ")"; - } - - // Don't show links that are fragment identifiers, - // or use the `javascript:` pseudo protocol - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - - thead { - display: table-header-group; // h5bp.com/t - } - - tr, - img { - page-break-inside: avoid; - } - - img { - max-width: 100% !important; - } - - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - - h2, - h3 { - page-break-after: avoid; - } - - // Bootstrap specific changes start - - // Bootstrap components - .navbar { - display: none; - } - .btn, - .dropup > .btn { - > .caret { - border-top-color: #000 !important; - } - } - .label { - border: 1px solid #000; - } - - .table { - border-collapse: collapse !important; - - td, - th { - background-color: #fff !important; - } - } - .table-bordered { - th, - td { - border: 1px solid #ddd !important; - } - } - - // Bootstrap specific changes end + *, + *:before, + *:after { + color: #000 !important; // Black prints faster: h5bp.com/s + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + // Don't show links that are fragment identifiers, + // or use the `javascript:` pseudo protocol + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; // h5bp.com/t + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + // Bootstrap specific changes start + + // Bootstrap components + .navbar { + display: none; + } + .btn, + .dropup > .btn { + > .caret { + border-top-color: #000 !important; + } + } + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + + td, + th { + background-color: #fff !important; + } + } + .table-bordered { + th, + td { + border: 1px solid #ddd !important; + } + } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/progress-bars.less b/themes/bootstrap3/less/vendor/bootstrap/progress-bars.less index 8868a1feef0f3a7a4b0fabe7548435bfeb481df2..c40ab153937d79f911cf3b406c956ecfc7a96a93 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/progress-bars.less +++ b/themes/bootstrap3/less/vendor/bootstrap/progress-bars.less @@ -1,3 +1,5 @@ +// stylelint-disable at-rule-no-vendor-prefix + // // Progress bars // -------------------------------------------------- @@ -24,12 +26,12 @@ // Outer container .progress { - overflow: hidden; height: @line-height-computed; margin-bottom: @line-height-computed; + overflow: hidden; background-color: @progress-bg; border-radius: @progress-border-radius; - .box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); + .box-shadow(inset 0 1px 2px rgba(0, 0, 0, .1)); } // Bar of progress @@ -42,7 +44,7 @@ color: @progress-bar-color; text-align: center; background-color: @progress-bar-bg; - .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); + .box-shadow(inset 0 -1px 0 rgba(0, 0, 0, .15)); .transition(width .6s ease); } diff --git a/themes/bootstrap3/less/vendor/bootstrap/responsive-embed.less b/themes/bootstrap3/less/vendor/bootstrap/responsive-embed.less index 080a5118fe9ab2af331e6b1444fff4be840ecc03..5a0e0b88608e76c693b8be84c507b99a6060a00a 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/responsive-embed.less +++ b/themes/bootstrap3/less/vendor/bootstrap/responsive-embed.less @@ -16,10 +16,10 @@ video { position: absolute; top: 0; - left: 0; bottom: 0; - height: 100%; + left: 0; width: 100%; + height: 100%; border: 0; } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/responsive-utilities.less b/themes/bootstrap3/less/vendor/bootstrap/responsive-utilities.less index b1db31d7bfc19a757d02fd773db765c4273549a1..5d7740ac20b1d5fd7e190c90b0ae5c386f6ce6cc 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/responsive-utilities.less +++ b/themes/bootstrap3/less/vendor/bootstrap/responsive-utilities.less @@ -1,3 +1,5 @@ +// stylelint-disable declaration-no-important, at-rule-no-vendor-prefix + // // Responsive: Utility classes // -------------------------------------------------- @@ -14,9 +16,9 @@ // For more information, see the following: // // Issue: https://github.com/twbs/bootstrap/issues/10497 -// Docs: http://getbootstrap.com/getting-started/#support-ie10-width -// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/ -// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ +// Docs: https://getbootstrap.com/docs/3.4/getting-started/#support-ie10-width +// Source: https://timkadlec.com/2013/01/windows-phone-8-and-device-width/ +// Source: https://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ @-ms-viewport { width: device-width; diff --git a/themes/bootstrap3/less/vendor/bootstrap/scaffolding.less b/themes/bootstrap3/less/vendor/bootstrap/scaffolding.less index 64a29c6a5e7f20920a7ab41baefdf342830be881..df91f07912bf1fc83366282e65a7f137b4092bef 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/scaffolding.less +++ b/themes/bootstrap3/less/vendor/bootstrap/scaffolding.less @@ -7,7 +7,7 @@ // // Heads up! This reset may cause conflicts with some third-party widgets. // For recommendations on resolving such conflicts, see -// http://getbootstrap.com/getting-started/#third-box-sizing +// https://getbootstrap.com/docs/3.4/getting-started/#third-box-sizing * { .box-sizing(border-box); } @@ -21,7 +21,7 @@ html { font-size: 10px; - -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { @@ -111,7 +111,7 @@ img { // Horizontal rules hr { - margin-top: @line-height-computed; + margin-top: @line-height-computed; margin-bottom: @line-height-computed; border: 0; border-top: 1px solid @hr-border; @@ -120,21 +120,21 @@ hr { // Only display content to screen readers // -// See: http://a11yproject.com/posts/how-to-hide-content +// See: https://a11yproject.com/posts/how-to-hide-content .sr-only { position: absolute; width: 1px; height: 1px; - margin: -1px; padding: 0; + margin: -1px; overflow: hidden; - clip: rect(0,0,0,0); + clip: rect(0, 0, 0, 0); border: 0; } // Use in conjunction with .sr-only to only display content when it's focused. -// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 +// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 // Credit: HTML5 Boilerplate .sr-only-focusable { diff --git a/themes/bootstrap3/less/vendor/bootstrap/tables.less b/themes/bootstrap3/less/vendor/bootstrap/tables.less index 2242c036868d7358ad684313ccab2e4d4704ee94..43411b38460c1f6e6cf01f58ac46bdecb872b987 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/tables.less +++ b/themes/bootstrap3/less/vendor/bootstrap/tables.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-no-qualifying-type + // // Tables // -------------------------------------------------- @@ -5,13 +7,34 @@ table { background-color: @table-bg; + + // Table cell sizing + // + // Reset default table behavior + + col[class*="col-"] { + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) + display: table-column; + float: none; + } + + td, + th { + &[class*="col-"] { + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) + display: table-cell; + float: none; + } + } } + caption { padding-top: @table-cell-padding; padding-bottom: @table-cell-padding; color: @text-muted; text-align: left; } + th { text-align: left; } @@ -128,27 +151,6 @@ th { } -// Table cell sizing -// -// Reset default table behavior - -table col[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-column; -} -table { - td, - th { - &[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-cell; - } - } -} - - // Table backgrounds // // Exact selectors below required to override `.table-striped` and prevent @@ -169,12 +171,12 @@ table { // will display normally. .table-responsive { + min-height: .01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837) overflow-x: auto; - min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837) @media screen and (max-width: @screen-xs-max) { width: 100%; - margin-bottom: (@line-height-computed * 0.75); + margin-bottom: (@line-height-computed * .75); overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid @table-border-color; diff --git a/themes/bootstrap3/less/vendor/bootstrap/theme.less b/themes/bootstrap3/less/vendor/bootstrap/theme.less index fb6174427ba296a62cc334a24a618dcac0700505..a41a1f642a93b3003cac2a52a42c65c113038b98 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/theme.less +++ b/themes/bootstrap3/less/vendor/bootstrap/theme.less @@ -1,6 +1,8 @@ +// stylelint-disable selector-no-qualifying-type, selector-max-compound-selectors + /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -23,14 +25,14 @@ .btn-info, .btn-warning, .btn-danger { - text-shadow: 0 -1px 0 rgba(0,0,0,.2); - @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); .box-shadow(@shadow); // Reset the shadow &:active, &.active { - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); } &.disabled, @@ -88,7 +90,11 @@ } // Apply the mixin to the buttons -.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; } +.btn-default { + .btn-styles(@btn-default-bg); + text-shadow: 0 1px 0 #fff; + border-color: #ccc; +} .btn-primary { .btn-styles(@btn-primary-bg); } .btn-success { .btn-styles(@btn-success-bg); } .btn-info { .btn-styles(@btn-info-bg); } @@ -102,7 +108,7 @@ .thumbnail, .img-thumbnail { - .box-shadow(0 1px 2px rgba(0,0,0,.075)); + .box-shadow(0 1px 2px rgba(0, 0, 0, .075)); } @@ -132,18 +138,18 @@ #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg); .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered border-radius: @navbar-border-radius; - @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075); + @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); .box-shadow(@shadow); .navbar-nav > .open > a, .navbar-nav > .active > a { #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%)); - .box-shadow(inset 0 3px 9px rgba(0,0,0,.075)); + .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075)); } } .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255,255,255,.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); } // Inverted navbar @@ -154,12 +160,12 @@ .navbar-nav > .open > a, .navbar-nav > .active > a { #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%)); - .box-shadow(inset 0 3px 9px rgba(0,0,0,.25)); + .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25)); } .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0,0,0,.25); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); } } @@ -189,8 +195,8 @@ // Common styles .alert { - text-shadow: 0 1px 0 rgba(255,255,255,.2); - @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05); + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + @shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); .box-shadow(@shadow); } @@ -241,7 +247,7 @@ .list-group { border-radius: @border-radius-base; - .box-shadow(0 1px 2px rgba(0,0,0,.075)); + .box-shadow(0 1px 2px rgba(0, 0, 0, .075)); } .list-group-item.active, .list-group-item.active:hover, @@ -262,7 +268,7 @@ // Common styles .panel { - .box-shadow(0 1px 2px rgba(0,0,0,.05)); + .box-shadow(0 1px 2px rgba(0, 0, 0, .05)); } // Mixin for generating new styles @@ -286,6 +292,6 @@ .well { #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg); border-color: darken(@well-bg, 10%); - @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); + @shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); .box-shadow(@shadow); } diff --git a/themes/bootstrap3/less/vendor/bootstrap/thumbnails.less b/themes/bootstrap3/less/vendor/bootstrap/thumbnails.less index 0713e67d0068e9553c5e21bb6024122029cce520..11bea9bf75afc412e253cd7e5ec6b022b8af77a5 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/thumbnails.less +++ b/themes/bootstrap3/less/vendor/bootstrap/thumbnails.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-no-qualifying-type + // // Thumbnails // -------------------------------------------------- @@ -17,8 +19,8 @@ > img, a > img { &:extend(.img-responsive); - margin-left: auto; margin-right: auto; + margin-left: auto; } // Add a hover state for linked versions only diff --git a/themes/bootstrap3/less/vendor/bootstrap/tooltip.less b/themes/bootstrap3/less/vendor/bootstrap/tooltip.less index b48d63e07ad880200cafb5c110acfc14e76ea7cf..650ab424d3bae0bbe920d9572be20f6f157ec7b6 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/tooltip.less +++ b/themes/bootstrap3/less/vendor/bootstrap/tooltip.less @@ -15,33 +15,25 @@ .opacity(0); - &.in { .opacity(@tooltip-opacity); } - &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; } - &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; } - &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; } - &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; } -} - -// Wrapper for the tooltip content -.tooltip-inner { - max-width: @tooltip-max-width; - padding: 3px 8px; - color: @tooltip-color; - text-align: center; - background-color: @tooltip-bg; - border-radius: @border-radius-base; -} + &.in { .opacity(@tooltip-opacity); } + &.top { + padding: @tooltip-arrow-width 0; + margin-top: -3px; + } + &.right { + padding: 0 @tooltip-arrow-width; + margin-left: 3px; + } + &.bottom { + padding: @tooltip-arrow-width 0; + margin-top: 3px; + } + &.left { + padding: 0 @tooltip-arrow-width; + margin-left: -3px; + } -// Arrows -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 -.tooltip { + // Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 &.top .tooltip-arrow { bottom: 0; left: 50%; @@ -50,8 +42,8 @@ border-top-color: @tooltip-arrow-color; } &.top-left .tooltip-arrow { - bottom: 0; right: @tooltip-arrow-width; + bottom: 0; margin-bottom: -@tooltip-arrow-width; border-width: @tooltip-arrow-width @tooltip-arrow-width 0; border-top-color: @tooltip-arrow-color; @@ -99,3 +91,22 @@ border-bottom-color: @tooltip-arrow-color; } } + +// Wrapper for the tooltip content +.tooltip-inner { + max-width: @tooltip-max-width; + padding: 3px 8px; + color: @tooltip-color; + text-align: center; + background-color: @tooltip-bg; + border-radius: @border-radius-base; +} + +// Arrows +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} diff --git a/themes/bootstrap3/less/vendor/bootstrap/type.less b/themes/bootstrap3/less/vendor/bootstrap/type.less index 0d4fee48486eaaa946e42f0335af6789fcf2a8d8..1980e40831dd509a0f917705ba4f5a6a848f08ff 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/type.less +++ b/themes/bootstrap3/less/vendor/bootstrap/type.less @@ -1,3 +1,5 @@ +// stylelint-disable selector-list-comma-newline-after, selector-no-qualifying-type + // // Typography // -------------------------------------------------- @@ -15,7 +17,7 @@ h1, h2, h3, h4, h5, h6, small, .small { - font-weight: normal; + font-weight: 400; line-height: 1; color: @headings-small-color; } @@ -82,8 +84,8 @@ small, mark, .mark { - background-color: @state-warning-bg; padding: .2em; + background-color: @state-warning-bg; } // Alignment @@ -180,8 +182,8 @@ ol { > li { display: inline-block; - padding-left: 5px; padding-right: 5px; + padding-left: 5px; } } @@ -195,7 +197,7 @@ dd { line-height: @line-height-base; } dt { - font-weight: bold; + font-weight: 700; } dd { margin-left: 0; // Undo browser default @@ -230,12 +232,12 @@ dd { // ------------------------- // Abbreviations and acronyms -abbr[title], // Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257 +abbr[title], abbr[data-original-title] { cursor: help; - border-bottom: 1px dotted @abbr-border-color; } + .initialism { font-size: 90%; .text-uppercase(); @@ -267,7 +269,7 @@ blockquote { color: @blockquote-small-color; &:before { - content: '\2014 \00A0'; // em dash, nbsp + content: "\2014 \00A0"; // em dash, nbsp } } } @@ -279,17 +281,17 @@ blockquote { blockquote.pull-right { padding-right: 15px; padding-left: 0; + text-align: right; border-right: 5px solid @blockquote-border-color; border-left: 0; - text-align: right; // Account for citation footer, small, .small { - &:before { content: ''; } + &:before { content: ""; } &:after { - content: '\00A0 \2014'; // nbsp, em dash + content: "\00A0 \2014"; // nbsp, em dash } } } diff --git a/themes/bootstrap3/less/vendor/bootstrap/utilities.less b/themes/bootstrap3/less/vendor/bootstrap/utilities.less index 7a8ca27a8ff54db1c439812d4b295d9a1c4f6f76..834f5b72670f8d5a98d422cc939bf335f8fdf7bb 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/utilities.less +++ b/themes/bootstrap3/less/vendor/bootstrap/utilities.less @@ -1,3 +1,5 @@ +// stylelint-disable declaration-no-important + // // Utility classes // -------------------------------------------------- diff --git a/themes/bootstrap3/less/vendor/bootstrap/variables.less b/themes/bootstrap3/less/vendor/bootstrap/variables.less index 03b54980ae2ab00a8c6180dd709deb361697adec..0b6499267ab6ababcce3d32497fc33e1a3873c35 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/variables.less +++ b/themes/bootstrap3/less/vendor/bootstrap/variables.less @@ -1,3 +1,5 @@ +// stylelint-disable value-keyword-case + // // Variables // -------------------------------------------------- @@ -50,14 +52,14 @@ @font-size-base: 14px; @font-size-large: ceil((@font-size-base * 1.25)); // ~18px -@font-size-small: ceil((@font-size-base * 0.85)); // ~12px +@font-size-small: ceil((@font-size-base * .85)); // ~12px @font-size-h1: floor((@font-size-base * 2.6)); // ~36px @font-size-h2: floor((@font-size-base * 2.15)); // ~30px @font-size-h3: ceil((@font-size-base * 1.7)); // ~24px @font-size-h4: ceil((@font-size-base * 1.25)); // ~18px @font-size-h5: @font-size-base; -@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px +@font-size-h6: ceil((@font-size-base * .85)); // ~12px //** Unit-less `line-height` for use in components like buttons. @line-height-base: 1.428571429; // 20/14 @@ -234,7 +236,7 @@ //** Background for the dropdown menu. @dropdown-bg: #fff; //** Dropdown menu `border-color`. -@dropdown-border: rgba(0,0,0,.15); +@dropdown-border: rgba(0, 0, 0, .15); //** Dropdown menu `border-color` **for IE8**. @dropdown-fallback-border: #ccc; //** Divider color for between dropdown items. @@ -540,7 +542,7 @@ //** Popover maximum width @popover-max-width: 276px; //** Popover border color -@popover-border-color: rgba(0,0,0,.2); +@popover-border-color: rgba(0, 0, 0, .2); //** Popover fallback border color @popover-fallback-border-color: #ccc; @@ -598,7 +600,7 @@ //** Background color of modal content area @modal-content-bg: #fff; //** Modal content border color -@modal-content-border-color: rgba(0,0,0,.2); +@modal-content-border-color: rgba(0, 0, 0, .2); //** Modal content border color **for IE8** @modal-content-fallback-border-color: #999; @@ -803,7 +805,7 @@ // //## -@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6); +@carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6); @carousel-control-color: #fff; @carousel-control-width: 15%; diff --git a/themes/bootstrap3/less/vendor/bootstrap/wells.less b/themes/bootstrap3/less/vendor/bootstrap/wells.less index 15d072b0cd0e31d6bd40fad5aa1cb8fb1fbdefd9..9f5bdaa3838296d3e9f13311b45141bd3a139f55 100644 --- a/themes/bootstrap3/less/vendor/bootstrap/wells.less +++ b/themes/bootstrap3/less/vendor/bootstrap/wells.less @@ -11,10 +11,10 @@ background-color: @well-bg; border: 1px solid @well-border; border-radius: @border-radius-base; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); + .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .05)); blockquote { border-color: #ddd; - border-color: rgba(0,0,0,.15); + border-color: rgba(0, 0, 0, .15); } } diff --git a/themes/bootstrap3/scss/bootstrap.scss b/themes/bootstrap3/scss/bootstrap.scss index 5433b8e62e22a5dc822b091b7b033f60809f3df5..6d7518624b1a527e7ee678174dadd13d779ed1c8 100644 --- a/themes/bootstrap3/scss/bootstrap.scss +++ b/themes/bootstrap3/scss/bootstrap.scss @@ -10,6 +10,7 @@ $fa-font-path: "../../bootstrap3/css/fonts"; @import "components/alphabrowse"; @import "components/autocomplete"; @import "components/channels"; +@import "components/form"; @import "components/icons"; @import "components/js-tree"; @import "components/lightbox"; @@ -114,7 +115,16 @@ footer { float: right; padding-left: 1rem; } + .mainbody.solo { + width: auto; + padding-left: 0; + padding-right: 0; + } } +.flex { display: flex; } +.rtl .flex { flex-direction: row-reverse; } +.flex-col { flex: 0 1 100%; } +.flex-none { flex: none; } /* ------ Form Errors ------ */ .has-error {margin-bottom: 0;} @@ -215,18 +225,6 @@ footer { .date-from { padding-right: .25rem; } .date-to { padding-left: .25rem; } } -.top-facets { - margin-left: -.5rem; - margin-right: -.5rem; -} -.top-facets .facet, -.top-facets .narrow-toggle, -.top-facets > strong { - display: inline-block; - padding: .25rem .5rem; - white-space: nowrap; -} -.top-facets .narrow-toggle { text-decoration: underline; } @media (min-width: 768px) { .author-facets { display: flex; } .author-list { flex: 0 1 100%; } @@ -239,18 +237,77 @@ footer { padding: 10px 15px; &:hover, &:focus { background-color: $nav-link-hover-bg; } - - .badge { float: right; } +} +.myresearch-menu .flex { display: flex; } +.myresearch-menu a:hover { + background-color: $gray-lighter; + outline: dotted 1px #000; } .myresearch-menu a.active { background-color: $brand-primary; color: #fff; - - .badge { - background-color: #fff; - color: $gray-darker; - } } +.myresearch-menu .active .badge { + background-color: #fff; + color: $gray-darker; +} +.myresearch-menu a > .badge { float: right; } +.myresearch-menu .status { + float: right; + display: flex; + flex: none; +} +.myresearch-menu .status .ok, +.myresearch-menu .status.ok { color: $state-success-text; } +.myresearch-menu .status .warn, +.myresearch-menu .status.warn { color: $state-warning-text; } +.myresearch-menu .status .overdue, +.myresearch-menu .status.overdue { color: $state-danger-text; } +.myresearch-menu .badge.ok { background-color: $state-success-bg; } +.myresearch-menu .badge.warn { background-color: $state-warning-bg; } +.myresearch-menu .badge.overdue { background-color: $state-danger-bg; } + +.checkedout-status .badge { + border-radius: 2px; + margin: 0 2px; + border: 1px solid; /* color inherited from bootstrap */ + height: 20px; +} +.active .status .badge { + color: #fff; + background-color: transparent; + border: 1px solid #fff; +} +.myresearch-menu .active .ok { + background-color: $state-success-text; + border-color: $state-success-bg; +} +.myresearch-menu .active .warn { + background-color: $state-warning-text; + border-color: $state-warning-bg; +} +.myresearch-menu .active .overdue { + background-color: $state-danger-text; + border-color: $state-danger-bg; +} +.myresearch-menu .active .warn { background-color: $state-warning-text; } +.myresearch-menu .active .overdue { background-color: $state-danger-text; } +.myresearch-menu .active .text-success { color: $state-success-bg; } +.myresearch-menu .active .text-warning { color: $state-warning-bg; } +.myresearch-menu .active .text-danger { color: $state-danger-bg; } + +.logoutOptions.with-dropdown a { padding-right: .5rem; } +#login-dropdown a { + margin-right: .5rem; + padding-left: .5rem; + padding-right: .5rem; +} +#login-dropdown .dropdown-menu { width: 250px; } +#login-dropdown .dropdown-menu h4 { display: none; } +#login-dropdown .dropdown-menu .myresearch-menu { display: none; } +#login-dropdown .dropdown-menu .account-menu { display: block; } + +/* --- PubDateVis --- */ .list-edit-container { @include clearfix(); } /* ------ PubDateVis ------ */ diff --git a/themes/bootstrap3/scss/components/channels.scss b/themes/bootstrap3/scss/components/channels.scss index dddb8817c9814a25656b915d0289311f09a06d58..65cbae9222eea067832c700f61c334fd24e1942e 100644 --- a/themes/bootstrap3/scss/components/channels.scss +++ b/themes/bootstrap3/scss/components/channels.scss @@ -1,15 +1,47 @@ +.channel-wrapper { + margin-top: 1rem; + margin-bottom: 2rem; +} +@media (max-width: 767px) { + .channel-wrapper { + margin-left: 1rem; + } +} .channel { position: relative; width: 100%; - height: 300px; - border: 1px solid $btn-default-border; + max-height: 300px; + padding: 1rem; + background-color: #eee; border-radius: $border-radius-base; } -.channel .slider-menu { - border-top-color: $btn-default-border; - border-radius: 0 0 $border-radius-base $border-radius-base; - .channel-links .btn { margin-left: 4px; } + +.channel-add-menu { + position: relative; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid $gray; + text-align: center; } +@media (min-width: 768px) { + .channel-add-menu { + float: right; + margin: 0; + padding: 0; + border: 0; + + body.rtl & { + float: left; + } + } +} +.channel-add-menu .dropdown-menu { + left: auto; + right: 0; + max-width: 90vw; + overflow: hidden; +} + .channel .channel-record.slide { display: inline-block; min-width: 100px; @@ -21,16 +53,32 @@ } .channel .channel-record.is-selected { @extend a:hover; } .channel .channel-record .thumb { + display: flex; height: 200px; - background-position: center center; - background-repeat: no-repeat; - background-size: contain; + align-items: center; + justify-content: center; +} +.channel .channel-record .thumb img { + max-width: 100%; + max-height: 100%; } + .channel .popover { width: 500px; max-width: none; } +.channel .popover-title { + font-size: 1.4rem; + font-weight: bold; +} +.channel-title h2 { + display: inline-block; + margin: 0; +} +.channel-title .dropdown { + display: inline-block; +} .channel-title a:hover { text-decoration: none; } .channel-title i.fa-fw { width: 1.4em; @@ -40,3 +88,17 @@ vertical-align: top; } .channel-title .placeholder { width: 25px; } + +.channel-title .dropdown button { + font-size: 18px; + color: #777; + vertical-align: baseline; +} +.channel .slick-prev::before, +.channel .slick-next::before { + color: #555; +} + +.channel-search { + margin-top: 1rem; +} diff --git a/themes/bootstrap3/scss/components/form.scss b/themes/bootstrap3/scss/components/form.scss new file mode 100644 index 0000000000000000000000000000000000000000..5a67b247fb004365778008ac06ddae6b3d05f2a9 --- /dev/null +++ b/themes/bootstrap3/scss/components/form.scss @@ -0,0 +1,21 @@ +form { + textarea:invalid, + input:invalid { + box-shadow: 0 0 2px 1px rgba(255, 0, 0, 0.9); + } + .form-info { + font-weight: bold; + margin: 20px 0; + } + .info { + margin: 10px 0; + } + .form-group ul { + padding: 0; + margin-left: 15px; + margin-top: 5px; + } + .form-group label.required::before { + content: '* '; + } +} diff --git a/themes/bootstrap3/scss/components/icons.scss b/themes/bootstrap3/scss/components/icons.scss index ed654a6ed50f84aae44d12426c570c701cda0035..751dfbcd26d889176ecb36577a05820cb45cd6a8 100644 --- a/themes/bootstrap3/scss/components/icons.scss +++ b/themes/bootstrap3/scss/components/icons.scss @@ -1,7 +1,11 @@ /** * Assign catalog formats to Font Awesome icons */ - +.doi-icon { + height: 1em; + width: 14px; + filter: brightness(50%); +} // Alias .fa-printer:before {content: "\f02f";} // .fa-print // Search Icons diff --git a/themes/bootstrap3/scss/components/lightbox.scss b/themes/bootstrap3/scss/components/lightbox.scss index 9361fab53c8332b260db43ea81f248ccf5d7c0a8..d7adf7a0bfd9a6bc76819e5e0af496c9ebb7130f 100644 --- a/themes/bootstrap3/scss/components/lightbox.scss +++ b/themes/bootstrap3/scss/components/lightbox.scss @@ -1,17 +1,30 @@ #modal { background-color: rgba(0,0,0,.2); } -#modal .modal-content > .close { // Fancy side X button + +#modal .modal-content > .close { position: absolute; - right: -50px; top: 0; + right: 0; z-index: 2; - font-size: 32pt; - color: #fff; + padding: .5rem 1rem; opacity: .7; + body.rtl & { - left: -50px; + left: 0; right: auto; } } +@media (min-width: 768px) { + #modal .modal-content > .close { // Fancy side X button + right: -50px; + font-size: 32pt; + color: #fff; + body.rtl & { + left: -50px; + right: auto; + } + } +} + #modal .modal-content > .close:hover { opacity: 1; } #modal .modal-body h1, #modal .modal-body h2 { @@ -30,4 +43,7 @@ body.rtl .modal-loading { float: left; } // Utility classes .lightbox-only { display: none; } -#modal .lightbox-only { display: initial; } \ No newline at end of file +#modal .lightbox-only { display: initial; } + +// Image display +.lightbox-image { text-align: center; } \ No newline at end of file diff --git a/themes/bootstrap3/scss/components/offcanvas.scss b/themes/bootstrap3/scss/components/offcanvas.scss index 2371997017aaa38ee66db8f79003276dcf9b70f8..d1e1b9a3866bddabbdde352b3378d802cfc6e931 100644 --- a/themes/bootstrap3/scss/components/offcanvas.scss +++ b/themes/bootstrap3/scss/components/offcanvas.scss @@ -1,88 +1,118 @@ -$offcanvas-offset: 75vw !default; // Width of open menu -$offcanvas-padding: 30px !default; // Body offset when offcanvas active, also width of toggle +$offcanvas-offset: 80vw !default; // Width of open menu -.offcanvas-overlay, -.offcanvas-toggle { display: none; } +.offcanvas-overlay { display: none; } + +.search-filter-toggle { + @extend .btn; + @extend .btn-default; + margin-top: 1rem; + margin-bottom: 1rem; +} + +.close-offcanvas, +.search-filter-toggle { display: none; } @media screen and (max-width: 767px) { + .close-offcanvas::before, + .close-offcanvas::after, + .search-filter-toggle::before, + .search-filter-toggle::after { + display: inline-block; + width: 16px; + font: normal normal normal 14px/1 FontAwesome; + } + + .offcanvas .close-offcanvas { display: block; } + .search-filter-toggle { + @extend .btn; + @extend .btn-default; + margin-top: 1rem; + margin-bottom: 1rem; + } + body.offcanvas { overflow-x: hidden; /* Prevent scroll on narrow devices */ - .sidebar { - position: fixed; - height: 100%; - top: 0; - width: $offcanvas-offset; - padding-left: 0; - padding-right: 0; - overflow-y: auto; - h4 { padding-left: $padding-base-horizontal; } - .checkbox { margin-left: 20px + $padding-base-horizontal; } - .list-group, .list-group-item { - border-left: 0; - border-right: 0; - border-radius: 0 !important; - } - } - &.active { overflow-y: hidden; } + transition: margin .5s; + } + .offcanvas-overlay { + display: none; + position: fixed; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,.3); + z-index: 3; + opacity: 0; + transition: opacity .5s; + cursor: pointer; + } + .offcanvas .offcanvas-overlay { display: block; } + + .offcanvas-left { + .sidebar { left: -$offcanvas-offset; } + .offcanvas-overlay { right: -100%; } + .offcanvas-toggle { left: 0; } + } + .offcanvas-right { + .sidebar { right: -$offcanvas-offset; } + .offcanvas-overlay { left: -100%; } + .offcanvas-toggle { right: 0; } + } + .offcanvas .sidebar { + position: fixed; + height: 100%; + top: 0; + width: $offcanvas-offset; + padding: 1rem; + overflow-y: auto; + background-color: #fff; + transition: left .5s, right .5s; + + .search-sort { padding-bottom: 1rem; } + } + .offcanvas.active { + overflow-y: hidden; &.offcanvas-left { - padding-left: $offcanvas-padding - $grid-gutter-width/2; - & .main { background: #FFF; } - &.active { - margin-left: $offcanvas-offset; - margin-right: -$offcanvas-offset; - .sidebar { left: 0; } - .offcanvas-overlay { right: -$offcanvas-offset; } - .offcanvas-toggle { left: $offcanvas-offset; } - } - .sidebar { left: -$offcanvas-offset; } - .offcanvas-overlay { right: -100%; } - .offcanvas-toggle { left: 0; } + margin-left: $offcanvas-offset; + margin-right: -$offcanvas-offset; + .sidebar { left: 0; } + .offcanvas-overlay { right: -$offcanvas-offset; } + .offcanvas-toggle { left: $offcanvas-offset; } } &.offcanvas-right { - padding-right: $offcanvas-padding - $grid-gutter-width/2; - & .main > .container { background: #FFF; } - &.active { - margin-left: -$offcanvas-offset; - margin-right: $offcanvas-offset; - .sidebar { right: 0; } - .offcanvas-overlay { left: -$offcanvas-offset; } - .offcanvas-toggle { right: $offcanvas-offset; } - } - .sidebar { right: -$offcanvas-offset; } - .offcanvas-overlay { left: -100%; } - .offcanvas-toggle { right: 0; } + margin-left: -$offcanvas-offset; + margin-right: $offcanvas-offset; + .sidebar { right: 0; } + .offcanvas-overlay { left: -$offcanvas-offset; } + .offcanvas-toggle { right: $offcanvas-offset; } } .offcanvas-overlay { - display: block; - position: fixed; - top: 0; - width: 100%; - height: 100%; - background-color: rgba(0,0,0,.3); - z-index: 3; + opacity: 1; + transition: opacity .5s; } - .offcanvas-toggle { - display: block; - position: fixed; - top: 0; - width: calc(#{$offcanvas-padding} - 5px); - height: 100%; - border-left: 1px solid $gray-lighter; - border-right: 1px solid $gray-lighter; - line-height: 90vh; // Center vertically - text-align: center; - background-color: #fff; - z-index: 5; + } + + /* Button arrows */ + .offcanvas-left { + .close-offcanvas::after { content: "\f105"; } + .search-filter-toggle::before { content: "\f100"; } + } + .offcanvas-right { + .close-offcanvas::before { content: "\f104"; } + .search-filter-toggle::after { content: "\f101"; } + } + .rtl /* right to left */ { + &.offcanvas-left { + .close-offcanvas::after { content: none; } + .close-offcanvas::before { content: "\f105"; } + .search-filter-toggle::before { content: none; } + .search-filter-toggle::after { content: "\f100"; } } - .offcanvas-overlay, - .offcanvas-toggle, - .offcanvas-toggle * { cursor: pointer; } - &,.sidebar, - .offcanvas-overlay, - .offcanvas-toggle { - -webkit-transition: all .25s ease-out; - -o-transition: all .25s ease-out; - transition: all .25s ease-out; + &.offcanvas-right { + .close-offcanvas::before { content: none; } + .close-offcanvas::after { content: "\f104"; } + .search-filter-toggle::after { content: none; } + .search-filter-toggle::before { content: "\f101"; } } } } diff --git a/themes/bootstrap3/scss/components/search.scss b/themes/bootstrap3/scss/components/search.scss index bb0ecf8dcc196312c02dd96444434041c6e42d74..278bf276be9a957f75bb825b5dd8bf8fea9e326d 100644 --- a/themes/bootstrap3/scss/components/search.scss +++ b/themes/bootstrap3/scss/components/search.scss @@ -40,8 +40,8 @@ header .container.navbar { margin-bottom: 0; } } .search-stats { display: block; - padding-top: 1rem; - padding-bottom: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; } @media (min-width: 768px) { @@ -98,6 +98,8 @@ header .container.navbar { margin-bottom: 0; } .media { flex: 1; margin: 0; + padding-right: 10px; + padding-left: 10px; } .media-left, .media-right { @@ -114,13 +116,13 @@ header .container.navbar { margin-bottom: 0; } max-width: none; } } + .media-left { margin-right: 10px; } + .media-right { margin-left: 10px; } @media (min-width: 768px) { .media-left, .media-right { max-width: 25%; - padding-right: 10px; - padding-left: 10px; a { display: inline-block; diff --git a/themes/bootstrap3/scss/components/sidebar.scss b/themes/bootstrap3/scss/components/sidebar.scss index 9c51e5151652df245e4a1f1e8e3038c36d69cc5d..163c15744cdcc981f12ef30311641f1be0b30177 100644 --- a/themes/bootstrap3/scss/components/sidebar.scss +++ b/themes/bootstrap3/scss/components/sidebar.scss @@ -3,33 +3,6 @@ margin-bottom: 1rem; padding-left: 0; - .facet, - .title { - display: block; - padding: 8px 15px; - line-height: 1.5rem; - width: 100%; - text-align: left; - background-color: transparent; - - .badge, - .status { - float: right; - - body.rtl & { float: left; } - } - .badge { - max-height: 19px; - line-height: 1.1rem; - } - } - .facet { border-bottom: 1px solid $list-group-border; } - .title { - padding-right: 8px; - border: 1px solid $list-group-border; - font-weight: bold; - } - [data-toggle="collapse"] { cursor: pointer; @@ -45,40 +18,89 @@ .collapse, .collapsing, & > .facet { + position: relative; border-left: 1px solid $list-group-border; border-right: 1px solid $list-group-border; } & > .facet:first-child { border-top: 1px solid $list-group-border; } +} - .facetOR .text { - display: inline-block; - padding-left: 0.5rem; - text-indent: -0.5rem; +.facet, +.facet-group .title, +.facet-load-indicator { + display: flex; + padding: .5rem; + width: 100%; + line-height: 1.5rem; + background-color: transparent; + + .text { + flex-grow: 1; } - .excludable { - display: flex; - flex-direction: row-reverse; - padding-right: 0; - - .badge { flex-shrink: 0; } - .text { flex-grow: 1; } - .exclude { - flex-basis: 2rem; - flex-shrink: 0; - text-align: center; - } + .badge { + flex-shrink: 0; + max-height: 19px; + line-height: 1.2; + vertical-align: baseline; + } - body.rtl & { - padding-left: 0; - padding-right: 15px; - } + .exclude { + flex-shrink: 0; + text-align: center; + padding-left: 0.5rem; } } +.facet-group .facet, +.facet-load-indicator { + border-bottom: 1px solid $list-group-border; +} +.facet-group .title { + display: block; + padding-right: 8px; + border: 1px solid $list-group-border; + font-weight: bold; + text-align: inherit; +} +.facet-loading-overlay { + position: absolute; + top: 0; + left: 0; + display: flex; + width: 100%; + height: 100%; + align-items: center; + justify-content: center; + background-color: rgba(0,0,0,0.4); +} +.facet-loading-overlay-label { + padding: 1px .5rem; + color: #fff; + background-color: #000; +} + +.top-facets .facet, +.top-facets .narrow-toggle, +.top-facets > strong { + display: inline-block; + width: auto; + padding: .25rem .5rem; + border: 0; + white-space: nowrap; +} +.top-facets .narrow-toggle { text-decoration: underline; } +.top-facets .top-facet { + margin-top: 2px; + margin-bottom: 2px; + border: 1px solid $list-group-border; +} +.checkboxFilter { + padding-bottom: 0.5rem; +} .checkbox-filter { - display: block; - padding-bottom: 1rem; + display: flex; + width: 100%; font-weight: bold; color: $text-color; } @@ -120,17 +142,16 @@ } .full-facet-list { margin-top: 1rem; } -.full-facet-list .active .fa { +.full-facet-list .active .fa.fa-times { float: right; margin-top: .25rem; - margin-right: 0.5rem; margin-left: 0.5rem; } -body.rtl .full-facet-list .active .fa { float: left; } +body.rtl .full-facet-list .active .fa.fa-times { float: left; } .jstree-node { .facet { - padding: 0; + padding: 0 0.5rem 0 0; border: none; } } diff --git a/themes/bootstrap3/scss/vendor/_bootstrap.scss b/themes/bootstrap3/scss/vendor/_bootstrap.scss index e72d1def2a217b615f5a931d1d7e84d9332cbc6a..3d6fa3a469d0f8a89ef7c7067343b34af5efbd04 100644 --- a/themes/bootstrap3/scss/vendor/_bootstrap.scss +++ b/themes/bootstrap3/scss/vendor/_bootstrap.scss @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_alerts.scss b/themes/bootstrap3/scss/vendor/bootstrap/_alerts.scss index 7d1e1fddd15d81820e7bcfbd4b270381cf3b9377..f9e69bd08403dc11220fc79093c7a998dae5f8c4 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_alerts.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_alerts.scss @@ -15,8 +15,7 @@ // Headings for larger alerts h4 { margin-top: 0; - // Specified for the h4 to prevent conflicts of changing $headings-color - color: inherit; + color: inherit; // Specified for the h4 to prevent conflicts of changing $headings-color } // Provide class for links that match alerts @@ -39,7 +38,8 @@ // // Expand the right padding and account for the close button's positioning. -.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +// The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissable, .alert-dismissible { padding-right: ($alert-padding + 20); diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_badges.scss b/themes/bootstrap3/scss/vendor/bootstrap/_badges.scss index 70002e085b1867b14af58414c79074e444cb07ce..44d5dd6f4ba4a28c3b246f9dc0c31d439b453e34 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_badges.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_badges.scss @@ -10,11 +10,11 @@ padding: 3px 7px; font-size: $font-size-small; font-weight: $badge-font-weight; - color: $badge-color; line-height: $badge-line-height; - vertical-align: middle; - white-space: nowrap; + color: $badge-color; text-align: center; + white-space: nowrap; + vertical-align: middle; background-color: $badge-bg; border-radius: $badge-border-radius; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_breadcrumbs.scss b/themes/bootstrap3/scss/vendor/bootstrap/_breadcrumbs.scss index b61f0c731caf2f99d3fba09e6643216c679984a6..67e39d909acf0e626f764d47daed150f66ffa42c 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_breadcrumbs.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_breadcrumbs.scss @@ -14,11 +14,11 @@ display: inline-block; + li:before { + padding: 0 5px; + color: $breadcrumb-color; // [converter] Workaround for https://github.com/sass/libsass/issues/1115 $nbsp: "\00a0"; content: "#{$breadcrumb-separator}#{$nbsp}"; // Unicode space added since inline-block means non-collapsing white-space - padding: 0 5px; - color: $breadcrumb-color; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_button-groups.scss b/themes/bootstrap3/scss/vendor/bootstrap/_button-groups.scss index 4b385f569c491ac441fc4e518c38247f717e221f..6a62faf5dfdeb41b249a6cdbc57d2225ea4446f6 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_button-groups.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_button-groups.scss @@ -103,18 +103,18 @@ // Give the line between buttons some depth .btn-group > .btn + .dropdown-toggle { - padding-left: 8px; padding-right: 8px; + padding-left: 8px; } .btn-group > .btn-lg + .dropdown-toggle { - padding-left: 12px; padding-right: 12px; + padding-left: 12px; } // The clickable button for toggling the menu // Remove the gradient and set the same inset shadow as the :active state .btn-group.open .dropdown-toggle { - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + @include box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); // Show no shadow for `.btn-link` since it has no other button styles. &.btn-link { @@ -205,8 +205,8 @@ border-collapse: separate; > .btn, > .btn-group { - float: none; display: table-cell; + float: none; width: 1%; } > .btn-group .btn { @@ -237,7 +237,7 @@ input[type="radio"], input[type="checkbox"] { position: absolute; - clip: rect(0,0,0,0); + clip: rect(0, 0, 0, 0); pointer-events: none; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_buttons.scss b/themes/bootstrap3/scss/vendor/bootstrap/_buttons.scss index 6452b709f109420cf060147f5eb3d943eeb33b43..62962d786aebb2a64b6839e2073f151a30ddaffd 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_buttons.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_buttons.scss @@ -11,12 +11,12 @@ margin-bottom: 0; // For input.btn font-weight: $btn-font-weight; text-align: center; + white-space: nowrap; vertical-align: middle; touch-action: manipulation; cursor: pointer; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid transparent; - white-space: nowrap; @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $btn-border-radius-base); @include user-select(none); @@ -38,9 +38,9 @@ &:active, &.active { - outline: 0; background-image: none; - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + outline: 0; + @include box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); } &.disabled, @@ -94,8 +94,8 @@ a.btn { // Make a button look and behave like a link .btn-link { + font-weight: 400; color: $link-color; - font-weight: normal; border-radius: 0; &, diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_carousel.scss b/themes/bootstrap3/scss/vendor/bootstrap/_carousel.scss index 753d881f455bc03321c48ada828687eb1ec3c2b5..52a1f7bff0d1a1f3974401dd27e75ff111b11430 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_carousel.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_carousel.scss @@ -10,12 +10,12 @@ .carousel-inner { position: relative; - overflow: hidden; width: 100%; + overflow: hidden; > .item { - display: none; position: relative; + display: none; @include transition(.6s ease-in-out left); // Account for jankitude on images @@ -93,34 +93,34 @@ .carousel-control { position: absolute; top: 0; - left: 0; bottom: 0; + left: 0; width: $carousel-control-width; - @include opacity($carousel-control-opacity); font-size: $carousel-control-font-size; color: $carousel-control-color; text-align: center; text-shadow: $carousel-text-shadow; background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug + @include opacity($carousel-control-opacity); // We can't have this transition here because WebKit cancels the carousel // animation if you trip this while in the middle of another animation. // Set gradients for backgrounds &.left { - @include gradient-horizontal($start-color: rgba(0,0,0,.5), $end-color: rgba(0,0,0,.0001)); + @include gradient-horizontal($start-color: rgba(0, 0, 0, .5), $end-color: rgba(0, 0, 0, .0001)); } &.right { - left: auto; right: 0; - @include gradient-horizontal($start-color: rgba(0,0,0,.0001), $end-color: rgba(0,0,0,.5)); + left: auto; + @include gradient-horizontal($start-color: rgba(0, 0, 0, .0001), $end-color: rgba(0, 0, 0, .5)); } // Hover/focus state &:hover, &:focus { - outline: 0; color: $carousel-control-color; text-decoration: none; + outline: 0; @include opacity(.9); } @@ -131,9 +131,9 @@ .glyphicon-chevron-right { position: absolute; top: 50%; - margin-top: -10px; z-index: 5; display: inline-block; + margin-top: -10px; } .icon-prev, .glyphicon-chevron-left { @@ -147,21 +147,20 @@ } .icon-prev, .icon-next { - width: 20px; + width: 20px; height: 20px; - line-height: 1; font-family: serif; + line-height: 1; } - .icon-prev { &:before { - content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) + content: "\2039";// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) } } .icon-next { &:before { - content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) + content: "\203a";// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) } } } @@ -177,21 +176,18 @@ left: 50%; z-index: 15; width: 60%; - margin-left: -30%; padding-left: 0; - list-style: none; + margin-left: -30%; text-align: center; + list-style: none; li { display: inline-block; - width: 10px; + width: 10px; height: 10px; margin: 1px; text-indent: -999px; - border: 1px solid $carousel-indicator-border-color; - border-radius: 10px; cursor: pointer; - // IE8-9 hack for event handling // // Internet Explorer 8-9 does not support clicks on elements without a set @@ -202,12 +198,16 @@ // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we // set alpha transparency for the best results possible. background-color: #000 \9; // IE8 - background-color: rgba(0,0,0,0); // IE9 + background-color: rgba(0, 0, 0, 0); // IE9 + + border: 1px solid $carousel-indicator-border-color; + border-radius: 10px; } + .active { - margin: 0; - width: 12px; + width: 12px; height: 12px; + margin: 0; background-color: $carousel-indicator-active-bg; } } @@ -217,15 +217,16 @@ // Hidden by default for smaller viewports .carousel-caption { position: absolute; - left: 15%; right: 15%; bottom: 20px; + left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: $carousel-caption-color; text-align: center; text-shadow: $carousel-text-shadow; + & .btn { text-shadow: none; // No shadow for button elements in carousel-caption } @@ -258,8 +259,8 @@ // Show and left align the captions .carousel-caption { - left: 20%; right: 20%; + left: 20%; padding-bottom: 30px; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_close.scss b/themes/bootstrap3/scss/vendor/bootstrap/_close.scss index 3b74d8a973c2be2a1c5ae3002a5935de577dda30..a858a8f367b56dc2845bcfa382434a4812365b05 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_close.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_close.scss @@ -33,4 +33,5 @@ button.close { background: transparent; border: 0; -webkit-appearance: none; + appearance: none; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_code.scss b/themes/bootstrap3/scss/vendor/bootstrap/_code.scss index caa5f06304c8e575b3fabdfdc7639af6d4053cd2..8e2b2a7f433dac43d07ae1f02c302fcd34a48a2f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_code.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_code.scss @@ -27,12 +27,12 @@ kbd { color: $kbd-color; background-color: $kbd-bg; border-radius: $border-radius-small; - box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); kbd { padding: 0; font-size: 100%; - font-weight: bold; + font-weight: 700; box-shadow: none; } } @@ -44,9 +44,9 @@ pre { margin: 0 0 ($line-height-computed / 2); font-size: ($font-size-base - 1); // 14px to 13px line-height: $line-height-base; + color: $pre-color; word-break: break-all; word-wrap: break-word; - color: $pre-color; background-color: $pre-bg; border: 1px solid $pre-border-color; border-radius: $border-radius-base; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_component-animations.scss b/themes/bootstrap3/scss/vendor/bootstrap/_component-animations.scss index ca3b43ca788fff99fb8f46626fdb1ea2efbe9ffc..ca4d6b06822c95a3d1c1343c1270aa142be0f64f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_component-animations.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_component-animations.scss @@ -10,6 +10,7 @@ .fade { opacity: 0; @include transition(opacity .15s linear); + &.in { opacity: 1; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_dropdowns.scss b/themes/bootstrap3/scss/vendor/bootstrap/_dropdowns.scss index aac84597a496ee873bed7e31498dce970da831ca..0a5898a8d02ccb848a218bebff6d9fbac63c3aaa 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_dropdowns.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_dropdowns.scss @@ -10,10 +10,10 @@ height: 0; margin-left: 2px; vertical-align: middle; - border-top: $caret-width-base dashed; - border-top: $caret-width-base solid \9; // IE8 + border-top: $caret-width-base dashed; + border-top: $caret-width-base solid \9; // IE8 border-right: $caret-width-base solid transparent; - border-left: $caret-width-base solid transparent; + border-left: $caret-width-base solid transparent; } // The dropdown wrapper (div) @@ -38,15 +38,15 @@ min-width: 160px; padding: 5px 0; margin: 2px 0 0; // override default ul - list-style: none; font-size: $font-size-base; text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + list-style: none; background-color: $dropdown-bg; + background-clip: padding-box; border: 1px solid $dropdown-fallback-border; // IE8 fallback border: 1px solid $dropdown-border; border-radius: $border-radius-base; - @include box-shadow(0 6px 12px rgba(0,0,0,.175)); - background-clip: padding-box; + @include box-shadow(0 6px 12px rgba(0, 0, 0, .175)); // Aligns the dropdown menu to right // @@ -66,20 +66,17 @@ display: block; padding: 3px 20px; clear: both; - font-weight: normal; + font-weight: 400; line-height: $line-height-base; color: $dropdown-link-color; white-space: nowrap; // prevent links from randomly breaking onto new lines - } -} -// Hover/Focus state -.dropdown-menu > li > a { - &:hover, - &:focus { - text-decoration: none; - color: $dropdown-link-hover-color; - background-color: $dropdown-link-hover-bg; + &:hover, + &:focus { + color: $dropdown-link-hover-color; + text-decoration: none; + background-color: $dropdown-link-hover-bg; + } } } @@ -90,8 +87,8 @@ &:focus { color: $dropdown-link-active-color; text-decoration: none; - outline: 0; background-color: $dropdown-link-active-bg; + outline: 0; } } @@ -110,10 +107,10 @@ &:hover, &:focus { text-decoration: none; + cursor: $cursor-disabled; background-color: transparent; background-image: none; // Remove CSS gradient @include reset-filter; - cursor: $cursor-disabled; } } @@ -135,8 +132,8 @@ // Add extra class to `.dropdown-menu` to flip the alignment of the dropdown // menu with the parent. .dropdown-menu-right { - left: auto; // Reset the default from `.dropdown-menu` right: 0; + left: auto; // Reset the default from `.dropdown-menu` } // With v3, we enabled auto-flipping if you have a dropdown within a right // aligned nav component. To enable the undoing of that, we provide an override @@ -145,8 +142,8 @@ // This is only for left-aligning a dropdown menu within a `.navbar-right` or // `.pull-right` nav component. .dropdown-menu-left { - left: 0; right: auto; + left: 0; } // Dropdown section headers @@ -162,10 +159,10 @@ // Backdrop to catch body clicks on mobile, etc. .dropdown-backdrop { position: fixed; - left: 0; + top: 0; right: 0; bottom: 0; - top: 0; + left: 0; z-index: ($zindex-dropdown - 10); } @@ -184,10 +181,10 @@ .navbar-fixed-bottom .dropdown { // Reverse the caret .caret { + content: ""; border-top: 0; border-bottom: $caret-width-base dashed; border-bottom: $caret-width-base solid \9; // IE8 - content: ""; } // Different positioning for bottom up menu .dropdown-menu { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_forms.scss b/themes/bootstrap3/scss/vendor/bootstrap/_forms.scss index ac26a6ad86b6516dbe332b847207d0fbc79660d5..d2e2bac5cdd69b0bc5e41409143c04ae86eeb12f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_forms.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_forms.scss @@ -8,13 +8,13 @@ // Restyle and baseline non-control form elements. fieldset { - padding: 0; - margin: 0; - border: 0; // Chrome and Firefox set a `min-width: min-content;` on fieldsets, // so we reset that to ensure it behaves more like a standard block element. // See https://github.com/twbs/bootstrap/issues/12359. min-width: 0; + padding: 0; + margin: 0; + border: 0; } legend { @@ -33,7 +33,7 @@ label { display: inline-block; max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) margin-bottom: 5px; - font-weight: bold; + font-weight: 700; } @@ -43,9 +43,18 @@ label { // is required to ensure optimum display with or without those classes to better // address browser inconsistencies. -// Override content-box in Normalize (* isn't specific enough) input[type="search"] { + // Override content-box in Normalize (* isn't specific enough) @include box-sizing(border-box); + + // Search inputs in iOS + // + // This overrides the extra rounded corners on search inputs in iOS so that our + // `.form-control` class can properly style them. Note that this cannot simply + // be added to `.form-control` as it's not specific enough. For details, see + // https://github.com/twbs/bootstrap/issues/11586. + -webkit-appearance: none; + appearance: none; } // Position radios and checkboxes better @@ -54,6 +63,16 @@ input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; // IE8-9 line-height: normal; + + // Apply same disabled cursor tweak as for inputs + // Some special care is needed because <label>s don't inherit their parent's `cursor`. + // + // Note: Neither radios nor checkboxes can be readonly. + &[disabled], + &.disabled, + fieldset[disabled] & { + cursor: $cursor-disabled; + } } input[type="file"] { @@ -123,7 +142,7 @@ output { background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid $input-border; border-radius: $input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS. - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); // Customize the `:focus` state to imitate native WebKit styles. @@ -134,8 +153,8 @@ output { // Unstyle the caret on `<select>`s in IE10+. &::-ms-expand { - border: 0; background-color: transparent; + border: 0; } // Disabled and read-only inputs @@ -164,18 +183,6 @@ textarea.form-control { } -// Search inputs in iOS -// -// This overrides the extra rounded corners on search inputs in iOS so that our -// `.form-control` class can properly style them. Note that this cannot simply -// be added to `.form-control` as it's not specific enough. For details, see -// https://github.com/twbs/bootstrap/issues/11586. - -input[type="search"] { - -webkit-appearance: none; -} - - // Special styles for iOS temporal inputs // // In Mobile Safari, setting `display: block` on temporal inputs causes the @@ -228,11 +235,19 @@ input[type="search"] { margin-top: 10px; margin-bottom: 10px; + // These are used on elements with <label> descendants + &.disabled, + fieldset[disabled] & { + label { + cursor: $cursor-disabled; + } + } + label { min-height: $line-height-computed; // Ensure the input doesn't jump when there is no text padding-left: 20px; margin-bottom: 0; - font-weight: normal; + font-weight: 400; cursor: pointer; } } @@ -241,8 +256,8 @@ input[type="search"] { .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { position: absolute; - margin-left: -20px; margin-top: 4px \9; + margin-left: -20px; } .radio + .radio, @@ -257,45 +272,20 @@ input[type="search"] { display: inline-block; padding-left: 20px; margin-bottom: 0; + font-weight: 400; vertical-align: middle; - font-weight: normal; cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; // space out consecutive inline controls -} -// Apply same disabled cursor tweak as for inputs -// Some special care is needed because <label>s don't inherit their parent's `cursor`. -// -// Note: Neither radios nor checkboxes can be readonly. -input[type="radio"], -input[type="checkbox"] { - &[disabled], - &.disabled, - fieldset[disabled] & { - cursor: $cursor-disabled; - } -} -// These classes are used directly on <label>s -.radio-inline, -.checkbox-inline { + // These are used directly on <label>s &.disabled, fieldset[disabled] & { cursor: $cursor-disabled; } } -// These classes are used on elements with <label> descendants -.radio, -.checkbox { - &.disabled, - fieldset[disabled] & { - label { - cursor: $cursor-disabled; - } - } +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; // space out consecutive inline controls } @@ -305,17 +295,17 @@ input[type="checkbox"] { // a horizontal form layout. .form-control-static { + min-height: ($line-height-computed + $font-size-base); // Size it appropriately next to real form controls padding-top: ($padding-base-vertical + 1); padding-bottom: ($padding-base-vertical + 1); // Remove default margin from `p` margin-bottom: 0; - min-height: ($line-height-computed + $font-size-base); &.input-lg, &.input-sm { - padding-left: 0; padding-right: 0; + padding-left: 0; } } @@ -560,9 +550,9 @@ input[type="checkbox"] { .checkbox, .radio-inline, .checkbox-inline { + padding-top: ($padding-base-vertical + 1); // Default padding plus a border margin-top: 0; margin-bottom: 0; - padding-top: ($padding-base-vertical + 1); // Default padding plus a border } // Account for padding we're adding to ensure the alignment and of help text // and other content below items @@ -580,9 +570,9 @@ input[type="checkbox"] { // labels on narrow viewports stack the same as a default form example. @media (min-width: $screen-sm-min) { .control-label { - text-align: right; - margin-bottom: 0; padding-top: ($padding-base-vertical + 1); // Default padding plus a border + margin-bottom: 0; + text-align: right; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_glyphicons.scss b/themes/bootstrap3/scss/vendor/bootstrap/_glyphicons.scss index 07a0fc91fe6dd8919fc4054e3134776b31170394..bd5966dd264548c7a47634bae1ccd4ec556b3712 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_glyphicons.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_glyphicons.scss @@ -10,13 +10,13 @@ @at-root { // Import the fonts @font-face { - font-family: 'Glyphicons Halflings'; - src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot'), '#{$icon-font-path}#{$icon-font-name}.eot')); - src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot?#iefix'), '#{$icon-font-path}#{$icon-font-name}.eot?#iefix')) format('embedded-opentype'), - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff2'), '#{$icon-font-path}#{$icon-font-name}.woff2')) format('woff2'), - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff'), '#{$icon-font-path}#{$icon-font-name}.woff')) format('woff'), - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.ttf'), '#{$icon-font-path}#{$icon-font-name}.ttf')) format('truetype'), - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}'), '#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}')) format('svg'); + font-family: "Glyphicons Halflings"; + src: url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.eot"), "#{$icon-font-path}#{$icon-font-name}.eot")); + src: url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.eot?#iefix"), "#{$icon-font-path}#{$icon-font-name}.eot?#iefix")) format("embedded-opentype"), + url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.woff2"), "#{$icon-font-path}#{$icon-font-name}.woff2")) format("woff2"), + url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.woff"), "#{$icon-font-path}#{$icon-font-name}.woff")) format("woff"), + url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.ttf"), "#{$icon-font-path}#{$icon-font-name}.ttf")) format("truetype"), + url(if($bootstrap-sass-asset-helper, twbs-font-path("#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}"), "#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}")) format("svg"); } } @@ -25,9 +25,9 @@ position: relative; top: 1px; display: inline-block; - font-family: 'Glyphicons Halflings'; + font-family: "Glyphicons Halflings"; font-style: normal; - font-weight: normal; + font-weight: 400; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_grid.scss b/themes/bootstrap3/scss/vendor/bootstrap/_grid.scss index b15ca27bb546898d56f9f13a8c600c593b7f824e..2ddb73debeca26d1a25789bb3e3d1e1fb9137cbc 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_grid.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_grid.scss @@ -40,6 +40,16 @@ @include make-row; } +.row-no-gutters { + margin-right: 0; + margin-left: 0; + + [class*="col-"] { + padding-right: 0; + padding-left: 0; + } +} + // Columns // diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_input-groups.scss b/themes/bootstrap3/scss/vendor/bootstrap/_input-groups.scss index 81f46f3e6161ce26fbfbdbddb278fdbd3a5275c4..04015feffd273138cf69bc96eea3af0ac198df14 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_input-groups.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_input-groups.scss @@ -12,8 +12,8 @@ // Undo padding and float of grid classes &[class*="col-"] { float: none; - padding-left: 0; padding-right: 0; + padding-left: 0; } .form-control { @@ -77,7 +77,7 @@ .input-group-addon { padding: $padding-base-vertical $padding-base-horizontal; font-size: $font-size-base; - font-weight: normal; + font-weight: 400; line-height: 1; color: $input-color; text-align: center; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_jumbotron.scss b/themes/bootstrap3/scss/vendor/bootstrap/_jumbotron.scss index a27da4738fe71de9fa737c1cfadc92b11975b4d6..7215b991312f6fdd790fabee39082d17871fc26a 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_jumbotron.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_jumbotron.scss @@ -4,7 +4,7 @@ .jumbotron { - padding-top: $jumbotron-padding; + padding-top: $jumbotron-padding; padding-bottom: $jumbotron-padding; margin-bottom: $jumbotron-padding; color: $jumbotron-color; @@ -27,9 +27,9 @@ .container &, .container-fluid & { - border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container - padding-left: ($grid-gutter-width / 2); padding-right: ($grid-gutter-width / 2); + padding-left: ($grid-gutter-width / 2); + border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container } .container { @@ -37,13 +37,13 @@ } @media screen and (min-width: $screen-sm-min) { - padding-top: ($jumbotron-padding * 1.6); + padding-top: ($jumbotron-padding * 1.6); padding-bottom: ($jumbotron-padding * 1.6); .container &, .container-fluid & { - padding-left: ($jumbotron-padding * 2); padding-right: ($jumbotron-padding * 2); + padding-left: ($jumbotron-padding * 2); } h1, diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_labels.scss b/themes/bootstrap3/scss/vendor/bootstrap/_labels.scss index 42ed6ea123273dc395095e96801d2dbefc4e53cb..f7f301392320a19cfbc0cbd3cdc6b3ef71fd73ba 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_labels.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_labels.scss @@ -6,7 +6,7 @@ display: inline; padding: .2em .6em .3em; font-size: 75%; - font-weight: bold; + font-weight: 700; line-height: 1; color: $label-color; text-align: center; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_list-group.scss b/themes/bootstrap3/scss/vendor/bootstrap/_list-group.scss index 7cb83aab05ca09849795a5d8e20527da0e0dc941..529f179e8cdfd874701692c2b7f042594285a563 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_list-group.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_list-group.scss @@ -9,8 +9,8 @@ .list-group { // No need to set list-style: none; since .list-group-item is block level - margin-bottom: 20px; padding-left: 0; // reset padding because ul and ol + margin-bottom: 20px; } @@ -35,44 +35,14 @@ margin-bottom: 0; @include border-bottom-radius($list-group-border-radius); } -} - - -// Interactive list items -// -// Use anchor or button elements instead of `li`s or `div`s to create interactive items. -// Includes an extra `.active` modifier class for showing selected items. - -a.list-group-item, -button.list-group-item { - color: $list-group-link-color; - - .list-group-item-heading { - color: $list-group-link-heading-color; - } - - // Hover state - &:hover, - &:focus { - text-decoration: none; - color: $list-group-link-hover-color; - background-color: $list-group-hover-bg; - } -} - -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item { // Disabled state &.disabled, &.disabled:hover, &.disabled:focus { - background-color: $list-group-disabled-bg; color: $list-group-disabled-color; cursor: $cursor-disabled; + background-color: $list-group-disabled-bg; // Force color to inherit for custom content .list-group-item-heading { @@ -105,6 +75,34 @@ button.list-group-item { } +// Interactive list items +// +// Use anchor or button elements instead of `li`s or `div`s to create interactive items. +// Includes an extra `.active` modifier class for showing selected items. + +a.list-group-item, +button.list-group-item { + color: $list-group-link-color; + + .list-group-item-heading { + color: $list-group-link-heading-color; + } + + // Hover state + &:hover, + &:focus { + color: $list-group-link-hover-color; + text-decoration: none; + background-color: $list-group-hover-bg; + } +} + +button.list-group-item { + width: 100%; + text-align: left; +} + + // Contextual variants // // Add modifier classes to change text and background color on individual items. diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_media.scss b/themes/bootstrap3/scss/vendor/bootstrap/_media.scss index 8c835e861edf28f7c3c49f18caf09d626565e11d..e4ae44573e94448ab26984d10b0a273a7fc0ee17 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_media.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_media.scss @@ -9,8 +9,8 @@ .media, .media-body { - zoom: 1; overflow: hidden; + zoom: 1; } .media-body { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_modals.scss b/themes/bootstrap3/scss/vendor/bootstrap/_modals.scss index 823870f2a4daa5323adb6a0ae0c2355562674afe..942ea8f5b3ab7880f922b6083c0ecdcd46067c93 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_modals.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_modals.scss @@ -14,14 +14,14 @@ // Container that the modal scrolls within .modal { - display: none; - overflow: hidden; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: $zindex-modal; + display: none; + overflow: hidden; -webkit-overflow-scrolling: touch; // Prevent Chrome on Windows from adding a focus outline. For details, see @@ -51,11 +51,11 @@ .modal-content { position: relative; background-color: $modal-content-bg; + background-clip: padding-box; border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc) border: 1px solid $modal-content-border-color; border-radius: $border-radius-large; - @include box-shadow(0 3px 9px rgba(0,0,0,.5)); - background-clip: padding-box; + @include box-shadow(0 3px 9px rgba(0, 0, 0, .5)); // Remove focus outline from opened modal outline: 0; } @@ -108,8 +108,8 @@ // Properly space out buttons .btn + .btn { - margin-left: 5px; margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs + margin-left: 5px; } // but override that for button groups .btn-group .btn + .btn { @@ -138,7 +138,7 @@ margin: 30px auto; } .modal-content { - @include box-shadow(0 5px 15px rgba(0,0,0,.5)); + @include box-shadow(0 5px 15px rgba(0, 0, 0, .5)); } // Modal sizes diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_navbar.scss b/themes/bootstrap3/scss/vendor/bootstrap/_navbar.scss index 11e5c01c15850511711675f0e5a009312e287db2..5d9093a93c974222f6f0217bd627d0c85cdf0950 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_navbar.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_navbar.scss @@ -48,11 +48,11 @@ // content for the user's viewport. .navbar-collapse { - overflow-x: visible; padding-right: $navbar-padding-horizontal; - padding-left: $navbar-padding-horizontal; + padding-left: $navbar-padding-horizontal; + overflow-x: visible; border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255,255,255,.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); @include clearfix; -webkit-overflow-scrolling: touch; @@ -81,8 +81,8 @@ .navbar-fixed-top &, .navbar-static-top &, .navbar-fixed-bottom & { - padding-left: 0; padding-right: 0; + padding-left: 0; } } } @@ -96,6 +96,27 @@ max-height: 200px; } } + + // Fix the top/bottom navbars when screen real estate supports it + position: fixed; + right: 0; + left: 0; + z-index: $zindex-navbar-fixed; + + // Undo the rounded corners + @media (min-width: $grid-float-breakpoint) { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; // override .navbar defaults + border-width: 1px 0 0; } @@ -108,11 +129,11 @@ > .navbar-header, > .navbar-collapse { margin-right: -$navbar-padding-horizontal; - margin-left: -$navbar-padding-horizontal; + margin-left: -$navbar-padding-horizontal; @media (min-width: $grid-float-breakpoint) { margin-right: 0; - margin-left: 0; + margin-left: 0; } } } @@ -134,38 +155,15 @@ } } -// Fix the top/bottom navbars when screen real estate supports it -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: $zindex-navbar-fixed; - - // Undo the rounded corners - @media (min-width: $grid-float-breakpoint) { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; // override .navbar defaults - border-width: 1px 0 0; -} - // Brand/project name .navbar-brand { float: left; + height: $navbar-height; padding: $navbar-padding-vertical $navbar-padding-horizontal; font-size: $font-size-large; line-height: $line-height-computed; - height: $navbar-height; &:hover, &:focus { @@ -193,8 +191,8 @@ .navbar-toggle { position: relative; float: right; - margin-right: $navbar-padding-horizontal; padding: 9px 10px; + margin-right: $navbar-padding-horizontal; @include navbar-vertical-align(34px); background-color: transparent; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 @@ -233,7 +231,7 @@ margin: ($navbar-padding-vertical / 2) (-$navbar-padding-horizontal); > li > a { - padding-top: 10px; + padding-top: 10px; padding-bottom: 10px; line-height: $line-height-computed; } @@ -270,7 +268,7 @@ > li { float: left; > a { - padding-top: $navbar-padding-vertical; + padding-top: $navbar-padding-vertical; padding-bottom: $navbar-padding-vertical; } } @@ -284,12 +282,12 @@ // our navbars. .navbar-form { - margin-left: -$navbar-padding-horizontal; - margin-right: -$navbar-padding-horizontal; padding: 10px $navbar-padding-horizontal; + margin-right: -$navbar-padding-horizontal; + margin-left: -$navbar-padding-horizontal; border-top: 1px solid transparent; border-bottom: 1px solid transparent; - $shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); + $shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); @include box-shadow($shadow); // Mixin behavior for optimum display @@ -311,11 +309,11 @@ // Undo 100% width for pull classes @media (min-width: $grid-float-breakpoint) { width: auto; - border: 0; - margin-left: 0; - margin-right: 0; padding-top: 0; padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; @include box-shadow(none); } } @@ -361,8 +359,8 @@ @media (min-width: $grid-float-breakpoint) { float: left; - margin-left: $navbar-padding-horizontal; margin-right: $navbar-padding-horizontal; + margin-left: $navbar-padding-horizontal; } } @@ -437,33 +435,15 @@ background-color: $navbar-default-link-disabled-bg; } } - } - - .navbar-toggle { - border-color: $navbar-default-toggle-border-color; - &:hover, - &:focus { - background-color: $navbar-default-toggle-hover-bg; - } - .icon-bar { - background-color: $navbar-default-toggle-icon-bar-bg; - } - } - .navbar-collapse, - .navbar-form { - border-color: $navbar-default-border; - } - - // Dropdown menu items - .navbar-nav { + // Dropdown menu items // Remove background color from open dropdown > .open > a { &, &:hover, &:focus { - background-color: $navbar-default-link-active-bg; color: $navbar-default-link-active-color; + background-color: $navbar-default-link-active-bg; } } @@ -498,6 +478,22 @@ } } + .navbar-toggle { + border-color: $navbar-default-toggle-border-color; + &:hover, + &:focus { + background-color: $navbar-default-toggle-hover-bg; + } + .icon-bar { + background-color: $navbar-default-toggle-icon-bar-bg; + } + } + + .navbar-collapse, + .navbar-form { + border-color: $navbar-default-border; + } + // Links in navbars // @@ -571,33 +567,14 @@ background-color: $navbar-inverse-link-disabled-bg; } } - } - - // Darken the responsive nav toggle - .navbar-toggle { - border-color: $navbar-inverse-toggle-border-color; - &:hover, - &:focus { - background-color: $navbar-inverse-toggle-hover-bg; - } - .icon-bar { - background-color: $navbar-inverse-toggle-icon-bar-bg; - } - } - .navbar-collapse, - .navbar-form { - border-color: darken($navbar-inverse-bg, 7%); - } - - // Dropdowns - .navbar-nav { + // Dropdowns > .open > a { &, &:hover, &:focus { - background-color: $navbar-inverse-link-active-bg; color: $navbar-inverse-link-active-color; + background-color: $navbar-inverse-link-active-bg; } } @@ -638,6 +615,23 @@ } } + // Darken the responsive nav toggle + .navbar-toggle { + border-color: $navbar-inverse-toggle-border-color; + &:hover, + &:focus { + background-color: $navbar-inverse-toggle-hover-bg; + } + .icon-bar { + background-color: $navbar-inverse-toggle-icon-bar-bg; + } + } + + .navbar-collapse, + .navbar-form { + border-color: darken($navbar-inverse-bg, 7%); + } + .navbar-link { color: $navbar-inverse-link-color; &:hover { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_navs.scss b/themes/bootstrap3/scss/vendor/bootstrap/_navs.scss index 9d369f307917e557b53e3aeb9e800708b3aadb6b..f4f0a55bae910c8f57437da8a186d1ea4f877713 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_navs.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_navs.scss @@ -7,8 +7,8 @@ // -------------------------------------------------- .nav { - margin-bottom: 0; padding-left: 0; // Override default ul/ol + margin-bottom: 0; list-style: none; @include clearfix; @@ -35,8 +35,8 @@ &:focus { color: $nav-disabled-link-hover-color; text-decoration: none; - background-color: transparent; cursor: $cursor-disabled; + background-color: transparent; } } } @@ -97,10 +97,10 @@ &:hover, &:focus { color: $nav-tabs-active-link-hover-color; + cursor: default; background-color: $nav-tabs-active-link-hover-bg; border: 1px solid $nav-tabs-active-link-hover-border-color; border-bottom-color: transparent; - cursor: default; } } } @@ -163,8 +163,8 @@ > li { float: none; > a { - text-align: center; margin-bottom: 5px; + text-align: center; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_normalize.scss b/themes/bootstrap3/scss/vendor/bootstrap/_normalize.scss index 9dddf73ad2924561afa704701655f2cbc011d7df..7850b9a41e95acd4b87130a934e955e6ee65ca2f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_normalize.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_normalize.scss @@ -104,11 +104,14 @@ a:hover { // ========================================================================== // -// Address styling not present in IE 8/9/10/11, Safari, and Chrome. +// 1. Remove the bottom border in Chrome 57- and Firefox 39-. +// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. // abbr[title] { - border-bottom: 1px dotted; + border-bottom: none; // 1 + text-decoration: underline; // 2 + text-decoration: underline dotted; // 2 } // diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_pager.scss b/themes/bootstrap3/scss/vendor/bootstrap/_pager.scss index c2342174ff3713003e0417b18271ef3e609475c7..07622389e9d4d97d55569363ea9d83403a52572a 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_pager.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_pager.scss @@ -6,8 +6,8 @@ .pager { padding-left: 0; margin: $line-height-computed 0; - list-style: none; text-align: center; + list-style: none; @include clearfix; li { display: inline; @@ -47,8 +47,8 @@ > a:focus, > span { color: $pager-disabled-color; - background-color: $pager-bg; cursor: $cursor-disabled; + background-color: $pager-bg; } } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_pagination.scss b/themes/bootstrap3/scss/vendor/bootstrap/_pagination.scss index fecfa9c6421106f05dd37023620a477012f2e9e9..c53082877eaeea4462d85815565e2c557a27394f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_pagination.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_pagination.scss @@ -14,12 +14,20 @@ position: relative; float: left; // Collapse white-space padding: $padding-base-vertical $padding-base-horizontal; + margin-left: -1px; line-height: $line-height-base; - text-decoration: none; color: $pagination-color; + text-decoration: none; background-color: $pagination-bg; border: 1px solid $pagination-border; - margin-left: -1px; + + &:hover, + &:focus { + z-index: 2; + color: $pagination-hover-color; + background-color: $pagination-hover-bg; + border-color: $pagination-hover-border; + } } &:first-child { > a, @@ -36,17 +44,6 @@ } } - > li > a, - > li > span { - &:hover, - &:focus { - z-index: 2; - color: $pagination-hover-color; - background-color: $pagination-hover-bg; - border-color: $pagination-hover-border; - } - } - > .active > a, > .active > span { &, @@ -54,9 +51,9 @@ &:focus { z-index: 3; color: $pagination-active-color; + cursor: default; background-color: $pagination-active-bg; border-color: $pagination-active-border; - cursor: default; } } @@ -68,9 +65,9 @@ > a:hover, > a:focus { color: $pagination-disabled-color; + cursor: $cursor-disabled; background-color: $pagination-disabled-bg; border-color: $pagination-disabled-border; - cursor: $cursor-disabled; } } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_panels.scss b/themes/bootstrap3/scss/vendor/bootstrap/_panels.scss index 6c568def47b5a219a8a661b52cb7fd72b8c61b32..8947ed254e432c122f0d17d18914e33b65c756c4 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_panels.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_panels.scss @@ -9,7 +9,7 @@ background-color: $panel-bg; border: 1px solid transparent; border-radius: $panel-border-radius; - @include box-shadow(0 1px 1px rgba(0,0,0,.05)); + @include box-shadow(0 1px 1px rgba(0, 0, 0, .05)); } // Panel contents @@ -113,8 +113,8 @@ margin-bottom: 0; caption { - padding-left: $panel-body-padding; padding-right: $panel-body-padding; + padding-left: $panel-body-padding; } } // Add border top radius for first one @@ -147,8 +147,8 @@ > tbody:last-child, > tfoot:last-child { > tr:last-child { - border-bottom-left-radius: ($panel-border-radius - 1); border-bottom-right-radius: ($panel-border-radius - 1); + border-bottom-left-radius: ($panel-border-radius - 1); td:first-child, th:first-child { @@ -208,8 +208,8 @@ } } > .table-responsive { - border: 0; margin-bottom: 0; + border: 0; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_popovers.scss b/themes/bootstrap3/scss/vendor/bootstrap/_popovers.scss index 9b90a2e964e39dee9ad208b544a2a9b538c92b08..6f83842280e02094e223eb7a4a51ae13539039ad 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_popovers.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_popovers.scss @@ -15,99 +15,81 @@ // So reset our font and text properties to avoid inheriting weird values. @include reset-text; font-size: $font-size-base; - background-color: $popover-bg; background-clip: padding-box; border: 1px solid $popover-fallback-border-color; border: 1px solid $popover-border-color; border-radius: $border-radius-large; - @include box-shadow(0 5px 10px rgba(0,0,0,.2)); + @include box-shadow(0 5px 10px rgba(0, 0, 0, .2)); // Offset the popover to account for the popover arrow - &.top { margin-top: -$popover-arrow-width; } - &.right { margin-left: $popover-arrow-width; } - &.bottom { margin-top: $popover-arrow-width; } - &.left { margin-left: -$popover-arrow-width; } -} + &.top { margin-top: -$popover-arrow-width; } + &.right { margin-left: $popover-arrow-width; } + &.bottom { margin-top: $popover-arrow-width; } + &.left { margin-left: -$popover-arrow-width; } -.popover-title { - margin: 0; // reset heading margin - padding: 8px 14px; - font-size: $font-size-base; - background-color: $popover-title-bg; - border-bottom: 1px solid darken($popover-title-bg, 5%); - border-radius: ($border-radius-large - 1) ($border-radius-large - 1) 0 0; -} + // Arrows + // .arrow is outer, .arrow:after is inner + > .arrow { + border-width: $popover-arrow-outer-width; -.popover-content { - padding: 9px 14px; -} - -// Arrows -// -// .arrow is outer, .arrow:after is inner + &, + &:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + } -.popover > .arrow { - &, - &:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + &:after { + content: ""; + border-width: $popover-arrow-width; + } } -} -.popover > .arrow { - border-width: $popover-arrow-outer-width; -} -.popover > .arrow:after { - border-width: $popover-arrow-width; - content: ""; -} -.popover { &.top > .arrow { + bottom: -$popover-arrow-outer-width; left: 50%; margin-left: -$popover-arrow-outer-width; - border-bottom-width: 0; border-top-color: $popover-arrow-outer-fallback-color; // IE8 fallback border-top-color: $popover-arrow-outer-color; - bottom: -$popover-arrow-outer-width; + border-bottom-width: 0; &:after { - content: " "; bottom: 1px; margin-left: -$popover-arrow-width; - border-bottom-width: 0; + content: " "; border-top-color: $popover-arrow-color; + border-bottom-width: 0; } } &.right > .arrow { top: 50%; left: -$popover-arrow-outer-width; margin-top: -$popover-arrow-outer-width; - border-left-width: 0; border-right-color: $popover-arrow-outer-fallback-color; // IE8 fallback border-right-color: $popover-arrow-outer-color; + border-left-width: 0; &:after { - content: " "; - left: 1px; bottom: -$popover-arrow-width; - border-left-width: 0; + left: 1px; + content: " "; border-right-color: $popover-arrow-color; + border-left-width: 0; } } &.bottom > .arrow { + top: -$popover-arrow-outer-width; left: 50%; margin-left: -$popover-arrow-outer-width; border-top-width: 0; border-bottom-color: $popover-arrow-outer-fallback-color; // IE8 fallback border-bottom-color: $popover-arrow-outer-color; - top: -$popover-arrow-outer-width; &:after { - content: " "; top: 1px; margin-left: -$popover-arrow-width; + content: " "; border-top-width: 0; border-bottom-color: $popover-arrow-color; } @@ -121,11 +103,24 @@ border-left-color: $popover-arrow-outer-fallback-color; // IE8 fallback border-left-color: $popover-arrow-outer-color; &:after { - content: " "; right: 1px; + bottom: -$popover-arrow-width; + content: " "; border-right-width: 0; border-left-color: $popover-arrow-color; - bottom: -$popover-arrow-width; } } } + +.popover-title { + padding: 8px 14px; + margin: 0; // reset heading margin + font-size: $font-size-base; + background-color: $popover-title-bg; + border-bottom: 1px solid darken($popover-title-bg, 5%); + border-radius: ($border-radius-large - 1) ($border-radius-large - 1) 0 0; +} + +.popover-content { + padding: 9px 14px; +} diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_print.scss b/themes/bootstrap3/scss/vendor/bootstrap/_print.scss index 66e54ab489ea278cab3ac847d59449b9bcea9020..564f304dd6c9e7b67184c34d69ff95229c70a09f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_print.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_print.scss @@ -6,96 +6,94 @@ // ========================================================================== @media print { - *, - *:before, - *:after { - background: transparent !important; - color: #000 !important; // Black prints faster: h5bp.com/s - box-shadow: none !important; - text-shadow: none !important; - } - - a, - a:visited { - text-decoration: underline; - } - - a[href]:after { - content: " (" attr(href) ")"; - } - - abbr[title]:after { - content: " (" attr(title) ")"; - } - - // Don't show links that are fragment identifiers, - // or use the `javascript:` pseudo protocol - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - - thead { - display: table-header-group; // h5bp.com/t - } - - tr, - img { - page-break-inside: avoid; - } - - img { - max-width: 100% !important; - } - - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - - h2, - h3 { - page-break-after: avoid; - } - - // Bootstrap specific changes start - - // Bootstrap components - .navbar { - display: none; - } - .btn, - .dropup > .btn { - > .caret { - border-top-color: #000 !important; - } - } - .label { - border: 1px solid #000; - } - - .table { - border-collapse: collapse !important; - - td, - th { - background-color: #fff !important; - } - } - .table-bordered { - th, - td { - border: 1px solid #ddd !important; - } - } - - // Bootstrap specific changes end + *, + *:before, + *:after { + color: #000 !important; // Black prints faster: h5bp.com/s + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + // Don't show links that are fragment identifiers, + // or use the `javascript:` pseudo protocol + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; // h5bp.com/t + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + // Bootstrap specific changes start + + // Bootstrap components + .navbar { + display: none; + } + .btn, + .dropup > .btn { + > .caret { + border-top-color: #000 !important; + } + } + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + + td, + th { + background-color: #fff !important; + } + } + .table-bordered { + th, + td { + border: 1px solid #ddd !important; + } + } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_progress-bars.scss b/themes/bootstrap3/scss/vendor/bootstrap/_progress-bars.scss index 343df6323c59464cf8088d9c136ace5c29637758..e7897dee630774516fd483781e4f02745c2f70b8 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_progress-bars.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_progress-bars.scss @@ -24,12 +24,12 @@ // Outer container .progress { - overflow: hidden; height: $line-height-computed; margin-bottom: $line-height-computed; + overflow: hidden; background-color: $progress-bg; border-radius: $progress-border-radius; - @include box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); + @include box-shadow(inset 0 1px 2px rgba(0, 0, 0, .1)); } // Bar of progress @@ -42,7 +42,7 @@ color: $progress-bar-color; text-align: center; background-color: $progress-bar-bg; - @include box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); + @include box-shadow(inset 0 -1px 0 rgba(0, 0, 0, .15)); @include transition(width .6s ease); } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_responsive-embed.scss b/themes/bootstrap3/scss/vendor/bootstrap/_responsive-embed.scss index 080a5118fe9ab2af331e6b1444fff4be840ecc03..5a0e0b88608e76c693b8be84c507b99a6060a00a 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_responsive-embed.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_responsive-embed.scss @@ -16,10 +16,10 @@ video { position: absolute; top: 0; - left: 0; bottom: 0; - height: 100%; + left: 0; width: 100%; + height: 100%; border: 0; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_responsive-utilities.scss b/themes/bootstrap3/scss/vendor/bootstrap/_responsive-utilities.scss index f3f0c839beca5d7d5064b49a0bbd48af7a0c8665..73641aae7fa67e6f498abb02ba8da59ca2f890f7 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_responsive-utilities.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_responsive-utilities.scss @@ -14,9 +14,9 @@ // For more information, see the following: // // Issue: https://github.com/twbs/bootstrap/issues/10497 -// Docs: http://getbootstrap.com/getting-started/#support-ie10-width -// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/ -// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ +// Docs: https://getbootstrap.com/docs/3.4/getting-started/#support-ie10-width +// Source: https://timkadlec.com/2013/01/windows-phone-8-and-device-width/ +// Source: https://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ @at-root { @-ms-viewport { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_scaffolding.scss b/themes/bootstrap3/scss/vendor/bootstrap/_scaffolding.scss index 362c7e2a13345957de5f40ca1891c1b44c22f8fb..7fda593848a3715a08228034c7dfcadf8cf53b29 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_scaffolding.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_scaffolding.scss @@ -7,7 +7,7 @@ // // Heads up! This reset may cause conflicts with some third-party widgets. // For recommendations on resolving such conflicts, see -// http://getbootstrap.com/getting-started/#third-box-sizing +// https://getbootstrap.com/docs/3.4/getting-started/#third-box-sizing * { @include box-sizing(border-box); } @@ -21,7 +21,7 @@ html { font-size: 10px; - -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { @@ -111,7 +111,7 @@ img { // Horizontal rules hr { - margin-top: $line-height-computed; + margin-top: $line-height-computed; margin-bottom: $line-height-computed; border: 0; border-top: 1px solid $hr-border; @@ -120,21 +120,21 @@ hr { // Only display content to screen readers // -// See: http://a11yproject.com/posts/how-to-hide-content +// See: https://a11yproject.com/posts/how-to-hide-content .sr-only { position: absolute; width: 1px; height: 1px; - margin: -1px; padding: 0; + margin: -1px; overflow: hidden; - clip: rect(0,0,0,0); + clip: rect(0, 0, 0, 0); border: 0; } // Use in conjunction with .sr-only to only display content when it's focused. -// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 +// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 // Credit: HTML5 Boilerplate .sr-only-focusable { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_tables.scss b/themes/bootstrap3/scss/vendor/bootstrap/_tables.scss index affcc58c0b0f80388f291c73451da8e38c8f9280..7bff4b0450bb35230b7147a3a6db0867b8a618d7 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_tables.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_tables.scss @@ -5,13 +5,34 @@ table { background-color: $table-bg; + + // Table cell sizing + // + // Reset default table behavior + + col[class*="col-"] { + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) + display: table-column; + float: none; + } + + td, + th { + &[class*="col-"] { + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) + display: table-cell; + float: none; + } + } } + caption { padding-top: $table-cell-padding; padding-bottom: $table-cell-padding; color: $text-muted; text-align: left; } + th { text-align: left; } @@ -128,27 +149,6 @@ th { } -// Table cell sizing -// -// Reset default table behavior - -table col[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-column; -} -table { - td, - th { - &[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-cell; - } - } -} - - // Table backgrounds // // Exact selectors below required to override `.table-striped` and prevent @@ -169,12 +169,12 @@ table { // will display normally. .table-responsive { + min-height: .01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837) overflow-x: auto; - min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837) @media screen and (max-width: $screen-xs-max) { width: 100%; - margin-bottom: ($line-height-computed * 0.75); + margin-bottom: ($line-height-computed * .75); overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid $table-border-color; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_theme.scss b/themes/bootstrap3/scss/vendor/bootstrap/_theme.scss index c1b0e9c609fda9a5ab22698e988506078a6d627f..0ce703acdb671d9549fac25799ec0fe62929113b 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_theme.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_theme.scss @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -23,14 +23,14 @@ .btn-info, .btn-warning, .btn-danger { - text-shadow: 0 -1px 0 rgba(0,0,0,.2); - $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + $shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); @include box-shadow($shadow); // Reset the shadow &:active, &.active { - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + @include box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); } &.disabled, @@ -88,7 +88,11 @@ } // Apply the mixin to the buttons -.btn-default { @include btn-styles($btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; } +.btn-default { + @include btn-styles($btn-default-bg); + text-shadow: 0 1px 0 #fff; + border-color: #ccc; +} .btn-primary { @include btn-styles($btn-primary-bg); } .btn-success { @include btn-styles($btn-success-bg); } .btn-info { @include btn-styles($btn-info-bg); } @@ -102,7 +106,7 @@ .thumbnail, .img-thumbnail { - @include box-shadow(0 1px 2px rgba(0,0,0,.075)); + @include box-shadow(0 1px 2px rgba(0, 0, 0, .075)); } @@ -132,18 +136,18 @@ @include gradient-vertical($start-color: lighten($navbar-default-bg, 10%), $end-color: $navbar-default-bg); @include reset-filter; // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered border-radius: $navbar-border-radius; - $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075); + $shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); @include box-shadow($shadow); .navbar-nav > .open > a, .navbar-nav > .active > a { @include gradient-vertical($start-color: darken($navbar-default-link-active-bg, 5%), $end-color: darken($navbar-default-link-active-bg, 2%)); - @include box-shadow(inset 0 3px 9px rgba(0,0,0,.075)); + @include box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075)); } } .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255,255,255,.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); } // Inverted navbar @@ -154,12 +158,12 @@ .navbar-nav > .open > a, .navbar-nav > .active > a { @include gradient-vertical($start-color: $navbar-inverse-link-active-bg, $end-color: lighten($navbar-inverse-link-active-bg, 2.5%)); - @include box-shadow(inset 0 3px 9px rgba(0,0,0,.25)); + @include box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25)); } .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0,0,0,.25); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); } } @@ -189,8 +193,8 @@ // Common styles .alert { - text-shadow: 0 1px 0 rgba(255,255,255,.2); - $shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05); + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + $shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); @include box-shadow($shadow); } @@ -241,7 +245,7 @@ .list-group { border-radius: $border-radius-base; - @include box-shadow(0 1px 2px rgba(0,0,0,.075)); + @include box-shadow(0 1px 2px rgba(0, 0, 0, .075)); } .list-group-item.active, .list-group-item.active:hover, @@ -262,7 +266,7 @@ // Common styles .panel { - @include box-shadow(0 1px 2px rgba(0,0,0,.05)); + @include box-shadow(0 1px 2px rgba(0, 0, 0, .05)); } // Mixin for generating new styles @@ -286,6 +290,6 @@ .well { @include gradient-vertical($start-color: darken($well-bg, 5%), $end-color: $well-bg); border-color: darken($well-bg, 10%); - $shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); + $shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); @include box-shadow($shadow); } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_thumbnails.scss b/themes/bootstrap3/scss/vendor/bootstrap/_thumbnails.scss index da0e1e76cf01131006ae0c188d81d3f1470ad197..835452f3b6a01fc85f9f6704c1c563dd5a8f4bfb 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_thumbnails.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_thumbnails.scss @@ -17,8 +17,8 @@ > img, a > img { @include img-responsive; - margin-left: auto; margin-right: auto; + margin-left: auto; } // [converter] extracted a&:hover, a&:focus, a&.active to a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_tooltip.scss b/themes/bootstrap3/scss/vendor/bootstrap/_tooltip.scss index f0c165827434484c9121d320324284b265ace7f1..fa69a81ece7cdff1b91115986c3ca65ddc841525 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_tooltip.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_tooltip.scss @@ -15,33 +15,25 @@ @include opacity(0); - &.in { @include opacity($tooltip-opacity); } - &.top { margin-top: -3px; padding: $tooltip-arrow-width 0; } - &.right { margin-left: 3px; padding: 0 $tooltip-arrow-width; } - &.bottom { margin-top: 3px; padding: $tooltip-arrow-width 0; } - &.left { margin-left: -3px; padding: 0 $tooltip-arrow-width; } -} - -// Wrapper for the tooltip content -.tooltip-inner { - max-width: $tooltip-max-width; - padding: 3px 8px; - color: $tooltip-color; - text-align: center; - background-color: $tooltip-bg; - border-radius: $border-radius-base; -} + &.in { @include opacity($tooltip-opacity); } + &.top { + padding: $tooltip-arrow-width 0; + margin-top: -3px; + } + &.right { + padding: 0 $tooltip-arrow-width; + margin-left: 3px; + } + &.bottom { + padding: $tooltip-arrow-width 0; + margin-top: 3px; + } + &.left { + padding: 0 $tooltip-arrow-width; + margin-left: -3px; + } -// Arrows -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 -.tooltip { + // Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 &.top .tooltip-arrow { bottom: 0; left: 50%; @@ -50,8 +42,8 @@ border-top-color: $tooltip-arrow-color; } &.top-left .tooltip-arrow { - bottom: 0; right: $tooltip-arrow-width; + bottom: 0; margin-bottom: -$tooltip-arrow-width; border-width: $tooltip-arrow-width $tooltip-arrow-width 0; border-top-color: $tooltip-arrow-color; @@ -99,3 +91,22 @@ border-bottom-color: $tooltip-arrow-color; } } + +// Wrapper for the tooltip content +.tooltip-inner { + max-width: $tooltip-max-width; + padding: 3px 8px; + color: $tooltip-color; + text-align: center; + background-color: $tooltip-bg; + border-radius: $border-radius-base; +} + +// Arrows +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_type.scss b/themes/bootstrap3/scss/vendor/bootstrap/_type.scss index 620796adc1e0a5c3a75a33a7175e238a92ee034f..c63cc4c071cb6c5f4dd51fdc0fac035b28488813 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_type.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_type.scss @@ -15,7 +15,7 @@ h1, h2, h3, h4, h5, h6, small, .small { - font-weight: normal; + font-weight: 400; line-height: 1; color: $headings-small-color; } @@ -82,8 +82,8 @@ small, mark, .mark { - background-color: $state-warning-bg; padding: .2em; + background-color: $state-warning-bg; } // Alignment @@ -176,8 +176,8 @@ ol { > li { display: inline-block; - padding-left: 5px; padding-right: 5px; + padding-left: 5px; } } @@ -191,7 +191,7 @@ dd { line-height: $line-height-base; } dt { - font-weight: bold; + font-weight: 700; } dd { margin-left: 0; // Undo browser default @@ -226,12 +226,12 @@ dd { // ------------------------- // Abbreviations and acronyms -abbr[title], // Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257 +abbr[title], abbr[data-original-title] { cursor: help; - border-bottom: 1px dotted $abbr-border-color; } + .initialism { font-size: 90%; @extend .text-uppercase; @@ -263,7 +263,7 @@ blockquote { color: $blockquote-small-color; &:before { - content: '\2014 \00A0'; // em dash, nbsp + content: "\2014 \00A0"; // em dash, nbsp } } } @@ -275,17 +275,17 @@ blockquote { blockquote.pull-right { padding-right: 15px; padding-left: 0; + text-align: right; border-right: 5px solid $blockquote-border-color; border-left: 0; - text-align: right; // Account for citation footer, small, .small { - &:before { content: ''; } + &:before { content: ""; } &:after { - content: '\00A0 \2014'; // nbsp, em dash + content: "\00A0 \2014"; // nbsp, em dash } } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_variables.scss b/themes/bootstrap3/scss/vendor/bootstrap/_variables.scss index e04968529171ed730a99e741dea4a2d593be0ebb..898ef14adc9a68348f7faf0f6fac0a1e90b50b50 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_variables.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_variables.scss @@ -51,14 +51,14 @@ $font-family-base: $font-family-sans-serif !default; $font-size-base: 14px !default; $font-size-large: ceil(($font-size-base * 1.25)) !default; // ~18px -$font-size-small: ceil(($font-size-base * 0.85)) !default; // ~12px +$font-size-small: ceil(($font-size-base * .85)) !default; // ~12px $font-size-h1: floor(($font-size-base * 2.6)) !default; // ~36px $font-size-h2: floor(($font-size-base * 2.15)) !default; // ~30px $font-size-h3: ceil(($font-size-base * 1.7)) !default; // ~24px $font-size-h4: ceil(($font-size-base * 1.25)) !default; // ~18px $font-size-h5: $font-size-base !default; -$font-size-h6: ceil(($font-size-base * 0.85)) !default; // ~12px +$font-size-h6: ceil(($font-size-base * .85)) !default; // ~12px //** Unit-less `line-height` for use in components like buttons. $line-height-base: 1.428571429 !default; // 20/14 @@ -239,7 +239,7 @@ $cursor-disabled: not-allowed !default; //** Background for the dropdown menu. $dropdown-bg: #fff !default; //** Dropdown menu `border-color`. -$dropdown-border: rgba(0,0,0,.15) !default; +$dropdown-border: rgba(0, 0, 0, .15) !default; //** Dropdown menu `border-color` **for IE8**. $dropdown-fallback-border: #ccc !default; //** Divider color for between dropdown items. @@ -545,7 +545,7 @@ $popover-bg: #fff !default; //** Popover maximum width $popover-max-width: 276px !default; //** Popover border color -$popover-border-color: rgba(0,0,0,.2) !default; +$popover-border-color: rgba(0, 0, 0, .2) !default; //** Popover fallback border color $popover-fallback-border-color: #ccc !default; @@ -603,7 +603,7 @@ $modal-title-line-height: $line-height-base !default; //** Background color of modal content area $modal-content-bg: #fff !default; //** Modal content border color -$modal-content-border-color: rgba(0,0,0,.2) !default; +$modal-content-border-color: rgba(0, 0, 0, .2) !default; //** Modal content border color **for IE8** $modal-content-fallback-border-color: #999 !default; @@ -808,7 +808,7 @@ $breadcrumb-separator: "/" !default; // //## -$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; +$carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6) !default; $carousel-control-color: #fff !default; $carousel-control-width: 15% !default; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/_wells.scss b/themes/bootstrap3/scss/vendor/bootstrap/_wells.scss index b8657118a661cfb1f6119f7dccb169db06e4cd04..9a048bdd0c4d6f8b49264938b5b9d02f925d5158 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/_wells.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/_wells.scss @@ -11,10 +11,10 @@ background-color: $well-bg; border: 1px solid $well-border; border-radius: $border-radius-base; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); + @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .05)); blockquote { border-color: #ddd; - border-color: rgba(0,0,0,.15); + border-color: rgba(0, 0, 0, .15); } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_alerts.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_alerts.scss index 3faf0b5a507d799af422ac2b65f20ef155781830..b1e6df9d2406e41ce0d1b1f0db62e630d0609080 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_alerts.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_alerts.scss @@ -1,13 +1,14 @@ // Alerts @mixin alert-variant($background, $border, $text-color) { + color: $text-color; background-color: $background; border-color: $border; - color: $text-color; hr { border-top-color: darken($border, 5%); } + .alert-link { color: darken($text-color, 10%); } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_border-radius.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_border-radius.scss index ce1949987508574a8d31b1d688096ce8925ed051..e03c390804897079b1b4765e96e5159233bb045d 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_border-radius.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_border-radius.scss @@ -1,18 +1,18 @@ // Single side border-radius @mixin border-top-radius($radius) { + border-top-left-radius: $radius; border-top-right-radius: $radius; - border-top-left-radius: $radius; } @mixin border-right-radius($radius) { + border-top-right-radius: $radius; border-bottom-right-radius: $radius; - border-top-right-radius: $radius; } @mixin border-bottom-radius($radius) { border-bottom-right-radius: $radius; - border-bottom-left-radius: $radius; + border-bottom-left-radius: $radius; } @mixin border-left-radius($radius) { + border-top-left-radius: $radius; border-bottom-left-radius: $radius; - border-top-left-radius: $radius; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_buttons.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_buttons.scss index b93f84b2cb69d72278590188f862e06853451afd..5afa735e8ef5710dfffa2cae6ec3c1c03a518a17 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_buttons.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_buttons.scss @@ -12,33 +12,29 @@ &.focus { color: $color; background-color: darken($background, 10%); - border-color: darken($border, 25%); + border-color: darken($border, 25%); } &:hover { color: $color; background-color: darken($background, 10%); - border-color: darken($border, 12%); + border-color: darken($border, 12%); } &:active, &.active, .open > &.dropdown-toggle { color: $color; background-color: darken($background, 10%); - border-color: darken($border, 12%); + background-image: none; + border-color: darken($border, 12%); &:hover, &:focus, &.focus { color: $color; background-color: darken($background, 17%); - border-color: darken($border, 25%); + border-color: darken($border, 25%); } } - &:active, - &.active, - .open > &.dropdown-toggle { - background-image: none; - } &.disabled, &[disabled], fieldset[disabled] & { @@ -46,7 +42,7 @@ &:focus, &.focus { background-color: $background; - border-color: $border; + border-color: $border; } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_center-block.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_center-block.scss index e06fb5e276e471ac4bd574068254808089695afd..ed69097f5bbd727b091a5dd5a3dbb39dd0265a1b 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_center-block.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_center-block.scss @@ -2,6 +2,6 @@ @mixin center-block() { display: block; - margin-left: auto; margin-right: auto; + margin-left: auto; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_clearfix.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_clearfix.scss index dc3e2ab426edf4d5ae1f27d5c767ff396f359243..e45eca50eacb7b9813aab24840f42c447f9f7294 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_clearfix.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_clearfix.scss @@ -13,8 +13,8 @@ @mixin clearfix() { &:before, &:after { - content: " "; // 1 display: table; // 2 + content: " "; // 1 } &:after { clear: both; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_forms.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_forms.scss index 277aa5f8e1872166a784a188a36d90ab4ba6a3bc..46578a14b0d8a089fa98f82cb6bd460d5852ded8 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_forms.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_forms.scss @@ -20,18 +20,18 @@ // Set the border and box shadow on specific inputs to match .form-control { border-color: $border-color; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work + @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); // Redeclare so transitions work &:focus { border-color: darken($border-color, 10%); - $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); + $shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px lighten($border-color, 20%); @include box-shadow($shadow); } } // Set validation states also for addons .input-group-addon { color: $text-color; - border-color: $border-color; background-color: $background-color; + border-color: $border-color; } // Optional feedback icon .form-control-feedback { @@ -57,7 +57,7 @@ &:focus { border-color: $color; outline: 0; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); + @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px $color-rgba); } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_gradients.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_gradients.scss index a8939f5ae6411aa9f9dabce969e1a20760eb0ef2..fd814407ea34e036a232861ff54b041d92d80e5f 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_gradients.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_gradients.scss @@ -1,5 +1,3 @@ -// Gradients - // Horizontal gradient, from left to right @@ -10,8 +8,8 @@ background-image: -webkit-linear-gradient(left, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient(left, $start-color $start-percent, $end-color $end-percent); // Opera 12 background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ - background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down + background-repeat: repeat-x; } // Vertical gradient, from top to bottom @@ -22,36 +20,36 @@ background-image: -webkit-linear-gradient(top, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient(top, $start-color $start-percent, $end-color $end-percent); // Opera 12 background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ - background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down + background-repeat: repeat-x; } @mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) { - background-repeat: repeat-x; background-image: -webkit-linear-gradient($deg, $start-color, $end-color); // Safari 5.1-6, Chrome 10+ background-image: -o-linear-gradient($deg, $start-color, $end-color); // Opera 12 background-image: linear-gradient($deg, $start-color, $end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + background-repeat: repeat-x; } @mixin gradient-horizontal-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { background-image: -webkit-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color); background-image: -o-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color); background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color); - background-repeat: no-repeat; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down, gets no color-stop at all for proper fallback + background-repeat: no-repeat; } @mixin gradient-vertical-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { background-image: -webkit-linear-gradient($start-color, $mid-color $color-stop, $end-color); background-image: -o-linear-gradient($start-color, $mid-color $color-stop, $end-color); background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color); - background-repeat: no-repeat; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down, gets no color-stop at all for proper fallback + background-repeat: no-repeat; } @mixin gradient-radial($inner-color: #555, $outer-color: #333) { background-image: -webkit-radial-gradient(circle, $inner-color, $outer-color); background-image: radial-gradient(circle, $inner-color, $outer-color); background-repeat: no-repeat; } -@mixin gradient-striped($color: rgba(255,255,255,.15), $angle: 45deg) { +@mixin gradient-striped($color: rgba(255, 255, 255, .15), $angle: 45deg) { background-image: -webkit-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); background-image: -o-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid-framework.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid-framework.scss index 16d038c04f3b1993608a76fd773eb39ec141dfa1..2b84cb13c8282f3802f0287f9dba59c48f4f093c 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid-framework.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid-framework.scss @@ -13,8 +13,8 @@ // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding - padding-left: ceil(($grid-gutter-width / 2)); padding-right: floor(($grid-gutter-width / 2)); + padding-left: ceil(($grid-gutter-width / 2)); } } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid.scss index 59551dac1eda335f9d73112a4b414abadf232bfc..884ac4f5b0d6829cbb1fb567c4e5b5dab1af4442 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_grid.scss @@ -4,17 +4,17 @@ // Centered container element @mixin container-fixed($gutter: $grid-gutter-width) { + padding-right: ceil(($gutter / 2)); + padding-left: floor(($gutter / 2)); margin-right: auto; margin-left: auto; - padding-left: floor(($gutter / 2)); - padding-right: ceil(($gutter / 2)); @include clearfix; } // Creates a wrapper for a series of columns @mixin make-row($gutter: $grid-gutter-width) { - margin-left: ceil(($gutter / -2)); margin-right: floor(($gutter / -2)); + margin-left: ceil(($gutter / -2)); @include clearfix; } @@ -24,8 +24,8 @@ float: left; width: percentage(($columns / $grid-columns)); min-height: 1px; - padding-left: ($gutter / 2); padding-right: ($gutter / 2); + padding-left: ($gutter / 2); } @mixin make-xs-column-offset($columns) { margin-left: percentage(($columns / $grid-columns)); @@ -41,8 +41,8 @@ @mixin make-sm-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-left: ($gutter / 2); padding-right: ($gutter / 2); + padding-left: ($gutter / 2); @media (min-width: $screen-sm-min) { float: left; @@ -69,8 +69,8 @@ @mixin make-md-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-left: ($gutter / 2); padding-right: ($gutter / 2); + padding-left: ($gutter / 2); @media (min-width: $screen-md-min) { float: left; @@ -97,8 +97,8 @@ @mixin make-lg-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-left: ($gutter / 2); padding-right: ($gutter / 2); + padding-left: ($gutter / 2); @media (min-width: $screen-lg-min) { float: left; diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_image.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_image.scss index c8dcf5e9cd867de4d0ba528736719483266a1ae0..b5a109b209d45f54ec03fa93258dcf89096867cf 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_image.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_image.scss @@ -1,8 +1,3 @@ -// Image Mixins -// - Responsive image -// - Retina image - - // Responsive image // // Keep images from scaling beyond the width of their parents. @@ -22,11 +17,11 @@ @media only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and ( min--moz-device-pixel-ratio: 2), - only screen and ( -o-min-device-pixel-ratio: 2/1), - only screen and ( min-device-pixel-ratio: 2), - only screen and ( min-resolution: 192dpi), - only screen and ( min-resolution: 2dppx) { + only screen and ( min--moz-device-pixel-ratio: 2), + only screen and ( -o-min-device-pixel-ratio: 2/1), + only screen and ( min-device-pixel-ratio: 2), + only screen and ( min-resolution: 192dpi), + only screen and ( min-resolution: 2dppx) { background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}")); background-size: $width-1x $height-1x; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_opacity.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_opacity.scss index 88e9a576abd795a9d0734542ff7e58e44a08d9a3..e9c5573345ae2ee4232259c1736183faebe56991 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_opacity.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_opacity.scss @@ -1,8 +1,7 @@ // Opacity @mixin opacity($opacity) { - opacity: $opacity; - // IE8 filter - $opacity-ie: ($opacity * 100); + $opacity-ie: ($opacity * 100); // IE8 filter filter: alpha(opacity=$opacity-ie); + opacity: $opacity; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_reset-text.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_reset-text.scss index c9c28417fabaf6f190bd284e6e954b5dec5034d6..8997eca28597c2d1c3f6f828af5135eb0b2a587b 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_reset-text.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_reset-text.scss @@ -2,17 +2,17 @@ font-family: $font-family-base; // We deliberately do NOT reset font-size. font-style: normal; - font-weight: normal; - letter-spacing: normal; - line-break: auto; + font-weight: 400; line-height: $line-height-base; + line-break: auto; text-align: left; // Fallback for where `start` is not supported text-align: start; text-decoration: none; text-shadow: none; text-transform: none; - white-space: normal; + letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; + white-space: normal; } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_resize.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_resize.scss index 83fa6379179cba67dbd3b3fb1b1d167380f361d4..66f233a63c988deb5a59dde3bba962082fbdfd57 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_resize.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_resize.scss @@ -1,6 +1,6 @@ // Resize anything @mixin resizable($direction) { - resize: $direction; // Options: horizontal, vertical, both overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` + resize: $direction; // Options: horizontal, vertical, both } diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_responsive-visibility.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_responsive-visibility.scss index cbdf77723977ab2b76e6f54454534e9e6b3c5874..d25ef973f589b963086461e1bcad956ea5ee47a7 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_responsive-visibility.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_responsive-visibility.scss @@ -1,7 +1,3 @@ -// Responsive utilities - -// -// More easily include all the states for responsive-utilities.less. // [converter] $parent hack @mixin responsive-visibility($parent) { #{$parent} { diff --git a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_vendor-prefixes.scss b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_vendor-prefixes.scss index b3d0371fa866e3f5bb0d8671126087d2f862fc4d..93d5775281ffafc378b291c21ea0e62b079aad2c 100644 --- a/themes/bootstrap3/scss/vendor/bootstrap/mixins/_vendor-prefixes.scss +++ b/themes/bootstrap3/scss/vendor/bootstrap/mixins/_vendor-prefixes.scss @@ -89,12 +89,12 @@ // Optional hyphenation @mixin hyphens($mode: auto) { - word-wrap: break-word; -webkit-hyphens: $mode; -moz-hyphens: $mode; -ms-hyphens: $mode; // IE10+ -o-hyphens: $mode; hyphens: $mode; + word-wrap: break-word; } // Placeholder text diff --git a/themes/bootstrap3/templates/Helpers/doi.phtml b/themes/bootstrap3/templates/Helpers/doi.phtml new file mode 100644 index 0000000000000000000000000000000000000000..55f9676ad355f2fee6df9db949fc1ba294708009 --- /dev/null +++ b/themes/bootstrap3/templates/Helpers/doi.phtml @@ -0,0 +1,2 @@ +<?=$this->inlineScript(\Zend\View\Helper\HeadScript::FILE, 'doi.js', 'SET');?> +<span class="doiLink" data-doi="<?=$this->escapeHtml($doi)?>"></span> \ No newline at end of file diff --git a/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml b/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml index 636796d8eb1047d17316891cd36bcab446add540..48799fe0d58049f1fd879511fab204a1805ce209 100644 --- a/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml +++ b/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml @@ -3,7 +3,7 @@ <li class="list-group-item title" data-toggle="collapse" href="#side-collapse-randomrecommend"> <?=$this->transEsc("random_recommendation_title")?> </li> - <div id="side-collapse-randomrecommend" class="collapse<?php if(!in_array('RandomRecommend', $collapsedFacets)): ?> in<?php endif ?>"> + <div id="side-collapse-randomrecommend" class="collapse in"> <?php foreach ($recommend as $driver): ?> <li class="list-group-item"> <?php if ($this->recommend->getDisplayMode() === "images" || $this->recommend->getDisplayMode() === "mixed"): ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacets.phtml b/themes/bootstrap3/templates/Recommend/SideFacets.phtml index 1813fa75f8e13117bf6122ad8eeea096159cc146..0b0821e039cd29dc2e5186558f001e92bc3ecea9 100644 --- a/themes/bootstrap3/templates/Recommend/SideFacets.phtml +++ b/themes/bootstrap3/templates/Recommend/SideFacets.phtml @@ -4,7 +4,15 @@ // Save results/options to $this so they are available to sub-templates: $this->results = $results = $this->recommend->getResults(); $this->options = $options = $results->getOptions(); + + $hierarchicalFacets = $this->recommend->getHierarchicalFacets(); + if ($hierarchicalFacets) { + // jstree.min.js used to be injected by hierarchical-facet.js, but with deferred + // processing it's called too late to append anything to the headers. + $this->headScript()->appendFile('vendor/jsTree/jstree.min.js'); + } ?> +<button class="close-offcanvas btn btn-link" data-toggle="offcanvas"><?=$this->transEsc('navigate_back') ?></button> <?php if ($results->getResultTotal() > 0): ?> <h4><?=$this->transEsc(isset($this->overrideSideFacetCaption) ? $this->overrideSideFacetCaption : 'Narrow Search')?></h4> <?php endif; ?> @@ -35,7 +43,7 @@ ]); ?> <?php endif; ?> <?= isset($this->sideFacetExtraControls) ? $this->sideFacetExtraControls : '' ?> -<?php $sideFacetSet = $this->recommend->getFacetSet(); $rangeFacets = $this->recommend->getAllRangeFacets(); ?> +<?php $sideFacetSet = $this->recommend->getFacetSet(); ?> <?php $hierarchicalFacets = $this->recommend->getHierarchicalFacets() ?> <?php $hierarchicalFacetSortOptions = $this->recommend->getHierarchicalFacetSortOptions() ?> <?php if (!empty($sideFacetSet) && $results->getResultTotal() > 0): ?> @@ -45,52 +53,13 @@ <?=$this->transEsc($cluster['label'])?> </button> <div id="side-collapse-<?=$this->escapeHtmlAttr($title) ?>" class="collapse<?php if(!in_array($title, $collapsedFacets)): ?> in<?php endif ?>"> - <?php if (isset($rangeFacets[$title])): // special display for ranges ?> - <?=$this->context($this)->renderInContext( - 'Recommend/SideFacets/range-slider.phtml', - ['title' => $title, 'facet' => $rangeFacets[$title]] - ); ?> - <?php else: ?> - <?php - // Set some variables so we can figure out which sub-template(s) to - // render. If we have a hierarchical facet, we will need to render a - // jsTree Javascript-based template. If we also support non-JS browsers, - // we will also need to render the basic default template. If we - // do NOT support non-JS browsers, we should instead display an error - // message. - $isHierarchical = in_array($title, $hierarchicalFacets); - $noJsSupport = $this->config()->nonJavascriptSupportEnabled(); - ?> - <?php if ($isHierarchical): // do we need hierarchical JS display? ?> - <?=$this->context($this)->renderInContext( - 'Recommend/SideFacets/hierarchical-facet.phtml', - [ - 'allowExclude' => $this->recommend->excludeAllowed($title), - 'title' => $title, - 'sortOptions' => $hierarchicalFacetSortOptions[$title] ?? '', - 'collapsedFacets' => $collapsedFacets - ] - ); ?> - <noscript> - <?php if (!$noJsSupport): ?> - <span class="facet"><?=$this->transEsc('Please enable JavaScript.')?></span> - <?php endif; ?> - <?php endif; ?> - <?php if (!$isHierarchical || $noJsSupport): // do we need regular display? ?> - <?=$this->context($this)->renderInContext( - 'Recommend/SideFacets/cluster-list.phtml', - [ - 'options' => $options, 'title' => $title, 'cluster' => $cluster, - 'allowExclude' => $this->recommend->excludeAllowed($title), - 'facets_before_more' => $this->recommend->getShowMoreSetting($title), - 'showMoreInLightbox' => $this->recommend->getShowInLightboxSetting($title) - ] - ); ?> - <?php endif; ?> - <?php if ($isHierarchical): // close tag opened in matching if above ?> - </noscript> - <?php endif; ?> - <?php endif; ?> + <?=$this->context($this)->renderInContext( + 'Recommend/SideFacets/facet.phtml', + [ + 'facet' => $title, + 'cluster' => $cluster, + 'collapsedFacets' => $collapsedFacets ] + ); ?> </div> </div> <?php endforeach; ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml index 3290f56bb4cf63c927ee595f2f31d20d94308b82..da04d197a24a8a8909b35728594047754c69f176 100644 --- a/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml +++ b/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml @@ -1,9 +1,16 @@ <?php foreach ($checkboxFilters as $current): ?> - <a class="checkbox-filter<?php if(!($results->getResultTotal() > 0 || $current['selected'] || $current['alwaysVisible'])): ?> hidden<?php endif; ?>" href="<?=$current['selected'] ? $results->getUrlQuery()->removeFilter($current['filter']) : $results->getUrlQuery()->addFilter($current['filter']);?>"> - <?php if ($current['selected']): ?> - <span class="sr-only"><?=$this->transEsc('clear_tag_filter') ?></span> - <?php endif; ?> - <i class="fa fa-<?=$current['selected'] ? 'check-square-o' : 'square-o' ?>"></i> - <?=$this->transEsc($current['desc']) ?> - </a> + <div class="facet" > + <a class="checkbox-filter<?php if(!($results->getResultTotal() > 0 || $current['selected'] || $current['alwaysVisible'])): ?> hidden<?php endif; ?>" href="<?=$current['selected'] ? $results->getUrlQuery()->removeFilter($current['filter']) : $results->getUrlQuery()->addFilter($current['filter']);?>" data-facet="<?=$this->escapeHtmlAttr($current['filter'])?>" data-facet="<?=$this->escapeHtmlAttr($current['filter'])?>"> + <?php if ($current['selected']): ?> + <span class="sr-only"><?=$this->transEsc('clear_tag_filter') ?></span> + <?php endif; ?> + <span class="text"> + <i class="fa fa-<?=$current['selected'] ? 'check-square-o' : 'square-o' ?>"></i> + <?=$this->transEsc($current['desc']) ?> + </span> + <?php if (!$current['selected']): ?> + <span class="badge avail-count"></span> + <?php endif; ?> + </a> + </div> <?php endforeach; ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml index b4badce6746d28e1b7efd770505df50a9050ce43..8d1d88508ba15c45f42f90dc5a2cb09a67827124 100644 --- a/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml +++ b/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml @@ -23,9 +23,12 @@ 'group' => $this->title, 'moreClass' => $i >= $this->facets_before_more ? $moreClass : false, 'url' => $this->results->getUrlQuery(), - 'urlBase' => $this->currentPath(), + 'urlBase' => '', ]) ?> <?php endforeach; ?> +<?php if (empty($this->cluster['list'])): ?> + <div class="facet"><?=$this->transEsc('facet_list_empty')?></div> +<?php endif; ?> <?php /* LESS and SEE MORE links */ ?> <?php if (isset($i) && $i >= $this->facets_before_more): ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/facet.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/facet.phtml new file mode 100644 index 0000000000000000000000000000000000000000..6ca7e7a7f8ab9cc06dda9120bb84346475a20ecd --- /dev/null +++ b/themes/bootstrap3/templates/Recommend/SideFacets/facet.phtml @@ -0,0 +1,55 @@ +<?php + $this->results = $results = $this->recommend->getResults(); + $this->options = $options = $results->getOptions(); + $hierarchicalFacetSortOptions = $this->recommend->getHierarchicalFacetSortOptions(); + $hierarchicalFacets = $this->recommend->getHierarchicalFacets(); + $collapsedFacets = $this->recommend->getCollapsedFacets(); + $rangeFacets = $this->recommend->getAllRangeFacets(); + $facet = $this->facet; +?> +<?php if (isset($rangeFacets[$facet])): // special display for ranges ?> + <?=$this->context($this)->renderInContext( + 'Recommend/SideFacets/range-slider.phtml', + ['title' => $facet, 'facet' => $rangeFacets[$facet]] + ); ?> +<?php else: ?> + <?php + // Set some variables so we can figure out which sub-template(s) to + // render. If we have a hierarchical facet, we will need to render a + // jsTree Javascript-based template. If we also support non-JS browsers, + // we will also need to render the basic default template. If we + // do NOT support non-JS browsers, we should instead display an error + // message. + $isHierarchical = in_array($facet, $hierarchicalFacets); + $noJsSupport = $this->config()->nonJavascriptSupportEnabled(); + ?> + <?php if ($isHierarchical): // do we need hierarchical JS display? ?> + <?=$this->context($this)->renderInContext( + 'Recommend/SideFacets/hierarchical-facet.phtml', + [ + 'allowExclude' => $this->recommend->excludeAllowed($facet), + 'title' => $facet, + 'sortOptions' => $hierarchicalFacetSortOptions[$facet] ?? '', + 'collapsedFacets' => $collapsedFacets + ] + ); ?> + <noscript> + <?php if (!$noJsSupport): ?> + <span class="facet"><?=$this->transEsc('Please enable JavaScript.')?></span> + <?php endif; ?> + <?php endif; ?> + <?php if (!$isHierarchical || $noJsSupport): // do we need regular display? ?> + <?=$this->context($this)->renderInContext( + 'Recommend/SideFacets/cluster-list.phtml', + [ + 'options' => $options, 'title' => $facet, 'cluster' => $cluster, + 'allowExclude' => $this->recommend->excludeAllowed($facet), + 'facets_before_more' => $this->recommend->getShowMoreSetting($facet), + 'showMoreInLightbox' => $this->recommend->getShowInLightboxSetting($facet) + ] + ); ?> + <?php endif; ?> + <?php if ($isHierarchical): // close tag opened in matching if above ?> + </noscript> + <?php endif; ?> +<?php endif; ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml b/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml new file mode 100644 index 0000000000000000000000000000000000000000..f155fc42d2c0827f1d4ecafa3c4c54737c120010 --- /dev/null +++ b/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml @@ -0,0 +1,81 @@ +<?php + $this->headScript()->appendFile('vendor/jsTree/jstree.min.js'); + $this->headScript()->appendFile('facets.js'); + + $results = $this->recommend->getResults(); + $activeFacets = $this->recommend->getActiveFacets(); + $rangeFacets = $this->recommend->getAllRangeFacets(); + + foreach ($activeFacets as $field => $facetName) { + if (isset($rangeFacets[$field]) && 'date' === $rangeFacets[$field]['type']) { + $this->headScript()->appendFile('vendor/bootstrap-slider.min.js'); + $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); + break; + } + } +?> +<?php if ($results->getResultTotal() > 0): ?> + <h4><?=$this->transEsc(isset($this->overrideSideFacetCaption) ? $this->overrideSideFacetCaption : 'Narrow Search')?></h4> + <div class="side-facets-container-ajax" data-search-class-id="<?=$this->escapeHtmlAttr($this->searchClassId) ?>" data-location="<?=$this->escapeHtmlAttr($this->location) ?>" data-config-index="<?=$this->escapeHtmlAttr($this->configIndex) ?>"> +<?php endif; ?> +<?php $checkboxFilters = $results->getParams()->getCheckboxFacets(); ?> +<?php $checkboxesShown = false; ?> +<?php if (count($checkboxFilters) > 0): + foreach ($checkboxFilters as $current) { + if ($results->getResultTotal() > 0 || $current['selected'] || $current['alwaysVisible']) { + $checkboxesShown = true; + break; + } + } + ?> + <?php if ($checkboxesShown): ?> + <div class="checkboxFilter"> + <?=$this->context($this)->renderInContext('Recommend/SideFacets/checkbox-filters.phtml', ['checkboxFilters' => $checkboxFilters, 'results' => $results]); ?> + </div> + <?php endif; ?> +<?php endif; ?> +<?php $extraFilters = isset($this->extraSideFacetFilters) ? $this->extraSideFacetFilters : []; ?> +<?php $collapsedFacets = $this->recommend->getCollapsedFacets() ?> +<?php $filterList = array_merge($results->getParams()->getFilterList(true), $extraFilters); ?> +<?php if (!empty($filterList)): ?> + <?=$this->context($this)->renderInContext('Recommend/SideFacets/filter-list.phtml', [ + 'collapsedFacets' => $collapsedFacets, + 'extraFilters' => $extraFilters, + 'filterList' => $filterList, + ]); ?> +<?php endif; ?> +<?= isset($this->sideFacetExtraControls) ? $this->sideFacetExtraControls : '' ?> +<?php $sideFacetSet = $this->recommend->getFacetSet(); ?> +<?php $hierarchicalFacets = $this->recommend->getHierarchicalFacets() ?> +<?php $hierarchicalFacetSortOptions = $this->recommend->getHierarchicalFacetSortOptions() ?> +<?php if (!empty($activeFacets) && $results->getResultTotal() > 0): ?> + <?php foreach ($activeFacets as $field => $facetName): ?> + <?php $allowExclude = $this->recommend->excludeAllowed($field); ?> + <div class="facet-group" id="side-panel-<?=$this->escapeHtmlAttr($field) ?>"> + <button class="title<?php if (in_array($field, $collapsedFacets)): ?> collapsed<?php endif ?>" data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($field) ?>" > + <?=$this->transEsc($facetName)?> + </button> + <div id="side-collapse-<?=$this->escapeHtmlAttr($field) ?>" class="collapse<?php if (!in_array($field, $collapsedFacets)): ?> in<?php endif ?>" data-facet="<?=$this->escapeHtmlAttr($field) ?>"> + <span class="facet-load-indicator hidden"> + <span class="text"> + <i class="fa fa-spinner fa-spin"></i> <?=$this->transEsc('Loading')?>... + </span> + </span> + <span class="facet-load-failed hidden"> <?=$this->transEsc('ajax_load_interrupted')?></span> + <?php if (in_array($field, $hierarchicalFacets)): ?> + <div id="facet_<?=$this->escapeHtml($field)?>" class="jstree-facet" + data-facet="<?=$this->escapeHtmlAttr($field)?>" + data-path="" + data-exclude="<?=$allowExclude?>" + data-operator="<?=$this->recommend->getFacetOperator($field)?>" + data-exclude-title="<?=$this->transEsc('exclude_facet')?>" + data-sort="<?=$hierarchicalFacetSortOptions[$field] ?? ''?>"> + </div> + <?php endif; ?> + </div> + </div> + <?php endforeach; ?> +<?php endif; ?> +<?php if ($results->getResultTotal() > 0): ?> + </div> +<?php endif; ?> diff --git a/themes/bootstrap3/templates/Recommend/TopFacets.phtml b/themes/bootstrap3/templates/Recommend/TopFacets.phtml index 789ce06224a4c396c387d134f4e1ed0ff50aa616..4c9325c4f2d191b88db81b4398584c272b18bb71 100644 --- a/themes/bootstrap3/templates/Recommend/TopFacets.phtml +++ b/themes/bootstrap3/templates/Recommend/TopFacets.phtml @@ -17,7 +17,7 @@ <div class="collapse in" id="top_<?=$this->escapeHtml($title) ?>"> <?php $limit = $topFacetSettings['rows'] * $topFacetSettings['cols']; ?> <?php foreach($cluster['list'] as $index => $thisFacet): ?> - <span class="facet <?=$index > $limit ? $moreClass : '' ?>"> + <span class="facet top-facet <?=$index > $limit ? $moreClass : '' ?>"> <?php if ($thisFacet['isApplied']): if (isset($thisFacet['specialType']) && $thisFacet['specialType'] == 'keyword') { $removeLink = $this->currentPath() . $results->getUrlQuery()->replaceTerm($thisFacet['value'], ''); @@ -31,11 +31,10 @@ <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet($title, $thisFacet['value'], $thisFacet['operator'])?>"> <?=$this->escapeHtml($thisFacet['displayText'])?><!-- --></a> - <span class="badge"><?=$this->localizedNumber($thisFacet['count']) ?> - <?php if ($allowExclude): ?> - <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet($title, $thisFacet['value'], 'NOT')?>" title="<?=$this->transEsc('exclude_facet')?>"><i class="fa fa-times" aria-hidden="true"></i></a> - <?php endif; ?> - </span> + <span class="badge"><?=$this->localizedNumber($thisFacet['count']) ?></span> + <?php if ($allowExclude): ?> + <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet($title, $thisFacet['value'], 'NOT')?>" title="<?=$this->transEsc('exclude_facet')?>"><i class="fa fa-times" aria-hidden="true"></i></a> + <?php endif; ?> <?php endif; ?> </span> <?php /* More link */ ?> diff --git a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/data-onlineAccess.phtml b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/data-onlineAccess.phtml index 4a545667a7a334f39747fc02532589fb69523ce8..4d96751f6f9b8d4fcf84b72d837649361b07f7e2 100644 --- a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/data-onlineAccess.phtml +++ b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/data-onlineAccess.phtml @@ -1,14 +1,15 @@ <?php $openUrl = $this->openUrl($this->driver, 'record'); $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'record'); + $doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); ?> -<?php if (!empty($urls) || $openUrlActive): ?> - <?php foreach ($urls as $current): ?> - <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/> - <?php endforeach; ?> - <?php if ($openUrlActive): ?> - <?=$openUrl->renderTemplate()?><br/> - <?php endif; ?> +<?php foreach ($urls as $current): ?> + <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/> +<?php endforeach; ?> +<?php if ($openUrlActive): ?> + <?=$openUrl->renderTemplate()?><br/> <?php endif; ?> +<?php if ($doiActive): ?><?=$doi->renderTemplate()?><?php endif; ?> diff --git a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/list-entry.phtml b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/list-entry.phtml index 323229a2109b3ac78389c5c7ff45e71042a76ff4..98d94ee07e44e062090ec66f796480db52021d9e 100644 --- a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/list-entry.phtml +++ b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/list-entry.phtml @@ -137,16 +137,23 @@ */ $openUrl = $this->openUrl($this->driver, 'results'); $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'results'); + $doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); - if ($openUrlActive || !empty($urls)): + if ($openUrlActive || $doiActive || !empty($urls)): ?> <?php if ($openUrlActive): ?> <br/> <?=$openUrl->renderTemplate()?> <?php endif;?> + <?php if ($doiActive): ?> + <br/> + <?=$doi->renderTemplate()?> + <?php endif; ?> + <?php if (!is_array($urls)) { $urls = []; } if(!$this->driver->isCollection()): foreach ($urls as $current): ?> diff --git a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-grid.phtml b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-grid.phtml index bb091ff369f061e43bcbc47b685846ff549517b5..e76e183deb676e1da67c39e304513dac1af19f99 100644 --- a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-grid.phtml +++ b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-grid.phtml @@ -5,6 +5,8 @@ */ $openUrl = $this->openUrl($this->driver, 'results'); $openUrlActive = $openUrl->isActive(); +$doi = $this->doi($this->driver, 'results'); +$doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); ?> @@ -29,11 +31,14 @@ $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); <a class="title" href="<?=$this->recordLink()->getUrl($this->driver)?>"> <?=$this->record($this->driver)->getTitleHtml(80)?> </a> - <?php if ($openUrlActive || !empty($urls)): ?> + <?php if ($openUrlActive || $doiActive || !empty($urls)): ?> <br/><br/> <?php if ($openUrlActive): ?> <?=$openUrl->renderTemplate()?><br /> <?php endif; ?> + <?php if ($doiActive): ?> + <?=$doi->renderTemplate()?><br /> + <?php endif; ?> <?php if (!is_array($urls)) $urls = []; foreach ($urls as $current): ?> <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a> <br/> diff --git a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-list.phtml index 3f8f07cc084a0f2826baca627e8bc53a6f39fb46..c97910034a87922bfc51e4ee819996690cac8d53 100644 --- a/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-list.phtml +++ b/themes/bootstrap3/templates/RecordDriver/DefaultRecord/result-list.phtml @@ -121,14 +121,20 @@ */ $openUrl = $this->openUrl($this->driver, 'results'); $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'results'); + $doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); - if ($openUrlActive || !empty($urls)): ?> + if ($openUrlActive || $doiActive || !empty($urls)): ?> <?php if ($openUrlActive): ?> <br/> <?=$openUrl->renderTemplate()?> <?php endif; ?> + <?php if ($doiActive): ?> + <br/> + <?=$doi->renderTemplate()?> + <?php endif; ?> <?php if (!is_array($urls)) $urls = []; if(!$this->driver->isCollection()): foreach ($urls as $current): ?> diff --git a/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml index a8855831777b1e3e0c69f093e6296ee53c0a4ed7..2eaabf714ee6a9ced44e5b3e19082ec3425dd482 100644 --- a/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml +++ b/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml @@ -61,7 +61,7 @@ <?php $customLinks = array_merge($this->driver->getFTCustomLinks(), $this->driver->getCustomLinks()); if (!empty($customLinks)): ?> <?php foreach ($customLinks as $customLink): ?> - <?php + <?php $url = $customLink['Url'] ?? ''; $mot = $customLink['MouseOverText'] ?? ''; $icon = $customLink['Icon'] ?? ''; diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml index a836656fef657d44f406b7250b43c66662173e4a..014b44758b27e3950af83fa3f0828a53239dba88 100644 --- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml +++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml @@ -79,13 +79,20 @@ */ $openUrl = $this->openUrl($this->driver, 'results'); $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'results'); + $doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); - if ($openUrlActive || !empty($urls)): ?> + + if ($openUrlActive || $doiActive || !empty($urls)): ?> <?php if ($openUrlActive): ?> <br/> <?=$openUrl->renderTemplate()?> <?php endif; ?> + <?php if ($doiActive): ?> + <br/> + <?=$doi->renderTemplate()?> + <?php endif; ?> <?php if (!is_array($urls)) $urls = []; if(!$this->driver->isCollection()): foreach ($urls as $current): ?> diff --git a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml index 3d4f71b9831d329283d71192b4d14c6befdceeb3..fefcb15662def1bca294bca16bd2b42edc00e539 100644 --- a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml +++ b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml @@ -4,6 +4,8 @@ $user = $account->isLoggedIn(); $openUrl = $this->openUrl($this->driver, 'holdings'); $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'holdings'); + $doiActive = $doi->isActive(); // Account for replace_other_urls setting $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); $offlineMode = $this->ils()->getOfflineMode(); @@ -42,7 +44,7 @@ <?php $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?> <a class="placehold" data-lightbox title="<?=$this->transEsc('request_place_text')?>" href="<?=$this->recordLink()->getRequestUrl($holdingTitleHold)?>"><i class="fa fa-flag" aria-hidden="true"></i> <?=$this->transEsc('title_hold_place')?></a> <?php endif; ?> -<?php if (!empty($urls) || $openUrlActive): ?> +<?php if (!empty($urls) || $openUrlActive || $doiActive): ?> <h3><?=$this->transEsc("Internet")?></h3> <?php if (!empty($urls)): ?> <?php foreach ($urls as $current): ?> @@ -50,6 +52,7 @@ <?php endforeach; ?> <?php endif; ?> <?php if ($openUrlActive): ?><?=$openUrl->renderTemplate()?><?php endif; ?> + <?php if ($doiActive): ?><?=$doi->renderTemplate()?><?php endif; ?> <?php endif; ?> <?php foreach ($holdings['holdings'] ?? [] as $holding): ?> <h3> diff --git a/themes/bootstrap3/templates/RecordTab/preview.phtml b/themes/bootstrap3/templates/RecordTab/preview.phtml index b151b30ad9334e521566a28775d4187ce349a4b4..289442f7e677b8d2552d1ecb1ae83ea8d0a12e94 100644 --- a/themes/bootstrap3/templates/RecordTab/preview.phtml +++ b/themes/bootstrap3/templates/RecordTab/preview.phtml @@ -3,7 +3,7 @@ $this->headTitle($this->translate('Preview') . ': ' . $this->driver->getBreadcrumb()); // load the embedded preview javascript file - $this->headScript()->appendFile('https://www.google.com/jsapi'); + $this->headScript()->appendFile('https://www.google.com/books/jsapi.js'); $this->headScript()->appendFile('embedGBS.js'); ?> <div id="gbsViewer" style="height: 600px;"></div> diff --git a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml index 0c6e3d562771e5b64c3512292d4cf7b236c82121..17c2652ffddfb9fb761d87a468b221e425bf6880 100644 --- a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml +++ b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml @@ -41,10 +41,10 @@ </div> <!-- Controls --> - <a class="left carousel-control" href="#similar-items-carousel" role="button" data-slide="prev"> + <a class="left carousel-control" href="#similar-items-carousel" role="button" data-slide="prev" aria-label="<?=$this->transEsc('Prev') ?>"> <span class="fa fa-chevron-left glyphicon-chevron-left" title="<?=$this->transEsc('Prev') ?>"></span> </a> - <a class="right carousel-control" href="#similar-items-carousel" role="button" data-slide="next"> + <a class="right carousel-control" href="#similar-items-carousel" role="button" data-slide="next" aria-label="<?=$this->transEsc('Next') ?>"> <span class="fa fa-chevron-right glyphicon-chevron-right" title="<?=$this->transEsc('Next') ?>"></span> </a> </div> diff --git a/themes/bootstrap3/templates/channels/channelList.phtml b/themes/bootstrap3/templates/channels/channelList.phtml index db34ec3ad09e2baf9c6ba7232c044ad88d00ec45..1ff0a0d42b56f5ee6bd3aecbc8ec60377c35b99d 100644 --- a/themes/bootstrap3/templates/channels/channelList.phtml +++ b/themes/bootstrap3/templates/channels/channelList.phtml @@ -3,7 +3,6 @@ $this->headLink()->appendStylesheet('vendor/slick-theme.css'); $this->headScript()->appendFile('vendor/slick.min.js'); $this->headScript()->appendFile('channels.js'); - $this->headScript()->appendFile('lib/accessible-carousels.js'); $this->headScript()->appendFile('vendor/jquery.dotdotdot.min.js'); $this->jsTranslations()->addStrings([ 'channel_browse' => 'channel_browse', diff --git a/themes/bootstrap3/templates/eds/advanced.phtml b/themes/bootstrap3/templates/eds/advanced.phtml index 0c87a8b62e9a306e9869d59b6c4f67c2b65023d5..beb90d5f79f29586ac27269a109907758ac5418e 100644 --- a/themes/bootstrap3/templates/eds/advanced.phtml +++ b/themes/bootstrap3/templates/eds/advanced.phtml @@ -22,9 +22,9 @@ <option value="OR"><?=$this->transEsc("OR")?></option> <option value="NOT"><?=$this->transEsc("NOT")?></option> </select> - <input id="search_lookfor0_<?=$search ?>" name="lookfor0[]" class="adv-term-input form-control" type="text" value=""/> + <input id="search_lookfor0_<?=$search ?>" name="lookfor0[]" class="adv-term-input form-control" type="text" value="" aria-label="<?=$this->transEsc("search_terms")?>"/> <span class="help-block hidden-xs"><?=$this->transEsc("in")?></span> - <select id="search_type0_<?=$search ?>" name="type0[]" class="adv-term-type form-control"> + <select id="search_type0_<?=$search ?>" name="type0[]" class="adv-term-type form-control" aria-label="<?=$this->transEsc("Search type")?>"> <?php foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?> <option value="<?=$this->escapeHtml($searchVal)?>"><?=$this->transEsc($searchDesc)?></option> <?php endforeach; ?> diff --git a/themes/bootstrap3/templates/feedback/form.phtml b/themes/bootstrap3/templates/feedback/form.phtml index f8488ec54b648dc2b4fc284931b75c46f098b1eb..f4246bec3daeb40b1a74f8d9244fdb51153e13dc 100644 --- a/themes/bootstrap3/templates/feedback/form.phtml +++ b/themes/bootstrap3/templates/feedback/form.phtml @@ -1,20 +1,89 @@ -<h2><?=$this->transEsc("Send us your feedback!")?></h2> -<?=$this->flashmessages() ?> -<form class="form-feedback" name="feedback" method="post" action="<?=$this->url('feedback-email')?>"> - <div class="form-group"> - <label class="control-label" for="name"><?=$this->transEsc("feedback_name")?></label> - <input type="text" id="name" name="name" value="<?=$this->escapeHtmlAttr($name ?? '')?>" class="form-control"/> - </div> - <div class="form-group"> - <label class="control-label" for="email"><?=$this->transEsc("Email")?></label> - <input type="email" id="email" name="email" value="<?=$this->escapeHtmlAttr($email ?? '')?>" class="form-control" required/> - </div> - <div class="form-group"> - <label class="control-label" for="comments"><?=$this->transEsc("Comments")?></label> - <textarea id="comments" name="comments" class="form-control" required><?=$this->escapeHtml($comments ?? '')?></textarea> - </div> - <?=$this->recaptcha()->html($this->useRecaptcha) ?> - <div class="form-group"> - <input type="submit" name="submit" class="btn btn-primary" value="<?=$this->transEsc("Send")?>" /> - </div> -</form> +<?php + $form = $this->form; + $form->prepare(); + + $title = $form->getTitle(); + $title = !empty($title) + ? $this->transEsc($title) : null; + + $formUrl = $this->url('feedback-form', ['id' => $this->formId]); + $form->setAttribute('action', $formUrl); + $form->setAttribute('class', 'dynamic-form'); + $form->setAttribute('method', 'post'); + + $help = $form->getHelp(); + $helpPre = $helpPost = null; + $helpPre = isset($help['pre']) ? $this->translate($help['pre']) : null; + $helpPost = isset($help['post']) ? $this->translate($help['post']) : null; +?> +<div class="feedback-content"> + <?php if ($title): ?> + <?php $this->headTitle($title); ?> + <h1><?=$title?></h1> + <?php endif; ?> + <?=$this->flashmessages()?> + + <?php if ($form->showOnlyForLoggedUsers() && !$this->user): ?> + <div class="form-group"> + <p><?=$this->translate('feedback_login_required')?></p> + <a href="<?=$this->url('myresearch-userlogin') ?>" class="btn btn-primary" data-lightbox title="Login"><i class="fa fa-sign-in" aria-hidden="true" data-lightbox-onclose="window.location.href='<?=$this->escapeHtmlAttr($formUrl) ?>'"></i> <?=$this->transEsc("Login") ?></a> + </div> + <?php else: ?> + <?= $this->form()->openTag($form); ?> + <?php if ($helpPre): ?> + <div class="form-group"> + <div class="form-info pre"> + <?=$helpPre?> + </div> + </div> + <?php endif ?> + + <?php $currentGroup = null; ?> + <?php foreach($form->getElements() as $el): ?> + <?php + $formElement = $form->get($el['name']); + + // Group form elements into field sets + $handleGroup = $group = null; + if (isset($el['group']) && !empty($el['group'])) { + $group = $el['group']; + } + if ($group && $currentGroup === null) { + $handleGroup = 'open'; + $currentGroup = $group; + } elseif ($currentGroup && !$group) { + $handleGroup = 'close'; + $currentGroup = null; + } elseif ($currentGroup !== $group) { + $handleGroup = 'openAndClose'; + $currentGroup = $group; + } + ?> + + <?php if (in_array($handleGroup, ['close', 'openAndClose'])): ?> + </div> + <?php endif ?> + <?php if (in_array($handleGroup, ['open', 'openAndClose'])): ?> + <div class="field-set"> + <?php endif ?> + + <div class="form-group"> + <?php if (!empty($el['help'])): ?> + <p class="info"><?= $this->transEsc($el['help']) ?></p> + <?php endif ?> + <?php if ($el['type'] !== 'submit'): ?> + <label for="<?=$this->escapeHtmlAttr($el['name'])?>" class="control-label<?=!empty($el['required']) ? ' required' : ''?>"><?=$this->transEsc($el['label'])?>:</label> + <?php else: ?> + <?php if ($helpPost): ?> + <div class="form-info post"> + <?=$helpPost?> + </div> + <?php endif ?> + <?=$this->recaptcha()->html($this->useRecaptcha) ?> + <?php endif ?> + <?= $this->formRow($formElement) ?> + </div> + <?php endforeach ?> + <?= $this->form()->closeTag() ?> + <?php endif ?> +</div> diff --git a/themes/bootstrap3/templates/header.phtml b/themes/bootstrap3/templates/header.phtml index 39a3e0cd9e68585f63f482fd709ab1263b31f210..f20e24f0a390b3af48d90d83c3140fe9c483197e 100644 --- a/themes/bootstrap3/templates/header.phtml +++ b/themes/bootstrap3/templates/header.phtml @@ -25,9 +25,17 @@ </li> <?php endif; ?> <?php if (is_object($account) && $account->loginEnabled()): // hide login/logout if unavailable ?> - <li class="logoutOptions<?php if(!$account->isLoggedIn()): ?> hidden<?php endif ?>"> - <a href="<?=$this->url('myresearch-home', [], ['query' => ['redirect' => 0]])?>"><i class="fa fa-home" aria-hidden="true"></i> <?=$this->transEsc("Your Account")?></a> + <li class="logoutOptions<?php if($account->dropdownEnabled()): ?> with-dropdown<?php endif ?><?php if(!$account->isLoggedIn()): ?> hidden<?php endif ?>"> + <a href="<?=$this->url('myresearch-home', [], ['query' => ['redirect' => 0]])?>"><i id="account-icon" class="fa fa-user-circle" aria-hidden="true"></i> <?=$this->transEsc("Your Account")?></a> </li> + <?php if($account->dropdownEnabled()): ?> + <li id="login-dropdown" class="dropdown<?php if(!$account->isLoggedIn()): ?> hidden<?php endif ?>"> + <a href="#" data-toggle="dropdown"><i class="fa fa-caret-down"></i></a> + <div class="dropdown-menu"> + <?=$this->render('myresearch/menu'); ?> + </div> + </li> + <?php endif; ?> <li class="logoutOptions<?php if(!$account->isLoggedIn()): ?> hidden<?php endif ?>"> <a href="<?=$this->url('myresearch-logout')?>" class="logout"><i class="fa fa-sign-out" aria-hidden="true"></i> <?=$this->transEsc("Log Out")?></a> </li> diff --git a/themes/bootstrap3/templates/layout/layout.phtml b/themes/bootstrap3/templates/layout/layout.phtml index df434797e2a372e7aa83540d75655ca192314708..ee079054fae527d073f349a4ee1bf386c99c99a6 100644 --- a/themes/bootstrap3/templates/layout/layout.phtml +++ b/themes/bootstrap3/templates/layout/layout.phtml @@ -37,6 +37,7 @@ 'collection_empty' => 'collection_empty', 'error_occurred' => 'An error has occurred', 'go_to_list' => 'go_to_list', + 'hold_available' => 'hold_available', 'libphonenumber_invalid' => 'libphonenumber_invalid', 'libphonenumber_invalidcountry' => 'libphonenumber_invalidcountry', 'libphonenumber_invalidregion' => 'libphonenumber_invalidregion', @@ -96,7 +97,7 @@ ] ); } - $this->headScript()->appendScript( + $this->headScript()->prependScript( 'var userIsLoggedIn = ' . ($this->auth()->isLoggedIn() ? 'true' : 'false') . ';' ); } @@ -107,8 +108,24 @@ . $this->keepAlive()); $this->headScript()->appendFile("keep_alive.js"); } - ?> - <?php + + // If account ajax is active, load script and add language strings + $account = $this->auth()->getManager(); + if ($account->ajaxEnabled()) { + $this->headScript()->appendFile("account_ajax.js"); + $this->jsTranslations()->addStrings( + [ + 'account_has_alerts' => 'account_has_alerts', + 'Checked Out Items' => 'Checked Out Items', + 'ill_request_available' => 'ill_request_available', + 'renew_item_due_tooltip' => 'renew_item_due_tooltip', + 'renew_item_overdue_tooltip' => 'renew_item_overdue_tooltip', + 'request_in_transit' => 'request_in_transit', + 'storage_retrieval_request_available' => 'storage_retrieval_request_available' + ] + ); + } + $root = rtrim($this->url('home'), '/'); $translations = $this->jsTranslations()->getJSON(); $dsb = DEFAULT_SEARCH_BACKEND; @@ -181,7 +198,6 @@ JS; </div> </div> </div> - <div class="offcanvas-toggle" data-toggle="offcanvas"><i class="fa" title="<?=$this->transEsc('sidebar_expand') ?>"></i></div> <div class="offcanvas-overlay" data-toggle="offcanvas"></div> <?=$this->googleanalytics()?> <?=$this->piwik()?> diff --git a/themes/bootstrap3/templates/librarycards/editcard.phtml b/themes/bootstrap3/templates/librarycards/editcard.phtml index 1361cd6947b08682eb02ba99a8d485be9ed7ae97..1e241c594c59d15b963c18971ebd60e6cd3635dc 100644 --- a/themes/bootstrap3/templates/librarycards/editcard.phtml +++ b/themes/bootstrap3/templates/librarycards/editcard.phtml @@ -13,7 +13,7 @@ <h2><?=$this->transEsc($pageTitle); ?></h2> -<form class="form-edit-card" method="post" name="<?=empty($this->card->id) ? 'newCardForm' : 'editCardForm'?>"> +<form class="form-edit-card" method="post" name="<?=empty($this->card->id) ? 'newCardForm' : 'editCardForm'?>" autocomplete="off"> <input type="hidden" name="id" value="<?=empty($this->card->id) ? 'NEW' : $this->card->id ?>"/> <div class="form-group"> <label class="control-label" for="card_name"><?=$this->transEsc('Library Card Name'); ?>:</label> @@ -35,7 +35,7 @@ </div> <div class="form-group"> <label class="control-label" for="login_password"><?=$this->transEsc('Password')?>:</label> - <input id="login_password" type="password" name="password" value="<?=$this->escapeHtmlAttr($this->password)?>" class="form-control"/> + <input id="login_password" type="password" name="password" value="" placeholder="<?=!empty($this->card->id) ? $this->escapeHtmlAttr($this->translate('library_card_edit_password_placeholder')) : ''?>" class="form-control"/> </div> <div class="form-group"> <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/> diff --git a/themes/bootstrap3/templates/librarycards/selectcard.phtml b/themes/bootstrap3/templates/librarycards/selectcard.phtml index ea295d90c995885008cd58aa6af9d4347cea1be3..b2fa24eca4d84b518571e71191f4c7f02ef6506f 100644 --- a/themes/bootstrap3/templates/librarycards/selectcard.phtml +++ b/themes/bootstrap3/templates/librarycards/selectcard.phtml @@ -3,6 +3,9 @@ <form class="form-inline" action="<?=$this->url('librarycards-selectcard')?>" method="get"> <label for="library_card"><?=$this->transEsc('Library Card')?></label> <select id="library_card" name="cardID" class="jumpMenu form-control"> + <?php if (null === $this->user->cat_username): ?> + <option value="" selected="selected">-</option> + <?php endif; ?> <?php foreach ($cards as $card): ?> <?php $target = ''; diff --git a/themes/bootstrap3/templates/myresearch/cataloglogin.phtml b/themes/bootstrap3/templates/myresearch/cataloglogin.phtml index 27ad44901d244ddc98589d05143dc5a1d4585dd8..0cb7afbe7fa2ec9d08a1853ae61ec1cd7b4ee0e5 100644 --- a/themes/bootstrap3/templates/myresearch/cataloglogin.phtml +++ b/themes/bootstrap3/templates/myresearch/cataloglogin.phtml @@ -13,6 +13,9 @@ <?php else: ?> <h3><?=$this->transEsc('Library Catalog Profile')?></h3> <?=$this->flashmessages()?> + <p> + <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?> + </p> <p><?=$this->transEsc('cat_establish_account')?></p> <form method="post" action="<?=$this->serverUrl(true)?>" class="form-catalog-login"> <?php if ($this->targets !== null): ?> diff --git a/themes/bootstrap3/templates/myresearch/checkedout.phtml b/themes/bootstrap3/templates/myresearch/checkedout.phtml index 1aa5feb1e0560d45c14478d20450c24f6c6958ab..c5d69da312ff9578cb2e0508f461ebba143a960e 100644 --- a/themes/bootstrap3/templates/myresearch/checkedout.phtml +++ b/themes/bootstrap3/templates/myresearch/checkedout.phtml @@ -4,6 +4,9 @@ // Set up breadcrumbs: $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Checked Out Items') . '</li>'; + + // Check if "Renew All" button can be displayed: + $renewAll = !$this->ilsPaging || !$paginator; ?> <div class="<?=$this->layoutClass('mainbody')?>"> @@ -13,6 +16,27 @@ <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?> <?php if (!empty($this->transactions)): ?> + <nav class="search-header hidden-print"> + <?php if ($paginator): ?> + <div class="search-stats"> + <?php + $end = min( + $paginator->getAbsoluteItemNumber($paginator->getItemCountPerPage()), + $paginator->getTotalItemCount() + ); + $transParams = [ + '%%start%%' => $this->localizedNumber($paginator->getAbsoluteItemNumber(1)), + '%%end%%' => $this->localizedNumber($end), + '%%total%%' => $this->localizedNumber($paginator->getTotalItemCount()) + ]; + ?> + <?=$this->translate('showing_items_of_html', $transParams); ?> + </div> + <?php endif; ?> + <?php if ($this->sortList): ?> + <?=$this->context($this)->renderInContext('myresearch/controls/sort.phtml', ['sortList' => $this->sortList]); ?> + <?php endif; ?> + </nav> <?php if ($this->renewForm): ?> <form name="renewals" method="post" id="renewals"> <div class="toolbar"> @@ -22,25 +46,13 @@ <?=$this->transEsc('select_page')?> </label> <input type="submit" class="btn btn-default" id="renewSelected" name="renewSelected" value="<?=$this->transEsc("renew_selected")?>" /> - <input type="submit" class="btn btn-default" id="renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" /> + <?php if ($renewAll): ?> + <input type="submit" class="btn btn-default" id="renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" /> + <?php endif; ?> </div> </div> <?php endif; ?> - <?php if ($paginator): ?> - <?php - $end = min( - $paginator->getAbsoluteItemNumber($paginator->getItemCountPerPage()), - $paginator->getTotalItemCount() - ); - $transParams = [ - '%%start%%' => $this->localizedNumber($paginator->getAbsoluteItemNumber(1)), - '%%end%%' => $this->localizedNumber($end), - '%%total%%' => $this->localizedNumber($paginator->getTotalItemCount()) - ]; - ?> - <?=$this->translate('showing_items_of_html', $transParams); ?> - <?php endif; ?> <?php foreach ($hiddenTransactions as $ilsDetails): ?> <?php if (isset($this->renewResult[$ilsDetails['item_id']])): ?> @@ -62,16 +74,18 @@ <?php $ilsDetails = $resource->getExtraDetail('ils_details'); ?> <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId())?>" class="result"> <?php if ($this->renewForm): ?> - <?php if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?> - <?php $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?> - <div class="checkbox"> + <div class="checkbox"> + <?php if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?> + <?php $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?> <label> <input class="checkbox-select-item" type="checkbox" name="renewSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" id="checkbox_<?=$safeId?>" /> </label> <input type="hidden" name="selectAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" /> <input type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" /> - </div> - <?php endif; ?> + <?php else: ?> + <label> </label> + <?php endif; ?> + </div> <?php endif; ?> <?php @@ -185,7 +199,7 @@ </div> <?php endforeach; ?> <?php if ($this->renewForm): ?></form><?php endif; ?> - <?=$paginator ? $this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml') : ''?> + <?=$paginator ? $this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml', compact('params')) : ''?> <?php else: ?> <?=$this->transEsc('You do not have any items checked out')?>. <?php endif; ?> diff --git a/themes/bootstrap3/templates/myresearch/fines.phtml b/themes/bootstrap3/templates/myresearch/fines.phtml index bd71880b49071511400aebcff2be5c1a1e7f1887..8300d9d9388cee5f49d643bfb4cc4c6acc79d705 100644 --- a/themes/bootstrap3/templates/myresearch/fines.phtml +++ b/themes/bootstrap3/templates/myresearch/fines.phtml @@ -14,37 +14,70 @@ <?php if (empty($this->fines)): ?> <?=$this->transEsc('You do not have any fines')?> <?php else: ?> + <?php + // Collect the data to build the table; we process this in advance so we + // can omit empty columns and simplify customization by separating data + // processing from rendering. + $tableData = []; + $totalDue = 0; + foreach ($this->fines as $record) { + if (empty($record['title'])) { + $title = $this->transEsc('not_applicable'); + } elseif (!is_object($record['driver'] ?? null)) { + $title = $this->escapeHtml(trim($record['title'], '/:')); + } else { + $title = '<a href="' + . $this->recordLink()->getUrl($record['driver']) + . '">' . $this->escapeHtml(trim($record['title'], '/:')) . '</a>'; + } + $tableData['Title'][] = $title; + $tableData['Checked Out'][] = $this->escapeHtml($record['checkout'] ?? ''); + $tableData['Due Date'][] = $this->escapeHtml($record['duedate'] ?? ''); + $tableData['Fine'][] = $this->escapeHtml($record['fine'] ?? ''); + $tableData['Fine Date'][] = $this->escapeHtml($record['createdate'] ?? ''); + $tableData['Fee'][] = isset($record['amount']) + ? $this->safeMoneyFormat($record['amount'] / 100.00) : ''; + $tableData['Balance'][] = isset($record['balance']) + ? $this->safeMoneyFormat($record['balance'] / 100.00) : ''; + $totalDue += $record['balance'] ?? 0; + } + + // Now empty out any unused columns: + foreach ($tableData as $column => $values) { + $empty = true; + foreach ($values as $value) { + if (strlen($value) > 0) { + $empty = false; + break; + } + } + if ($empty) { + unset($tableData[$column]); + } + } + + // Create the final list of columns and count of rows: + $columns = array_keys($tableData); + $rowCount = count($this->fines); + ?> <table class="table table-striped"> <caption class="sr-only"><?=$this->transEsc('Your Fines')?></caption> - <tr> - <th><?=$this->transEsc('Title')?></th> - <th><?=$this->transEsc('Checked Out')?></th> - <th><?=$this->transEsc('Due Date')?></th> - <th><?=$this->transEsc('Fine')?></th> - <th><?=$this->transEsc('Fee')?></th> - <th><?=$this->transEsc('Balance')?></th> - </tr> - <?php $totalDue = 0; ?> - <?php foreach ($this->fines as $record): ?> <tr> - <td> - <?php if (empty($record['title'])): ?> - <?=$this->transEsc('not_applicable')?> - <?php elseif (!isset($record['driver']) || !is_object($record['driver'])): ?> - <?=$this->escapeHtml(trim($record['title'], '/:'))?> - <?php else: ?> - <a href="<?=$this->recordLink()->getUrl($record['driver'])?>"><?=$this->escapeHtml(trim($record['title'], '/:'))?></a> - <?php endif; ?> - </td> - <td><?=isset($record['checkout']) ? $this->escapeHtml($record['checkout']) : ''?></td> - <td><?=isset($record['duedate']) ? $this->escapeHtml($record['duedate']) : ''?></td> - <td><?=isset($record['fine']) ? $this->escapeHtml($record['fine']) : ''?></td> - <td><?=isset($record['amount']) ? $this->safeMoneyFormat($record['amount'] / 100.00) : ''?></td> - <td><?=isset($record['balance']) ? $this->safeMoneyFormat($record['balance'] / 100.00) : ''?></td> + <?php foreach ($columns as $header): ?> + <th><?=$this->transEsc($header)?></th> + <?php endforeach; ?> + </tr> + <?php for ($row = 0; $row < $rowCount; $row++): ?> + <tr> + <?php foreach ($columns as $column): ?> + <td><?=$tableData[$column][$row]?></td> + <?php endforeach; ?> + </tr> + <?php endfor; ?> + <tr style="font-weight:bold"> + <td colspan="<?=count($columns) - 1?>"><?=$this->transEsc('Total Balance Due')?></td> + <td><?=$this->safeMoneyFormat($totalDue / 100.00) ?></td> </tr> - <?php $totalDue += $record['balance']; ?> - <?php endforeach; ?> - <tr style="font-weight:bold"><td colspan="5"><?=$this->transEsc('Total Balance Due')?></td><td><?=$this->safeMoneyFormat($totalDue / 100.00) ?></td></tr> </table> <?php endif; ?> </div> diff --git a/themes/bootstrap3/templates/myresearch/holds.phtml b/themes/bootstrap3/templates/myresearch/holds.phtml index 1c5fc30e6e581919378ce76ef5d1cf3e196cfe0d..74ce8c7ea0930604ef52f7a119fb789f7ec17e8e 100644 --- a/themes/bootstrap3/templates/myresearch/holds.phtml +++ b/themes/bootstrap3/templates/myresearch/holds.phtml @@ -149,7 +149,13 @@ <?php endif; ?> <?php if (isset($ilsDetails['available']) && $ilsDetails['available'] == true): ?> - <div class="text-success"><?=$this->transEsc("hold_available") ?></div> + <div class="text-success"> + <?php if (!empty($ilsDetails['last_pickup_date'])): ?> + <?=$this->transEsc('hold_available_until', ['%%date%%' => $ilsDetails['last_pickup_date']]) ?> + <?php else: ?> + <?=$this->transEsc('hold_available') ?> + <?php endif; ?> + </div> <?php elseif (isset($ilsDetails['in_transit']) && $ilsDetails['in_transit']): ?> <div class="text-success"><?=$this->transEsc('request_in_transit') . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], [], $ilsDetails['in_transit']) : '') ?></div> <?php elseif (isset($ilsDetails['position'])): ?> diff --git a/themes/bootstrap3/templates/myresearch/menu.phtml b/themes/bootstrap3/templates/myresearch/menu.phtml index df38a22316de0ed776f86881eea016572adcc049..d7f9ba01a2f8df03c3b5194021d303658fee903b 100644 --- a/themes/bootstrap3/templates/myresearch/menu.phtml +++ b/themes/bootstrap3/templates/myresearch/menu.phtml @@ -4,7 +4,7 @@ $capabilityParams = $patron ? ['patron' => $patron] : []; ?> <h4><?=$this->transEsc('Your Account')?></h4> -<div class="myresearch-menu"> +<div class="myresearch-menu account-menu"> <?php if ($this->userlist()->getMode() !== 'disabled'): ?> <a href="<?=$this->url('myresearch-favorites')?>"<?=$this->active == 'favorites' ? ' class="active"' : ''?>> <i class="fa fa-fw fa-star" aria-hidden="true"></i> <?=$this->transEsc('Favorites')?> @@ -12,33 +12,38 @@ <?php endif; ?> <?php if ('ils-none' !== $this->ils()->getOfflineMode()): ?> <?php if ($this->ils()->checkCapability('getMyTransactions', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-checkedout')?>"<?=$this->active == 'checkedout' ? ' class="active"' : ''?>> - <i class="fa fa-fw fa-book" aria-hidden="true"></i> <?=$this->transEsc('Checked Out Items')?> + <a href="<?=$this->url('myresearch-checkedout')?>" class="flex checkedout<?=$this->active == 'checkedout' ? ' active' : ''?>"> + <span class="flex-col"><i class="fa fa-fw fa-book" aria-hidden="true"></i> <?=$this->transEsc('Checked Out Items')?></span> + <span class="checkedout-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span> </a> <?php endif; ?> <?php if ($this->ils()->checkFunction('getMyTransactionHistory', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-historicloans')?>"<?=$this->active == 'historicloans' ? ' class="active"' : ''?>"> + <a href="<?=$this->url('myresearch-historicloans')?>"<?=$this->active == 'historicloans' ? ' class="active"' : ''?>> <i class="fa fa-fw fa-history" aria-hidden="true"></i> <?=$this->transEsc('Loan History')?> </a> <?php endif; ?> <?php if ($this->ils()->checkCapability('getMyHolds', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-holds')?>"<?=$this->active == 'holds' ? ' class="active"' : ''?>> - <i class="fa fa-fw fa-flag" aria-hidden="true"></i> <?=$this->transEsc('Holds and Recalls')?> + <a href="<?=$this->url('myresearch-holds')?>" class="flex<?=$this->active == 'holds' ? ' active' : ''?>"> + <span class="flex-col"><i class="fa fa-fw fa-flag" aria-hidden="true"></i> <?=$this->transEsc('Holds and Recalls')?></span> + <span class="holds-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span> </a> <?php endif; ?> <?php if ($this->ils()->checkFunction('StorageRetrievalRequests', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-storageretrievalrequests')?>"<?=$this->active == 'storageRetrievalRequests' ? ' class="active"' : ''?>> - <i class="fa fa-fw fa-archive" aria-hidden="true"></i> <?=$this->transEsc('Storage Retrieval Requests')?> + <a href="<?=$this->url('myresearch-storageretrievalrequests')?>" class="flex<?=$this->active == 'storageRetrievalRequests' ? ' active' : ''?>"> + <span class="flex-col"><i class="fa fa-fw fa-archive" aria-hidden="true"></i> <?=$this->transEsc('Storage Retrieval Requests')?></span> + <span class="storageretrievalrequests-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span> </a> <?php endif; ?> <?php if ($this->ils()->checkFunction('ILLRequests', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-illrequests')?>"<?=$this->active == 'ILLRequests' ? ' class="active"' : ''?>> - <i class="fa fa-fw fa-exchange" aria-hidden="true"></i> <?=$this->transEsc('Interlibrary Loan Requests')?> + <a href="<?=$this->url('myresearch-illrequests')?>" class="flex<?=$this->active == 'ILLRequests' ? ' active' : ''?>"> + <span class="flex-col"><i class="fa fa-fw fa-exchange" aria-hidden="true"></i> <?=$this->transEsc('Interlibrary Loan Requests')?></span> + <span class="illrequests-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span> </a> <?php endif; ?> <?php if ($this->ils()->checkCapability('getMyFines', $capabilityParams)): ?> - <a href="<?=$this->url('myresearch-fines')?>"<?=$this->active == 'fines' ? ' class="active"' : ''?>> - <i class="fa fa-fw fa-usd" aria-hidden="true"></i> <?=$this->transEsc('Fines')?> + <a href="<?=$this->url('myresearch-fines')?>" class="flex<?=$this->active == 'fines' ? ' active' : ''?>"> + <span class="flex-col"><i class="fa fa-fw fa-usd" aria-hidden="true"></i> <?=$this->transEsc('Fines')?></span> + <span class="fines-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span> </a> <?php endif; ?> <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active"' : ''?>> diff --git a/themes/bootstrap3/templates/myresearch/profile.phtml b/themes/bootstrap3/templates/myresearch/profile.phtml index f5010aff87bdc948b4bb8b2aa33d06e5f6812f33..7032e3a602469f9b5e820b780ece4b01d6b4094e 100644 --- a/themes/bootstrap3/templates/myresearch/profile.phtml +++ b/themes/bootstrap3/templates/myresearch/profile.phtml @@ -77,7 +77,7 @@ ] )?> </table> - <?php elseif ('ils-none' !== $this->ils()->getOfflineMode() && !empty($this->patronLoginView->getTemplate())): ?> + <?php elseif ('ils-none' !== $this->ils()->getOfflineMode() && $this->patronLoginView && !empty($this->patronLoginView->getTemplate())): ?> <?=$this->partial($this->patronLoginView);?> <?php endif; ?> </div> diff --git a/themes/bootstrap3/templates/primo/advanced.phtml b/themes/bootstrap3/templates/primo/advanced.phtml index 4aa47b36d197d314190bb3d6665cc3b613b3fcbf..21db6623032e3157f2c3fa6a161465c2fc3ac9b5 100644 --- a/themes/bootstrap3/templates/primo/advanced.phtml +++ b/themes/bootstrap3/templates/primo/advanced.phtml @@ -64,7 +64,7 @@ <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=($currRow && $currRow->getOperator() == $searchVal)?' selected="selected"':''?>><?=$this->transEsc($searchDesc)?></option> <?php endforeach; ?> </select> - <input id="search_lookfor<?=$i?>_<?=$j?>" type="text" value="<?=$currRow?$this->escapeHtmlAttr($currRow->getString()):''?>" size="30" name="lookfor<?=$i?>[]" class="form-control primo-adv-input"/> + <input id="search_lookfor<?=$i?>_<?=$j?>" type="text" value="<?=$currRow?$this->escapeHtmlAttr($currRow->getString()):''?>" size="30" name="lookfor<?=$i?>[]" class="form-control primo-adv-input" aria-label="<?=$this->transEsc("search_terms")?>"/> </div> <?php endfor; ?> </div> diff --git a/themes/bootstrap3/templates/record/cover.phtml b/themes/bootstrap3/templates/record/cover.phtml index f19dc13d0939c47b9f4fa9cb35ab8bc3d02203fc..96666e065e3f201efc8201d0e00a20c2d7884f6f 100644 --- a/themes/bootstrap3/templates/record/cover.phtml +++ b/themes/bootstrap3/templates/record/cover.phtml @@ -1,6 +1,6 @@ <?php /* Display thumbnail if appropriate: */ ?> <?php if ($cover): ?> - <?php if ($this->link): ?><a href="<?=$this->escapeHtmlAttr($this->link)?>"><?php endif; ?> + <?php if ($this->link): ?><a href="<?=$this->escapeHtmlAttr($this->link)?>" data-lightbox-image><?php endif; ?> <img alt="<?=$this->transEsc('Cover Image')?>" <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?>class="recordcover" src="<?=$this->escapeHtmlAttr($cover); ?>"/> <?php if ($this->link): ?></a><?php endif; ?> <?php else: ?> diff --git a/themes/bootstrap3/templates/search/advanced/layout.phtml b/themes/bootstrap3/templates/search/advanced/layout.phtml index 87476abe8cb7e29b2e421b703b8d19a6cd5ded91..06cd9f477ba4fe86895cfea4e4b6ba6fcaca4f43 100644 --- a/themes/bootstrap3/templates/search/advanced/layout.phtml +++ b/themes/bootstrap3/templates/search/advanced/layout.phtml @@ -105,8 +105,8 @@ <div id="new_search_template"> <?php endif; ?> <div id="search<?=$group . '_' . $search ?>" class="adv-search"> - <input name="lookfor<?=$group ?>[]" id="search_lookfor<?=$group . '_' . $search ?>" class="adv-term-input form-control" type="text"<?php if (isset($setQueries[$group][$search])): ?> value="<?=$this->escapeHtml($setQueries[$group][$search]->getString())?>"<?php endif; ?>> - <select class="adv-term-type form-control" name="type<?=$group ?>[]"> + <input name="lookfor<?=$group ?>[]" id="search_lookfor<?=$group . '_' . $search ?>" class="adv-term-input form-control" type="text"<?php if (isset($setQueries[$group][$search])): ?> value="<?=$this->escapeHtml($setQueries[$group][$search]->getString())?>"<?php endif; ?> aria-label="<?=$this->transEsc("search_terms")?>"> + <select class="adv-term-type form-control" name="type<?=$group ?>[]" aria-label="<?=$this->transEsc("Search type")?>"> <?php foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?> <option value="<?=$this->escapeHtml($searchVal)?>"<?php if (isset($setQueries[$group][$search]) && $searchVal == $setQueries[$group][$search]->getHandler()): ?> selected<?php endif; ?>><?=$this->transEsc($searchDesc)?></option> <?php endforeach; ?> diff --git a/themes/bootstrap3/templates/search/facet-list.phtml b/themes/bootstrap3/templates/search/facet-list.phtml index b3bae437d46924450ecd9b49b5e1b8b28232a90c..181bca6ec2d19c9df3b0a44f895cd8fe8f4c43ef 100644 --- a/themes/bootstrap3/templates/search/facet-list.phtml +++ b/themes/bootstrap3/templates/search/facet-list.phtml @@ -11,6 +11,7 @@ $searchAction .= urlencode($this->baseUriExtra); $urlBase .= '&baseUriExtra=' . urlencode($this->baseUriExtra); } + $this->headTitle($this->translate('facet_list_for', ['%%field%%' => $this->facetLabel])); ?> <h2><?=$this->transEsc($this->facetLabel) ?></h2> <?php if (count($this->sortOptions) > 1): ?> diff --git a/themes/bootstrap3/templates/search/results.phtml b/themes/bootstrap3/templates/search/results.phtml index 02f1f87d4175aa3bc42766443e7b6a05619fe41d..46e1b8e21a2e83149748999edc89e8d80784f4c5 100644 --- a/themes/bootstrap3/templates/search/results.phtml +++ b/themes/bootstrap3/templates/search/results.phtml @@ -54,8 +54,8 @@ <div class="<?=$this->layoutClass('mainbody')?>"> <?php if (($recordTotal = $this->results->getResultTotal()) > 0): // only display these at very top if we have results ?> - <?php foreach ($this->results->getRecommendations('top') as $current): ?> - <?=$this->recommend($current)?> + <?php foreach ($this->results->getRecommendations('top') as $index => $current): ?> + <?=$this->recommend($current, 'top', $index)?> <?php endforeach; ?> <?php endif; ?> <?=$this->flashmessages()?> @@ -63,6 +63,9 @@ <div class="search-stats"> <?php if ($recordTotal > 0): ?> <?=$this->context()->renderInContext('search/controls/showing.phtml', ['lookfor' => $lookfor, 'recordTotal' => $recordTotal]) ?> + <a class="search-filter-toggle visible-xs" href="#search-sidebar" data-toggle="offcanvas" title="<?=$this->transEsc('sidebar_expand') ?>"> + <?=$this->transEsc('Refine Results') ?> + </a> <?php else: ?> <h2><?=$this->transEsc('nohit_heading')?></h2> <?php endif; ?> @@ -90,12 +93,12 @@ <?php if (isset($this->parseError)): ?> <p class="alert alert-danger"><?=$this->transEsc('nohit_parse_error')?></p> <?php endif; ?> - <?php foreach (($top = $this->results->getRecommendations('top')) as $current): ?> - <?=$this->recommend($current)?> + <?php foreach (($top = $this->results->getRecommendations('top')) as $index => $current): ?> + <?=$this->recommend($current, 'top', $index)?> <?php endforeach; ?> - <?php foreach ($this->results->getRecommendations('noresults') as $current): ?> + <?php foreach ($this->results->getRecommendations('noresults') as $index => $current): ?> <?php if (!in_array($current, $top)): ?> - <?=$this->recommend($current)?> + <?=$this->recommend($current, 'noresults', $index)?> <?php endif; ?> <?php endforeach; ?> <?php else: ?> @@ -129,9 +132,9 @@ <?php /* End Main Listing */ ?> <?php /* Narrow Search Options */ ?> -<div class="<?=$this->layoutClass('sidebar')?>"> - <?php foreach ($this->results->getRecommendations('side') as $current): ?> - <?=$this->recommend($current)?> +<div class="<?=$this->layoutClass('sidebar')?>" id="search-sidebar"> + <?php foreach ($this->results->getRecommendations('side') as $index => $current): ?> + <?=$this->recommend($current, 'side', $index)?> <?php endforeach; ?> </div> <?php /* End Narrow Search Options */ ?> diff --git a/themes/bootstrap3/templates/search/searchbox.phtml b/themes/bootstrap3/templates/search/searchbox.phtml index 4d4d4ca1fed76b88afa334efb3a814f533f6a70f..f0f9470c95c71cf6cf337b675a3728bc3d9055a6 100644 --- a/themes/bootstrap3/templates/search/searchbox.phtml +++ b/themes/bootstrap3/templates/search/searchbox.phtml @@ -44,9 +44,9 @@ <form id="searchForm" class="searchForm navbar-form navbar-left flip" method="get" action="<?=$this->url($basicSearch)?>" name="searchForm" autocomplete="off"> <?= $this->context($this)->renderInContext('search/searchTabs', ['searchTabs' => $tabConfig['tabs']]); ?> <?php $placeholder = $this->searchbox()->getPlaceholderText($tabConfig['selected']['id'] ?? null); ?> - <input id="searchForm_lookfor" class="searchForm_lookfor form-control search-query<?php if($this->searchbox()->autocompleteEnabled($this->searchClassId)):?> autocomplete searcher:<?=$this->escapeHtmlAttr($this->searchClassId) ?><?php endif ?>" type="text" name="lookfor" value="<?=$this->escapeHtmlAttr($this->lookfor)?>"<?php if ($placeholder): ?> placeholder="<?=$this->transEsc($placeholder) ?>"<?php endif ?> /> + <input id="searchForm_lookfor" class="searchForm_lookfor form-control search-query<?php if($this->searchbox()->autocompleteEnabled($this->searchClassId)):?> autocomplete searcher:<?=$this->escapeHtmlAttr($this->searchClassId) ?><?=$this->searchbox()->autocompleteAutoSubmit($this->searchClassId) ? ' ac-auto-submit' : '' ?><?php endif ?>" type="text" name="lookfor" value="<?=$this->escapeHtmlAttr($this->lookfor)?>"<?php if ($placeholder): ?> placeholder="<?=$this->transEsc($placeholder) ?>"<?php endif ?> aria-label="<?=$this->transEsc("search_terms")?>" /> <?php if ($handlerCount > 1): ?> - <select id="searchForm_type" class="searchForm_type form-control" name="type" data-native-menu="false"> + <select id="searchForm_type" class="searchForm_type form-control" name="type" data-native-menu="false" aria-label="<?=$this->transEsc("Search type")?>"> <?php foreach ($handlers as $handler): ?> <option value="<?=$this->escapeHtmlAttr($handler['value'])?>"<?=$handler['selected'] ? ' selected="selected"' : ''?>><?=$handler['indent'] ? '-- ' : ''?><?=$this->transEsc($handler['label'])?></option> <?php endforeach; ?> diff --git a/themes/root/templates/Email/form.phtml b/themes/root/templates/Email/form.phtml new file mode 100644 index 0000000000000000000000000000000000000000..2075c6dbfd383d223fcfc9a7aabe1f58d0ea35ee --- /dev/null +++ b/themes/root/templates/Email/form.phtml @@ -0,0 +1,12 @@ +<?php foreach($this->fields as $key => $data): ?> +<?php $isTextarea = $data['type'] === 'textarea'; ?> +<?php if ($isTextarea): ?> +----- +<?=$key?>: +<?=$data['value']?> + +----- +<?php else: ?> +<?= "$key: " . $data['value'] . PHP_EOL ?> +<?php endif ?> +<?php endforeach ?> diff --git a/themes/root/templates/HelpTranslations/fr/advsearch.phtml b/themes/root/templates/HelpTranslations/fr/advsearch.phtml index 1aa65e2bca239c776818e6baf413c3edb902f5dc..9c4aa3144a8f7d442bc81d7a722a89c9b2525b95 100644 --- a/themes/root/templates/HelpTranslations/fr/advsearch.phtml +++ b/themes/root/templates/HelpTranslations/fr/advsearch.phtml @@ -1,4 +1,4 @@ -<h1>Aide sur la recherche avencée</h1> +<h1>Aide sur la recherche avancée</h1> <ul class="HelpMenu"> <li><a href="#Search Fields">Champ de recherche</a></li> @@ -8,59 +8,48 @@ <dl class="Content"> <dt><a name="Search Fields"></a>Champ de recherche</dt> <dd> - <p>Lorsque vous visitez la première fois la recherche avancée, plusieures - champs de saisie vous sont présentés. Vous pouvez taper dans chaque - champ de saisie tous les mots que vous désirez rechercher. Certaines + <p>Dans chaque champ de recherche, vous pouvez saisir les mots pour lesquels vous désirez trouver un résultat. Certaines chaînes de caractères, ou <a href="<?=$this->url('help-home')?>?topic=search">« opérateurs »</a> - , modifient le comportement VuFind. + , modifient le comportement de la recherche. </p> - <p>Chaque champ est accomapgner par un menu déroulant, avec lequel vous - pouvez specifiquer le type de recherche (titre, auteur etc.). - Vous pouvez mélanger les types de recherche comme vous voulez. + <p>Pour chaque champ de recherche, un menu déroulant permet de + préciser la fonction du terme recherché (titre, auteur etc.). + Vous pouvez ainsi combiner plusieurs critères. </p> - <p>Le réglage "correspond à " permet de modifier le comportement de recherche + <p>Le paramètre "correspond à " permet de modifier le comportement de recherche avec plusieur champs de recherche: </p> <ul> - <li>TOUS les mots suivant - Affiche les dossiers qui correspondent - avec chaque terme.</li> - <li>AU MOINS un des mots suivants - Affiche les dossiers qui correspondent - avec au moins un des termes.</li> - <li>AUCUN des mots suivants -- Affiche tous les dossiers, sauf celui qui - correspond avec les termes de recherche.</li> + <li>TOUS les termes - Pour afficher les notices qui correspondent + à l'ensemble des mots saisis (ET).</li> + <li>UN des termes - Pour afficher les notices qui correspondent + à au moins l'un ou l'autre des mots saisis (OU).</li> + <li>AUCUN terme - À utiliser seul dans un groupe de recherche pour exclure les notices + qui ne correspondent pas aux mots saisis.</li> </ul> - <p>Vous pouvez ajouter tant de champ de recherche que vous voulez, en + <p>Vous pouvez ajouter tant de champ de recherche que nécessaire, en cliquant sur "Ajouter un champ de recherche". </p> </dd> <dt><a name="Search Groups"></a>Groupe de recherche</dt> <dd> - <p>Pour des recherches plus complexe, une simple recherche ne suffit pas. - Par exemple, supposons que voud recherchez des livres sur l'histoire de - Chine et de l'Inde. Si vous faites une recherche "TOUS les mots suivants" - vous obtiendrez des livres d'histoire sur l'Inde ET la Chine. Si vous - faites une recherche avec "AU MOINS un des mots suivants" vous obtiendrez - des livre qui non rien avoir avec l'Inde ou la Chine. + <p>Un groupe de recherche permet de formuler une recherche plus complexe, en + combinant plusieurs groupes de champs de recherche. Il est possible d'ajouter + un nouveau groupe en cliquant sur "Ajouter un groupe de recherche", + ou d'en effacer un en cliquant sur "Effacer un groupe de + recherche". Pour combiner les critères définis par chaque groupe, vous pouvez + choisir "TOUS les groupes" ou "UN des groupes". </p> - <p>Un groupe de recherche est une possibilité de soumettre une requête à - l'aide de differentes groupes de champs de rechereche. Chaque fois que - vous cliquez sur "Ajouter un groupe de recherche", un nouveau groupe de - recherche est ajouter. Dès que vous avez plusieurs groupes de recherche - il est possible d'effacer un groupe en cliquant sur "Effacer un groupe de - recherche". Vous pouvez ensuite régler la recherche en spécifiant une - recherche avec "TOUTES les groupes de recherche" ou - "AU MOINS un groupe de recherche". - </p> - <p>Pour rechercher des livre sur l'histoire de Chine ou de l'Inde - vous pouvez par exemple faire une recherche de la manière suivante: + <p>Exemple : pour trouver des ressources sur l'histoire de Chine ou de l'Inde + vous pouvez faire une recherche de la manière suivante: </p> <ul> - <li>Tapez dans le premier groupe "Inde" et "Chine" et choisisez "AU MOINS - un des mot suivant" + <li>Dans le premier groupe, saisir "Inde" dans le premier champ, "Chine" dans le deuxième, + et choisir la correspondance "UN des termes". </li> - <li>Ajoutez un second groupe de recherche et tapez "histoire".</li> - <li>Réglez la recherche sur "TOUS les groupes de recherche". + <li>Ajouter un second groupe de recherche et saisir "histoire".</li> + <li>Choisir la correspondance sur "TOUS les groupes de recherche". </li> </ul> </dd> diff --git a/themes/root/templates/HelpTranslations/fr/search.phtml b/themes/root/templates/HelpTranslations/fr/search.phtml index 3ddaa5a43afcf49a490e58f7fdb69c45d58a33d0..b59cd0a5d7cc7dee8b2e0611e84ce0ccb33535dc 100644 --- a/themes/root/templates/HelpTranslations/fr/search.phtml +++ b/themes/root/templates/HelpTranslations/fr/search.phtml @@ -22,18 +22,18 @@ <dd> <p>La troncature est un signe qui remplace une ou plusieurs lettres d'un mot.</p> <p><strong>?</strong> (point d'interrogation) représente n'importe quel caractère unique.</p> - <p>Par exemple, pour rechercher "texte" ou "teste" vous pouvez utiliser:</p> - <pre class="code">te?t</pre> - <p>Pour remplacer 0 ou plus de lettres d'un mot utilisez <strong>*</strong> - (astérisque).</p> - <p>Par exemple pour rechercher "testes", "teste", "testez" vous pouvez - utilisez</p> - <pre class="code">test*</pre> - <p>L'astérisque représente n'importe quelle chaîne de caractères et peut être - placé à n'importe quelle place.</p> - <pre class="code">te*t</pre> - <p>Notez: Il n'est pas possible d'utiliser l'astérisque ou le point - d'interrogation comme premier signe dans une recherche.</p> + <p>Par exemple, pour rechercher "francophone" ou "francophobe" vous pouvez utiliser :</p> + <pre class="code">francopho?e</pre> + <p>Pour remplacer 0, 1 ou plusieurs lettres d'un mot utilisez <strong>*</strong> + (astérisque).</p> + <p>Par exemple pour rechercher "francophone", "francophonie", "francophobe" vous pouvez + utilisez</p> + <pre class="code">francopho*</pre> + <p>L'astérisque représente n'importe quelle chaîne de caractères et peut aussi être + placée au milieu d'un mot.</p> + <pre class="code">francopho*e</pre> + <p>Note : Il n'est pas possible d'utiliser l'astérisque ou le point + d'interrogation comme premier signe dans une recherche.</p> </dd> <dt><a name="Fuzzy Searches"></a>Recherches floues</dt> diff --git a/themes/root/theme.config.php b/themes/root/theme.config.php index d175736cfc7abff1ea122edcefe462b5efa00f60..0f2215e799b60b4cc73c83bd9f2037e3e9841463 100644 --- a/themes/root/theme.config.php +++ b/themes/root/theme.config.php @@ -18,6 +18,7 @@ return [ 'VuFind\View\Helper\Root\CurrentPath' => 'Zend\ServiceManager\Factory\InvokableFactory', 'VuFind\View\Helper\Root\DateTime' => 'VuFind\View\Helper\Root\DateTimeFactory', 'VuFind\View\Helper\Root\DisplayLanguageOption' => 'VuFind\View\Helper\Root\DisplayLanguageOptionFactory', + 'VuFind\View\Helper\Root\Doi' => 'VuFind\View\Helper\Root\DoiFactory', 'VuFind\View\Helper\Root\Export' => 'VuFind\View\Helper\Root\ExportFactory', 'VuFind\View\Helper\Root\Feedback' => 'VuFind\View\Helper\Root\FeedbackFactory', 'VuFind\View\Helper\Root\Flashmessages' => 'VuFind\View\Helper\Root\FlashmessagesFactory', @@ -77,6 +78,7 @@ return [ 'currentPath' => 'VuFind\View\Helper\Root\CurrentPath', 'dateTime' => 'VuFind\View\Helper\Root\DateTime', 'displayLanguageOption' => 'VuFind\View\Helper\Root\DisplayLanguageOption', + 'doi' => 'VuFind\View\Helper\Root\Doi', 'export' => 'VuFind\View\Helper\Root\Export', 'feedback' => 'VuFind\View\Helper\Root\Feedback', 'flashmessages' => 'VuFind\View\Helper\Root\Flashmessages', diff --git a/themes/sandal/less/sandal.less b/themes/sandal/less/sandal.less index a3ee3044f57f7d745b85ff01a14677b6ebf27b16..6c2095afc59f2958cec121f366f8c16ec3cdb796 100644 --- a/themes/sandal/less/sandal.less +++ b/themes/sandal/less/sandal.less @@ -224,7 +224,10 @@ header { padding-right: 0; } .sidebar .checkbox-filter, -.sidebar > h4 { margin-left: 1rem; } +.sidebar > h4 { + margin-left: 1rem; + margin-right: 1rem; +} .jstree-facet { .main .fa-check { margin-top: 3px; } diff --git a/themes/sandal/scss/common.scss b/themes/sandal/scss/common.scss index 30c1391f0e593f709b198a00ae30a8ae69b6268a..f835a95b6db203c302fcfe5627b3ead5159e8153 100644 --- a/themes/sandal/scss/common.scss +++ b/themes/sandal/scss/common.scss @@ -3,12 +3,13 @@ $list-group-border-radius: 0 !default; $border-radius-large: 0 !default; // modal /* ------ Common element changes ------ */ -h1, h2, h3, h4 { - margin: 0; - margin-bottom: 1rem; - - .help-block & { margin: 0; } +.help-block { + h1, + h2, + h3, + h4 { margin: 0; } } + .highlight, mark { background-color: $highlighter-color; } table { font-size: $reduced-font-size; } @@ -86,8 +87,8 @@ select.form-control { .alert-success, .alert-success:hover { color: $dark-green; - background-color: $light-green; - a { color: $white; } + background-color: $washed-green; + a { color: $green; } } .alert-danger, .alert-danger:hover { diff --git a/themes/sandal/scss/sandal.scss b/themes/sandal/scss/sandal.scss index 5d34610ba2c5608a3d52d84d2a10f02b8d4c906d..5a6a7108278a4a7262e654e3b39a7bafe406662e 100644 --- a/themes/sandal/scss/sandal.scss +++ b/themes/sandal/scss/sandal.scss @@ -162,6 +162,8 @@ header { font-size: $reduced-font-size; background-color: $light-gray; + h1,h2,h3,h4 { margin-top: 0; } + .facet-group { margin-left: 1rem; margin-right: 1rem; @@ -206,17 +208,26 @@ header { .facet .badge { max-height: 15px; margin-top: 5px; - line-height: .8; - background-color: $sidebar-item-badge; } } + +.facet .badge { + flex-shrink: 0; + max-height: 19px; + line-height: .8; + background-color: $sidebar-item-badge; +} + .sidebar.left, .sidebar.right { padding-left: 0; padding-right: 0; } .sidebar .checkbox-filter, -.sidebar > h4 { margin-left: 1rem; } +.sidebar > h4 { + margin-left: 1rem; + margin-right: 1rem; +} .jstree-facet { .main .fa-check { margin-top: 3px; } diff --git a/themes/sandal/scss/search.scss b/themes/sandal/scss/search.scss index 0ad5d19635c0815901596bbb4642228801156d92..04af0a1a57829de5c5ae69f65d765673494c780e 100644 --- a/themes/sandal/scss/search.scss +++ b/themes/sandal/scss/search.scss @@ -17,9 +17,8 @@ .result { margin-left: -1rem; margin-right: -1rem; - padding-top: 1rem; - padding-left: 1rem; - padding-bottom: 1rem; + padding: 1rem; + padding-right: 0; border-bottom: 1px solid $moon-gray; font-size: $reduced-font-size; @@ -112,7 +111,6 @@ .grid-result .grid-checkbox label { width: 100%; } @media (min-width: 768px) { - .result { padding-right: 1rem; } .result-body { width: 75%; } .result-links { width: 25%; @@ -259,8 +257,12 @@ padding-top: 1rem; padding-bottom: 1rem; } -.combined-search-container { - @include full-width(); - - .result { margin-right: 0; } +.template-dir-combined.template-name-results { + .bulkActionButtons { + max-width: 1170px; + margin: auto; + } + .main .container { + width: 100%; + } }