diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..153cf3ef5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +; top-most EditorConfig file +root = true + +; Unix-style newlines +[*] +end_of_line = LF + +[*.php] +indent_style = space +indent_size = 4 diff --git a/.env.dist b/.env.dist new file mode 100644 index 000000000..61dfee9ff --- /dev/null +++ b/.env.dist @@ -0,0 +1,23 @@ +# This file is a "template" of which env vars needs to be defined in your configuration or in an .env file +# Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. +# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_DEBUG=1 +APP_SECRET=67d829bf61dc5f87a73fd814e2c9f629 +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# For a sqlite database, use: "sqlite:///%kernel.project_dir%/var/data.db" +# Set "serverVersion" to your server version to avoid edge-case exceptions and extra database calls +DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/blog.sqlite +###< doctrine/doctrine-bundle ### + +###> symfony/swiftmailer-bundle ### +# For Gmail as a transport, use: "gmail://username:password@localhost" +# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" +# Delivery is disabled by default via "null://localhost" +MAILER_URL=null://localhost +###< symfony/swiftmailer-bundle ### diff --git a/.gitignore b/.gitignore index 643645727..253b2cee4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,36 @@ -/app/bootstrap.php.cache -/app/cache/* -/app/logs/* -!app/cache/.gitkeep -!app/logs/.gitkeep /build/ +/node_modules/ +/var/* +!/var/cache +/var/cache/* +!var/cache/.gitkeep +!/var/data +!/var/log +/var/log/* +!var/log/.gitkeep +!/var/sessions +/var/sessions/* +!var/sessions/.gitkeep +!var/SymfonyRequirements.php +/public/build/fonts/glyphicons-* +/public/build/images/glyphicons-* + +###> symfony/framework-bundle ### +.env +/public/bundles/ +/var/ /vendor/ -/bin/ -/composer.phar +###< symfony/framework-bundle ### + +###> symfony/phpunit-bridge ### +/phpunit.xml +###< symfony/phpunit-bridge ### + +###> symfony/web-server-bundle ### +.web-server-pid +###< symfony/web-server-bundle ### + +###> friendsofphp/php-cs-fixer ### +.php_cs +.php_cs.cache +###< friendsofphp/php-cs-fixer ### diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 000000000..ecd127eb3 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,42 @@ + + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +COMMENT; + +$finder = PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude('config') + ->exclude('var') + ->exclude('public/bundles') + ->exclude('public/build') +; + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + 'array_syntax' => ['syntax' => 'short'], + 'header_comment' => ['header' => $fileHeaderComment, 'separate' => 'both'], + 'linebreak_after_opening_tag' => true, + 'mb_str_functions' => true, + 'no_php4_constructor' => true, + 'no_unreachable_default_argument_value' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_imports' => true, + 'php_unit_strict' => true, + 'phpdoc_order' => true, + 'semicolon_after_instruction' => true, + 'strict_comparison' => true, + 'strict_param' => true, + ]) + ->setFinder($finder) + ->setCacheFile(__DIR__.'/var/.php_cs.cache') +; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..b908ee4d5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,39 @@ +language: php +sudo: false + +cache: + directories: + - $HOME/.composer/cache/files + - $HOME/symfony-bridge/.phpunit + +env: + global: + - SYMFONY_PHPUNIT_DIR="$HOME/symfony-bridge/.phpunit" + +matrix: + fast_finish: true + include: + - php: 7.1 + +before_install: + - phpenv config-rm xdebug.ini + - composer self-update + +install: + - composer install + - ./vendor/bin/simple-phpunit install + +script: + - ./vendor/bin/simple-phpunit + # this checks that the source code follows the Symfony Code Syntax rules + - ./vendor/bin/php-cs-fixer fix --diff --dry-run -v + # this checks that the YAML config files contain no syntax errors + - ./bin/console lint:yaml config + # this checks that the Twig template files contain no syntax errors + - ./bin/console lint:twig templates + # this checks that the XLIFF translations contain no syntax errors + - ./bin/console lint:xliff translations + # this checks that the application doesn't use dependencies with known security vulnerabilities + - ./bin/console security:check --end-point=http://security.sensiolabs.org/check_lock + # this checks that the composer.json and composer.lock files are valid + - composer validate --strict diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb992a561..906c46f5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,18 +4,4 @@ Contributing The Symfony Demo application is an open source project. Contributions made by the community are welcome. Send us your ideas, code reviews, pull requests and feature requests to help us improve this project. All contributions must follow -the [usual Symfony contribution requirements](http://symfony.com/doc/current/contributing/index.html). - -Web Assets Management ---------------------- - -This project manages its web assets in a special way to allow them to work -without configuring any option, installing any tool or executing any command. -If your contribution changes CSS styles or JavaScript code in any way, make -sure to regenerate the `web/css/app.css` and `web/js/app.js` files. To do so, -uncomment the Assetic blocks in the `app/Resources/views/base.html.twig` and -execute the following command: - -```bash -$ php app/console assetic:dump --no-debug -``` +the [usual Symfony contribution requirements](https://symfony.com/doc/current/contributing/index.html). diff --git a/LICENSE b/LICENSE index a69485974..2ca4d6305 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015 Fabien Potencier +Copyright (c) 2015-2017 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8cc40c5b8..c2e75d6d2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ We use official "Symfony Demo Application" to demonstrate basics of Codeception ``` composer install -n -php app/console doctrine:fixtures:load -n --env test +php bin/console doctrine:fixtures:load -n --env test php bin/codecept run ``` @@ -21,54 +21,45 @@ to develop Symfony applications following the recommended best practices. Requirements ------------ - * PHP 5.3 or higher; + * PHP 7.1.3 or higher; * PDO-SQLite PHP extension enabled; - * and the [usual Symfony application requirements](http://symfony.com/doc/current/reference/requirements.html). + * and the [usual Symfony application requirements][1]. Installation ------------ -First, install the [Symfony Installer](https://github.com/symfony/symfony-installer) -if you haven't already. Then, install the Symfony Demo Application executing -this command anywhere in your system: +Execute this command to install the project: ```bash -$ symfony demo - -# if you're using Windows: -$ php symfony demo +$ composer create-project symfony/symfony-demo ``` -If the `demo` command is not available, update your Symfony Installer to the -most recent version executing the `symfony self-update` command. - -> **NOTE** -> -> If you can't use the Symfony Installer, download and install the demo -> application using Git and Composer: -> -> $ git clone https://github.com/symfony/symfony-demo -> $ cd symfony-demo/ -> $ composer install +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) Usage ----- -If you have PHP 5.4 or higher, there is no need to configure a virtual host -in your web server to access the application. Just use the built-in web server: +There's no need to configure anything to run the application. Just execute this +command to run the built-in web server and access the application in your +browser at : ```bash $ cd symfony-demo/ -$ php app/console server:run +$ php bin/console server:run ``` -This command will start a web server for the Symfony application. Now you can -access the application in your browser at . You can -stop the built-in web server by pressing `Ctrl + C` while you're in the -terminal. +Alternatively, you can [configure a fully-featured web server][2] like Nginx +or Apache to run the application. + +Tests +----- + +Execute this command to run tests: + +```bash +$ cd symfony-demo/ +$ ./vendor/bin/simple-phpunit +``` -> **NOTE** -> -> If you're using PHP 5.3, configure your web server to point at the `web/` -> directory of the project. For more details, see: -> http://symfony.com/doc/current/cookbook/configuration/web_server_configuration.html +[1]: https://symfony.com/doc/current/reference/requirements.html +[2]: https://symfony.com/doc/current/cookbook/configuration/web_server_configuration.html diff --git a/app.json b/app.json new file mode 100644 index 000000000..c82585210 --- /dev/null +++ b/app.json @@ -0,0 +1,39 @@ +{ + "name": "Symfony Demo Application", + "description": "The official demo application for the Symfony framework.", + "keywords": [ + "php", + "symfony" + ], + "website": "https://symfony.com/download", + "repository": "https://github.com/symfony/symfony-demo", + "logo": "https://symfony.com/images/v5/pictos/demoapp.svg?v=4", + "success_url": "/", + "scripts": { + "postdeploy": "php bin/console doctrine:schema:create && php bin/console doctrine:fixtures:load -n", + "test-setup": "php bin/console doctrine:schema:create && php bin/console doctrine:fixtures:load -n", + "test": "phpunit" + }, + "env": { + "APP_ENV": { + "value": "prod", + "description": "If you want to use the Symfony `dev` environment in the deployed application, you must move the necessary dependencies (like SensioGeneratorBundle) from `require-dev` to `require`. This will introduce security issues because development tools like the WebProfiler reveal sensitive information." + }, + "APP_DEBUG": { + "value": "0" + }, + "APP_SECRET": { + "description": "Extra entropy for %kernel.secret%; used for CSRF tokens, cookies and signed URLs.", + "generator": "secret" + }, + "MAILER_URL": { + "value": "null://localhost", + "description": "A DSN-like configuration string for the mail server. See https://symfony.com/doc/current/reference/configuration/swiftmailer.html#url" + }, + "SYMFONY_LOG": "php://stderr" + }, + "addons": [ + "heroku-postgresql" + ], + "image": "heroku/php" +} diff --git a/app/.htaccess b/app/.htaccess deleted file mode 100644 index fb1de45bd..000000000 --- a/app/.htaccess +++ /dev/null @@ -1,7 +0,0 @@ - - Require all denied - - - Order deny,allow - Deny from all - diff --git a/app/AppCache.php b/app/AppCache.php deleted file mode 100644 index ddb51db05..000000000 --- a/app/AppCache.php +++ /dev/null @@ -1,9 +0,0 @@ -getEnvironment(), array('dev', 'test'))) { - $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); - $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); - $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); - $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); - } - - return $bundles; - } - - public function registerContainerConfiguration(LoaderInterface $loader) - { - $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); - } -} diff --git a/app/Resources/assets/css/font-lato.css b/app/Resources/assets/css/font-lato.css deleted file mode 100644 index 8ef56925f..000000000 --- a/app/Resources/assets/css/font-lato.css +++ /dev/null @@ -1,24 +0,0 @@ -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 400; - src: local('Lato Regular'), local('Lato-Regular'), url('../fonts/lato/Lato-Regular.woff') format('woff'); -} -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 700; - src: local('Lato Bold'), local('Lato-Bold'), url('../fonts/lato/Lato-Bold.woff') format('woff'); -} -@font-face { - font-family: 'Lato'; - font-style: italic; - font-weight: 400; - src: local('Lato Italic'), local('Lato-Italic'), url('../fonts/lato/Lato-Italic.woff') format('woff'); -} -@font-face { - font-family: 'Lato'; - font-style: italic; - font-weight: 700; - src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url('../fonts/lato/Lato-BoldItalic.woff') format('woff'); -} diff --git a/app/Resources/assets/css/highlight-solarized-light.css b/app/Resources/assets/css/highlight-solarized-light.css deleted file mode 100644 index fa2cc305c..000000000 --- a/app/Resources/assets/css/highlight-solarized-light.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - -Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0.5em; - background: #fdf6e3; - color: #657b83; - -webkit-text-size-adjust: none; -} - -.hljs-comment, -.diff .hljs-header, -.hljs-doctype, -.hljs-pi, -.lisp .hljs-string, -.hljs-javadoc { - color: #93a1a1; -} - -/* Solarized Green */ -.hljs-keyword, -.hljs-winutils, -.method, -.hljs-addition, -.css .hljs-tag, -.hljs-request, -.hljs-status, -.nginx .hljs-title { - color: #859900; -} - -/* Solarized Cyan */ -.hljs-number, -.hljs-command, -.hljs-string, -.hljs-tag .hljs-value, -.hljs-rules .hljs-value, -.hljs-phpdoc, -.hljs-dartdoc, -.tex .hljs-formula, -.hljs-regexp, -.hljs-hexcolor, -.hljs-link_url { - color: #2aa198; -} - -/* Solarized Blue */ -.hljs-title, -.hljs-localvars, -.hljs-chunk, -.hljs-decorator, -.hljs-built_in, -.hljs-identifier, -.vhdl .hljs-literal, -.hljs-id, -.css .hljs-function { - color: #268bd2; -} - -/* Solarized Yellow */ -.hljs-attribute, -.hljs-variable, -.lisp .hljs-body, -.smalltalk .hljs-number, -.hljs-constant, -.hljs-class .hljs-title, -.hljs-parent, -.hljs-type, -.hljs-link_reference { - color: #b58900; -} - -/* Solarized Orange */ -.hljs-preprocessor, -.hljs-preprocessor .hljs-keyword, -.hljs-pragma, -.hljs-shebang, -.hljs-symbol, -.hljs-symbol .hljs-string, -.diff .hljs-change, -.hljs-special, -.hljs-attr_selector, -.hljs-subst, -.hljs-cdata, -.css .hljs-pseudo, -.hljs-header { - color: #cb4b16; -} - -/* Solarized Red */ -.hljs-deletion, -.hljs-important { - color: #dc322f; -} - -/* Solarized Violet */ -.hljs-link_label { - color: #6c71c4; -} - -.tex .hljs-formula { - background: #eee8d5; -} diff --git a/app/Resources/assets/js/bootstrap-3.3.4.js b/app/Resources/assets/js/bootstrap-3.3.4.js deleted file mode 100755 index 1c88b71e8..000000000 --- a/app/Resources/assets/js/bootstrap-3.3.4.js +++ /dev/null @@ -1,2317 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -if (typeof jQuery === 'undefined') { - throw new Error('Bootstrap\'s JavaScript requires jQuery') -} - -+function ($) { - 'use strict'; - var version = $.fn.jquery.split(' ')[0].split('.') - if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) { - throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher') - } -}(jQuery); - -/* ======================================================================== - * Bootstrap: transition.js v3.3.4 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.3.4 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.VERSION = '3.3.4' - - Alert.TRANSITION_DURATION = 150 - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.closest('.alert') - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - // detach from parent, fire event then clean up data - $parent.detach().trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(Alert.TRANSITION_DURATION) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.alert - - $.fn.alert = Plugin - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.3.4 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.VERSION = '3.3.4' - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state = state + 'Text' - - if (data.resetText == null) $el.data('resetText', $el[val]()) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - $el[val](data[state] == null ? this.options[state] : data[state]) - - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false - else $parent.find('.active').removeClass('active') - } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') - } else { - this.$element.attr('aria-pressed', !this.$element.hasClass('active')) - } - - if (changed) this.$element.toggleClass('active') - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - var old = $.fn.button - - $.fn.button = Plugin - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document) - .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - e.preventDefault() - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { - $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.3.4 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = null - this.sliding = null - this.interval = null - this.$active = null - this.$items = null - - this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - - this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element - .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) - .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) - } - - Carousel.VERSION = '3.3.4' - - Carousel.TRANSITION_DURATION = 600 - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true, - keyboard: true - } - - Carousel.prototype.keydown = function (e) { - if (/input|textarea/i.test(e.target.tagName)) return - switch (e.which) { - case 37: this.prev(); break - case 39: this.next(); break - default: return - } - - e.preventDefault() - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getItemIndex = function (item) { - this.$items = item.parent().children('.item') - return this.$items.index(item || this.$active) - } - - Carousel.prototype.getItemForDirection = function (direction, active) { - var activeIndex = this.getItemIndex(active) - var willWrap = (direction == 'prev' && activeIndex === 0) - || (direction == 'next' && activeIndex == (this.$items.length - 1)) - if (willWrap && !this.options.wrap) return active - var delta = direction == 'prev' ? -1 : 1 - var itemIndex = (activeIndex + delta) % this.$items.length - return this.$items.eq(itemIndex) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || this.getItemForDirection(type, $active) - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var that = this - - if ($next.hasClass('active')) return (this.sliding = false) - - var relatedTarget = $next[0] - var slideEvent = $.Event('slide.bs.carousel', { - relatedTarget: relatedTarget, - direction: direction - }) - this.$element.trigger(slideEvent) - if (slideEvent.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) - $nextIndicator && $nextIndicator.addClass('active') - } - - var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one('bsTransitionEnd', function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { - that.$element.trigger(slidEvent) - }, 0) - }) - .emulateTransitionEnd(Carousel.TRANSITION_DURATION) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger(slidEvent) - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - var old = $.fn.carousel - - $.fn.carousel = Plugin - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - var clickHandler = function (e) { - var href - var $this = $(this) - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 - if (!$target.hasClass('carousel')) return - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - Plugin.call($target, options) - - if (slideIndex) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - } - - $(document) - .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) - .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Plugin.call($carousel, $carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.3.4 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.4' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var activesData - var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - Collapse.prototype.getParent = function () { - return $(this.options.parent) - .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') - .each($.proxy(function (i, element) { - var $element = $(element) - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) - }, this)) - .end() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.3.4 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle="dropdown"]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.VERSION = '3.3.4' - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $('