Pastakhov has uploaded a new change for review. https://gerrit.wikimedia.org/r/172222
Change subject: Init and add Slick widget (v 1.0.0) ...................................................................... Init and add Slick widget (v 1.0.0) Change-Id: Ifb57ca9716953389f3601373fe875e0d14d6fb7f --- A .jshintignore A PhpTagsWidgets.i18n.php A PhpTagsWidgets.init.php A PhpTagsWidgets.php A i18n/en.json A i18n/qqq.json A includes/GenericWidget.php A includes/WidgetSlick.php A resources/ext.pw.onReady.js A resources/libs/slick/LICENSE A resources/libs/slick/README.markdown A resources/libs/slick/ajax-loader.gif A resources/libs/slick/fonts/slick.eot A resources/libs/slick/fonts/slick.svg A resources/libs/slick/fonts/slick.ttf A resources/libs/slick/fonts/slick.woff A resources/libs/slick/slick.css A resources/libs/slick/slick.js A tests/phpunit/Slick_Test.php 19 files changed, 2,864 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/PhpTagsWidgets refs/changes/22/172222/1 diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..7faed22 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,2 @@ +# upstream libs +resources/libs/ diff --git a/PhpTagsWidgets.i18n.php b/PhpTagsWidgets.i18n.php new file mode 100644 index 0000000..8ee5f72 --- /dev/null +++ b/PhpTagsWidgets.i18n.php @@ -0,0 +1,31 @@ +<?php +/** + * This is a backwards-compatibility shim, generated by: + * https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2FgenerateJsonI18n.php + * + * Beginning with MediaWiki 1.23, translation strings are stored in json files, + * and the EXTENSION.i18n.php file only exists to provide compatibility with + * older releases of MediaWiki. For more information about this migration, see: + * https://www.mediawiki.org/wiki/Requests_for_comment/Localisation_format + * + * This shim maintains compatibility back to MediaWiki 1.17. + */ +$messages = array(); +$GLOBALS['wgHooks']['LocalisationCacheRecache'][] = function ( $cache, $code, &$cachedData ) { + $codeSequence = array_merge( array( $code ), $cachedData['fallbackSequence'] ); + foreach ( $codeSequence as $csCode ) { + $fileName = __DIR__ . "/extensions/PhpTags/i18n/$csCode.json"; + if ( is_readable( $fileName ) ) { + $data = FormatJson::decode( file_get_contents( $fileName ), true ); + foreach ( array_keys( $data ) as $key ) { + if ( $key === '' || $key[0] === '@' ) { + unset( $data[$key] ); + } + } + $cachedData['messages'] = array_merge( $data, $cachedData['messages'] ); + } + + $cachedData['deps'][] = new FileDependency( $fileName ); + } + return true; +}; diff --git a/PhpTagsWidgets.init.php b/PhpTagsWidgets.init.php new file mode 100644 index 0000000..48b710c --- /dev/null +++ b/PhpTagsWidgets.init.php @@ -0,0 +1,15 @@ +<?php + +class PhpTagsWidgetsInit { + + public static function initializeRuntime() { + \PhpTags\Hooks::setObjects( + array( + 'Slick' => 'WidgetSlick', + ) + ); + + return true; + } + +} diff --git a/PhpTagsWidgets.php b/PhpTagsWidgets.php new file mode 100644 index 0000000..00d832f --- /dev/null +++ b/PhpTagsWidgets.php @@ -0,0 +1,91 @@ +<?php +/** + * Main entry point for the PhpTags Widgets extension. + * + * @link https://www.mediawiki.org/wiki/Extension:PhpTags_Widgets Documentation + * @file PhpTagsFunctions.php + * @defgroup PhpTags + * @ingroup Extensions + * @author Pavel Astakhov <pastak...@yandex.ru> + * @licence GNU General Public Licence 2.0 or later + */ + +// Check to see if we are being called as an extension or directly +if ( !defined('MEDIAWIKI') ) { + die( 'This file is an extension to MediaWiki and thus not a valid entry point.' ); +} + +if ( !defined( 'PHPTAGS_VERSION' ) ) { + die( 'ERROR: The <a href="https://www.mediawiki.org/wiki/Extension:PhpTags">extension PhpTags</a> must be installed for the extension PhpTags Widgets to run!' ); +} + +$needVersion = '3.9.0'; +if ( version_compare( PHPTAGS_VERSION, $needVersion, '<' ) ) { + die( + '<b>Error:</b> This version of extension PhpTags Widgets needs <a href="https://www.mediawiki.org/wiki/Extension:PhpTags">PhpTags</a> ' . $needVersion . ' or later. + You are currently using version ' . PHPTAGS_VERSION . '.<br />' + ); +} + +if ( PHPTAGS_HOOK_RELEASE != 5 ) { + die ( + '<b>Error:</b> This version of extension PhpTags Widgets is not compatible to current version of the PhpTags extension.' + ); +} + +define( 'PHPTAGS_WIDGETS_VERSION' , '1.0.1' ); + +// Register this extension on Special:Version +$wgExtensionCredits['phptags'][] = array( + 'path' => __FILE__, + 'name' => 'PhpTags Widgets', + 'version' => PHPTAGS_WIDGETS_VERSION, + 'url' => 'https://www.mediawiki.org/wiki/Extension:PhpTags_Widgets', + 'author' => '[https://www.mediawiki.org/wiki/User:Pastakhov Pavel Astakhov]', + 'descriptionmsg' => 'phptagswidgets-desc' +); + +// Allow translations for this extension +$wgMessagesDirs['PhpTagsWidgets'] = __DIR__ . '/i18n'; +$wgExtensionMessagesFiles['PhpTagsWidgets'] = __DIR__ . '/PhpTagsWidgets.i18n.php'; + +// Specify the function that will initialize the parser function. +/** + * @codeCoverageIgnore + */ +$wgHooks['PhpTagsRuntimeFirstInit'][] = 'PhpTagsWidgetsInit::initializeRuntime'; + +// Preparing classes for autoloading +$wgAutoloadClasses['PhpTagsWidgetsInit'] = __DIR__ . '/PhpTagsWidgets.init.php'; + +$wgAutoloadClasses['PhpTags\\GenericWidget'] = __DIR__ . '/includes/GenericWidget.php'; +$wgAutoloadClasses['PhpTagsObjects\\WidgetSlick'] = __DIR__ . '/includes/WidgetSlick.php'; + +/** + * Add files to phpunit test + * @codeCoverageIgnore + */ +$wgHooks['UnitTestsList'][] = function ( &$files ) { + $testDir = __DIR__ . '/tests/phpunit'; + $files = array_merge( $files, glob( "$testDir/*Test.php" ) ); + return true; +}; + +$wgParserTestFiles[] = __DIR__ . '/tests/parser/PhpTagsWidgetsTests.txt'; + +$tpl = array( + 'localBasePath' => __DIR__ . '/resources', + 'remoteExtPath' => 'PhpTagsWidgets/resources', +); + +$wgResourceModules['ext.PhpTagsWidgets.slick'] = array( + 'group' => 'PhpTagsWidgets', + 'scripts' => 'libs/slick/slick.js', + 'styles' => 'libs/slick/slick.css', + 'dependencies' => array( 'jquery' ), +) + $tpl; + +$wgResourceModules['ext.PhpTagsWidgets.onReady'] = array( + 'group' => 'PhpTagsWidgets', + 'scripts' => 'ext.pw.onReady.js', +) + $tpl; diff --git a/i18n/en.json b/i18n/en.json new file mode 100644 index 0000000..7108aed --- /dev/null +++ b/i18n/en.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "pastakhov" + ] + }, + "phptagswidgets-desc": "Contains a collection of widgets for PhpTags extension" +} diff --git a/i18n/qqq.json b/i18n/qqq.json new file mode 100644 index 0000000..06ba444 --- /dev/null +++ b/i18n/qqq.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "pastakhov" + ] + }, + "phptagswidgets-desc": "{{desc|name=PhpTags_Widgets|url=http://www.mediawiki.org/wiki/Extension:PhpTags_Widgets}}" +} diff --git a/includes/GenericWidget.php b/includes/GenericWidget.php new file mode 100644 index 0000000..e0e0cc4 --- /dev/null +++ b/includes/GenericWidget.php @@ -0,0 +1,144 @@ +<?php +namespace PhpTags; + +/** + * Description of GenericWidget + * + * @author pastakhov + */ +class GenericWidget extends GenericObject { + + protected static $classPrefix; + protected static $classN = 1; + protected static $addedModules = array(); + protected $classID; + const PROP = 0; + const DATA = 1; + const GENERAL_ATTRIBS = 2; + const PRIVATE_PROP = 3; + + function __construct( $name, $value = null ) { + if ( self::$classPrefix === null ) { + self::$classPrefix = 'pw-' . base_convert( mt_rand(), 10, 36 ) . '-'; + \PhpTags::$globalVariablesScript['Widgets']['prefix'] = self::$classPrefix; + } + $this->classID = self::$classN++; + + if ( $value === null ) { + $value = array( array(), array(), array(), array() ); + } + parent::__construct( $name, $value ); + } + + function m___construct( $properties = null ) { + if ( $properties === null ) { + return true; + } elseif ( is_array( $properties ) ) { + foreach ( $properties as $prop => $val ) { + $handler = "b_$prop"; + $this->$handler( $val ); + } + } + return true; + } + + function getString() {} + + public function getClassName() { + return self::$classPrefix . $this->classID; + } + + public function toString() { + $element = 'div'; + $attribs = $this->value[self::GENERAL_ATTRIBS]; + $class = $this->getClassName(); + $attribs['class'] = isset( $attribs['class'] ) ? "$class {$attribs['class']}" : $class; + return \Html::rawElement( $element, $attribs, $this->getString() ); + } + + public function __toString() { + return $this->toString(); + } + + /** + * + * @param array $values + */ + protected function addToData( $values ) { + \PhpTags::$globalVariablesScript['Widgets']['data'][(string)$this->classID] = $values; + } + + /** + * + * @param mixed $command + */ + protected function addToOnReady( $command ) { + $this->addModule( 'ext.PhpTagsWidgets.onReady', false ); + \PhpTags::$globalVariablesScript['Widgets']['onReady'][ (string)$this->classID ] = $command; + } + + public function m_disable() { + unset( \PhpTags::$globalVariablesScript['Widgets']['onReady'][ (string)$this->classID ] ); + } + + protected function addModule( $module, $wait = true ) { + static $output = false; + if ( isset( self::$addedModules[$module] ) ) { // Module is already added + return; + } + if ( $output === false ) { + $output = \PhpTags\Runtime::getParser()->getOutput(); + } + $output->addModules( $module ); + self::$addedModules[$module] = true; + if ( $wait ) { + \PhpTags::$globalVariablesScript['Widgets']['wait'][] = $module; + } + } + + private function checkGenericProperty( $property, &$value ) { + $arguments = array( &$value ); + $expects = false; + + switch ( strtolower( $property ) ) { + case 'class': + case 'dir': + case 'style': + $expects = \PhpTags\Hooks::TYPE_STRING; + break; + } + + $check = parent::checkArguments( $this->name, $property, $arguments, array($expects) ); + if ( $check === true ) { + return true; + } + if ( $check instanceof \PhpTags\PhpTagsException && $check->getCode() === \PhpTags\PhpTagsException::WARNING_EXPECTS_PARAMETER ) { + \PhpTags\Runtime::$transit[PHPTAGS_TRANSIT_EXCEPTION][] = new \PhpTags\PhpTagsException( \PhpTags\PhpTagsException::NOTICE_EXPECTS_PROPERTY, $check->params ); + } + return false; + } + + public function __call( $name, $arguments ) { + list ( $callType, $tmp ) = explode( '_', $name, 2 ); + $subname = strtolower( $tmp ); + $property = $subname; + + switch ( $subname ) { + case 'class': + case 'dir': + case 'style': + if ( $callType === 'p' ) { // get property + return isset( $this->value[self::GENERAL_ATTRIBS][$property] ) ? $this->value[self::GENERAL_ATTRIBS][$property] : null; + } elseif ( $callType === 'b' ) { // set property + if ( $arguments[0] === null ) { + unset( $this->value[self::GENERAL_ATTRIBS][$property] ); + } elseif ( $this->checkGenericProperty( $subname, $arguments[0] ) ) { + $this->value[self::GENERAL_ATTRIBS][$property] = $arguments[0]; + } + return $this; + } + break; + } + return parent::__call( $name, $arguments ); + } +} diff --git a/includes/WidgetSlick.php b/includes/WidgetSlick.php new file mode 100644 index 0000000..92093a7 --- /dev/null +++ b/includes/WidgetSlick.php @@ -0,0 +1,251 @@ +<?php +namespace PhpTagsObjects; + +/** + * Description of WidgetsSlick + * @see http://kenwheeler.github.io/slick/ + * + * @author pastakhov + */ +class WidgetSlick extends \PhpTags\GenericWidget { + + protected static $modules = false; + protected static $trueCase = array( + 'adaptiveheight' => 'adaptiveHeight', + 'autoplayspeed' => 'autoplaySpeed', + 'centermode' => 'centerMode', + 'centerpadding' => 'centerPadding', + 'cssease' => 'cssEase', + 'initialslide' => 'initialSlide', + 'focusonselect' => 'focusOnSelect', + 'pauseonhover' => 'pauseOnHover', + 'pauseondotshover' => 'pauseOnDotsHover', + 'slidestoshow' => 'slidesToShow', + 'slidestoscroll' => 'slidesToScroll', + 'swipetoslide' => 'swipeToSlide', + 'touchmove' => 'touchMove', + 'touchthreshold' => 'touchThreshold', + 'usecss' => 'useCSS', + 'variablewidth' => 'variableWidth', + ); + + public function m___construct( $properties = null, $value = null ) { + $this->value[self::DATA] = $value; + return parent::m___construct( $properties ); + } + + public function m_enable() { + $this->addToOnReady( 'slick' ); + } + + public function toString() { + $this->m_enable(); + return parent::toString(); + } + + public function getString() { + $this->addModule( 'ext.PhpTagsWidgets.slick' ); + $this->addToData( array( $this->value[self::PROP] ) ); + $data = $this->value[self::DATA]; + if ( is_array( $data ) ) { + $data = '<div>' . implode( '</div><div>', $this->value[self::DATA] ) . '</div>'; + } + return $data; + } + + private function checkProperty( $property, &$value ) { + $arguments = array( &$value ); + $expects = false; + + switch ( $property ) { + case 'accessibility': + case 'adaptiveHeight': + case 'autoplay': + case 'arrows': + case 'centerMode': + case 'dots': + case 'draggable': +// case 'fade': do not allow it! + case 'focusOnSelect': + case 'infinite': + case 'pauseOnHover': + case 'pauseOnDotsHover': + case 'swipe': + case 'swipeToSlide': + case 'touchMove': + case 'variableWidth': + case 'vertical': + case 'rtl': + case 'useCSS': + $expects = \PhpTags\Hooks::TYPE_BOOL; + break; + case 'autoplaySpeed': + case 'initialSlide': + case 'slidesToShow': + case 'slidesToScroll': + case 'speed': + case 'touchThreshold': + $expects = \PhpTags\Hooks::TYPE_INT; + break; + case 'centerPadding': +// @todo case 'appendArrows': +// @todo case 'prevArrow': +// @todo case 'nextArrow': + case 'cssEase': +// @???todo case 'customPaging': ??? +// @todo case 'easing': +// case 'lazyLoad': + case 'slide': + $expects = \PhpTags\Hooks::TYPE_STRING; + break; + case 'asnavfor': + $expects = 'Slick'; + break; +// @todo case 'responsive': +// $expects = \PhpTags\Hooks::TYPE_ARRAY; +// break; + default: + return true; + } + + $check = parent::checkArguments( $this->name, $property, $arguments, array($expects) ); + if ( $check === true ) { + return true; + } + if ( $check instanceof \PhpTags\PhpTagsException && $check->getCode() === \PhpTags\PhpTagsException::WARNING_EXPECTS_PARAMETER ) { + \PhpTags\Runtime::$transit[PHPTAGS_TRANSIT_EXCEPTION][] = new \PhpTags\PhpTagsException( \PhpTags\PhpTagsException::NOTICE_EXPECTS_PROPERTY, $check->params ); + } + return false; + } + + public function __call( $name, $arguments ) { + list ( $callType, $tmp ) = explode( '_', $name, 2 ); + $subname = strtolower( $tmp ); + $property = $subname; + + switch ( $subname ) { + case 'adaptiveheight': + case 'autoplayspeed': + case 'centermode': + case 'centerpadding': + case 'cssease': + case 'focusonselect': + case 'initialslide': + case 'pauseonhover': + case 'pauseondotshover': + case 'slidestoshow': + case 'slidestoscroll': + case 'swipetoslide': + case 'touchmove': + case 'touchthreshold': + case 'usecss': + case 'variablewidth': + $property = self::$trueCase[$subname]; + // break is not necessary here + case 'accessibility': + case 'autoplay': + case 'arrows': + case 'dots': + case 'draggable': +// case 'fade': do not allow it! +// case 'easing': + case 'infinite': + case 'swipe': + case 'vertical': + case 'rtl': + case 'slide': + case 'speed': + if ( $callType === 'p' ) { // get property + return isset( $this->value[self::PROP][$property] ) ? $this->value[self::PROP][$property] : null; + } elseif ( $callType === 'b' ) { // set property + if ( $arguments[0] === null ) { + unset( $this->value[self::PROP][$property] ); + } elseif ( $this->checkProperty( $property, $arguments[0] ) ) { + $this->value[self::PROP][$property] = $arguments[0]; + } + return $this; + } + break; + } + return parent::__call( $name, $arguments ); + } + + /** + * Set property centerPadding + * @param string $value + * @return \PhpTagsObjects\WidgetSlick + */ + public function b_centerPadding( $value ) { + $matches = array(); + if ( $value === null ) { + unset( $this->value[self::PROP]['centerPadding'] ); + } elseif( $this->checkProperty( 'centerPadding', $value ) ) { + if ( preg_match( '/\d+(?:px|%)/i', $value, $matches ) ) { + $this->value[self::PROP]['centerPadding'] = $matches[0]; + } else { + // @todo error message + } + } + return $this; + } + + /** + * Set property rtl + * @param bool $value + */ + public function b_rtl( $value ) { + if ( $value === null ) { + unset( $this->value[self::PROP]['rtl'] ); + $this->b_dir( null ); + } elseif( $this->checkProperty( 'rtl', $value ) ) { + $this->value[self::PROP]['rtl'] = $value; + if ( $value ) { + $this->b_dir( 'rtl' ); + } + } + return $this; + } + + /** + * + * @param \PhpTagsObjects\WidgetSlick $value + * @return \PhpTagsObjects\WidgetSlick + */ + public function b_asNavFor( $value ) { + if( $value !== null && !$this->checkProperty( 'asNavFor', $value ) ) { + $value = null; + } + $oldValue = isset($this->value[self::PRIVATE_PROP]['asNavFor']) ? $this->value[self::PRIVATE_PROP]['asNavFor'] : null; + if ( $oldValue === $value ) { + return; + } + + $this->setAsNavFor( $value ); + + if ( $oldValue instanceof WidgetSlick ) { + $oldValue->setAsNavFor( null ); + if ( $value !== null ) { + $oldValue->setAsNavFor( $this ); + } + } + if ( $value instanceof WidgetSlick ) { + $value->setAsNavFor( $this ); + } + return $this; + } + + public function p_asNavFor() { + return isset($this->value[self::PRIVATE_PROP]['asNavFor']) ? $this->value[self::PRIVATE_PROP]['asNavFor'] : null; + } + + public function setAsNavFor ( $value ) { + if ( $value === null ) { + unset( $this->value[self::PRIVATE_PROP]['asNavFor'] ); + unset( $this->value[self::PROP]['asNavFor'] ); + } else { + $this->value[self::PRIVATE_PROP]['asNavFor'] = $value; + $this->value[self::PROP]['asNavFor'] = '.' . $value->getClassName(); + } + } + +} diff --git a/resources/ext.pw.onReady.js b/resources/ext.pw.onReady.js new file mode 100644 index 0000000..483334b --- /dev/null +++ b/resources/ext.pw.onReady.js @@ -0,0 +1,18 @@ +/* global window, mw, $ */ +if(window.mw){ + var $phptagsWidgets = mw.config.get( 'ext.phptags.Widgets' ); + $.when( + $.ready, + mw.loader.using( $phptagsWidgets.wait ) + ).done( + function () { + var $prefix = $phptagsWidgets.prefix; + if ( !$phptagsWidgets.onReady ) { + return; + } + for ( var $key in $phptagsWidgets.onReady ) { + $.fn[ $phptagsWidgets.onReady[$key] ].apply( $( '.' + $prefix + $key ) , $phptagsWidgets.data[$key] ); + } + } + ); +} diff --git a/resources/libs/slick/LICENSE b/resources/libs/slick/LICENSE new file mode 100644 index 0000000..e0bb8c7 --- /dev/null +++ b/resources/libs/slick/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/resources/libs/slick/README.markdown b/resources/libs/slick/README.markdown new file mode 100644 index 0000000..e5b5ba0 --- /dev/null +++ b/resources/libs/slick/README.markdown @@ -0,0 +1,148 @@ +slick +------- + +[1]: <https://github.com/kenwheeler/slick> + +_the last carousel you'll ever need_ + +#### Demo + +[http://kenwheeler.github.io/slick](http://kenwheeler.github.io/slick/) + +#### CDN + +CDN hosted slick is a great way to get set up quick: + +In your ```<head>``` add: + +```` +<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.3.13/slick.css"/> +```` + +Then, before your closing ```<body>``` tag add: + +``` +<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.3.13/slick.min.js"></script> +``` + +#### Bower + +```` +bower install --save slick.js +```` + +#### Contributing + +PLEASE review CONTRIBUTING.markdown prior to requesting a feature, filing a pull request or filing an issue. + +#### Options + +Option | Type | Default | Description +------ | ---- | ------- | ----------- +accessibility | boolean | true | Enables tabbing and arrow key navigation +autoplay | boolean | false | Enables auto play of slides +autoplaySpeed | int | 3000 | Auto play change interval +centerMode | boolean | false | Enables centered view with partial prev/next slides. Use with odd numbered slidesToShow counts. +centerPadding | string | '50px' | Side padding when in center mode. (px or %) +cssEase | string | 'ease' | CSS3 easing +customPaging | function | n/a | Custom paging templates. See source for use example. +dots | boolean | false | Current slide indicator dots +dotsClass | string | 'slick-dots' | Class for slide indicator dots container +draggable | boolean | true | Enables desktop dragging +easing | string | 'linear' | animate() fallback easing +fade | boolean | false | Enables fade +arrows | boolean | true | Enable Next/Prev arrows +appendArrows | string | $(element) | Change where the navigation arrows are attached (Selector, htmlString, Array, Element, jQuery object) +appendDots | string | $(element) | Change where the navigation dots are attached (Selector, htmlString, Array, Element, jQuery object) +prevArrow | string (html|jQuery selector) | object (DOM node|jQuery object) | <button type="button" class="slick-prev">Previous</button> | Allows you to select a node or customize the HTML for the "Previous" arrow. +nextArrow | string (html|jQuery selector) | object (DOM node|jQuery object) | <button type="button" class="slick-next">Next</button> | Allows you to select a node or customize the HTML for the "Next" arrow. +infinite | boolean | true | Infinite looping +initialSlide | integer | 0 | Slide to start on +lazyLoad | string | 'ondemand' | Accepts 'ondemand' or 'progressive' for lazy load technique +onBeforeChange(this, currentIndex,targetIndex) | method | null | Before slide change callback +onAfterChange(this, index) | method | null | After slide change callback +onInit(this) | method | null | When Slick initializes for the first time callback +onReInit(this) | method | null | Every time Slick (re-)initializes callback +pauseOnHover | boolean | true | Pauses autoplay on hover +pauseOnDotsHover | boolean | false | Pauses autoplay when a dot is hovered +responsive | object | null | Breakpoint triggered settings +slide | string | 'div' | Slide element query +slidesToShow | int | 1 | # of slides to show at a time +slidesToScroll | int | 1 | # of slides to scroll at a time +speed | int | 300 | Transition speed +swipe | boolean | true | Enables touch swipe +swipeToSlide | boolean | false | Swipe to slide irrespective of slidesToScroll +touchMove | boolean | true | Enables slide moving with touch +touchThreshold | int | 5 | To advance slides, the user must swipe a length of (1/touchThreshold) * the width of the slider. +useCSS | boolean | true | Enable/Disable CSS Transitions +variableWidth | boolean | false | Disables automatic slide width calculation +vertical | boolean | false | Vertical slide direction +rtl | boolean | false | Change the slider's direction to become right-to-left +waitForAnimate | boolean | true | Ignores requests to advance the slide while animating + + +#### Methods + +Method | Argument | Description +------ | -------- | ----------- +slick() | options : object | Initializes Slick +unslick() | | Destroys Slick +slickNext() | | Triggers next slide +slickPrev() | | Triggers previous slide +slickPause() | | Pause Autoplay +slickPlay() | | Start Autoplay +slickGoTo() | index : int | Goes to slide by index +slickCurrentSlide() | | Returns the current slide index +slickAdd() | element : html or DOM object, index: int, addBefore: bool | Add a slide. If an index is provided, will add at that index, or before if addBefore is set. If no index is provided, add to the end or to the beginning if addBefore is set. Accepts HTML String || Object +slickRemove() | index: int, removeBefore: bool | Remove slide by index. If removeBefore is set true, remove slide preceding index, or the first slide if no index is specified. If removeBefore is set to false, remove the slide following index, or the last slide if no index is set. +slickFilter() | filter : selector or function | Filters slides using jQuery .filter syntax +slickUnfilter() | | Removes applied filter +slickGetOption(option) | option : string(option name) | Gets an option value. +slickSetOption(option,value,refresh) | option : string(option name), value : depends on option, refresh : boolean | Sets an option live. Set refresh to true if it is an option that changes the display + + +#### Example + +Initialize with: + +```javascript +$(element).slick({ + dots: true, + speed: 500 +}); + ``` + +Destroy with: + +```javascript +$(element).unslick(); +``` + + +#### Sass Variables + +Variable | Type | Default | Description +------ | ---- | ------- | ----------- +$slick-font-path | string | "./fonts/" | Directory path for the slick icon font +$slick-font-family | string | "slick" | Font-family for slick icon font +$slick-loader-path | string | "./" | Directory path for the loader image +$slick-arrow-color | color | white | Color of the left/right arrow icons +$slick-dot-color | color | black | Color of the navigation dots +$slick-dot-color-active | color | $slick-dot-color | Color of the active navigation dot +$slick-prev-character | string | '\2190' | Unicode character code for the previous arrow icon +$slick-next-character | string | '\2192' | Unicode character code for the next arrow icon +$slick-dot-character | string | '\2022' | Unicode character code for the navigation dot icon +$slick-dot-size | pixels | 6px | Size of the navigation dots + + +#### Dependencies + +jQuery 1.7 + +#### License + +Copyright (c) 2014 Ken Wheeler + +Licensed under the MIT license. + +Free as in Bacon. diff --git a/resources/libs/slick/ajax-loader.gif b/resources/libs/slick/ajax-loader.gif new file mode 100644 index 0000000..e0e6e97 --- /dev/null +++ b/resources/libs/slick/ajax-loader.gif Binary files differ diff --git a/resources/libs/slick/fonts/slick.eot b/resources/libs/slick/fonts/slick.eot new file mode 100644 index 0000000..2cbab9c --- /dev/null +++ b/resources/libs/slick/fonts/slick.eot Binary files differ diff --git a/resources/libs/slick/fonts/slick.svg b/resources/libs/slick/fonts/slick.svg new file mode 100644 index 0000000..b36a66a --- /dev/null +++ b/resources/libs/slick/fonts/slick.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata>Generated by Fontastic.me</metadata> +<defs> +<font id="slick" horiz-adv-x="512"> +<font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/> +<missing-glyph horiz-adv-x="512" /> + +<glyph unicode="→" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="←" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="•" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="a" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/> +</font></defs></svg> diff --git a/resources/libs/slick/fonts/slick.ttf b/resources/libs/slick/fonts/slick.ttf new file mode 100644 index 0000000..9d03461 --- /dev/null +++ b/resources/libs/slick/fonts/slick.ttf Binary files differ diff --git a/resources/libs/slick/fonts/slick.woff b/resources/libs/slick/fonts/slick.woff new file mode 100644 index 0000000..8ee9972 --- /dev/null +++ b/resources/libs/slick/fonts/slick.woff Binary files differ diff --git a/resources/libs/slick/slick.css b/resources/libs/slick/slick.css new file mode 100644 index 0000000..2570f48 --- /dev/null +++ b/resources/libs/slick/slick.css @@ -0,0 +1,57 @@ +@charset "UTF-8"; +/* Slider */ +.slick-slider { position: relative; display: block; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -ms-touch-action: pan-y; touch-action: pan-y; -webkit-tap-highlight-color: transparent; } + +.slick-list { position: relative; overflow: hidden; display: block; margin: 0; padding: 0; } +.slick-list:focus { outline: none; } +.slick-loading .slick-list { background: #fff url("./ajax-loader.gif") center center no-repeat; } +.slick-list.dragging { cursor: pointer; cursor: hand; } + +.slick-slider .slick-track { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + +.slick-track { position: relative; left: 0; top: 0; display: block; } +.slick-track:before, .slick-track:after { content: ""; display: table; } +.slick-track:after { clear: both; } +.slick-loading .slick-track { visibility: hidden; } + +.slick-slide { float: left; height: 100%; min-height: 1px; display: none; } +[dir="rtl"] .slick-slide { float: right; } +.slick-slide img { display: block; } +.slick-slide.slick-loading img { display: none; } +.slick-slide.dragging img { pointer-events: none; } +.slick-initialized .slick-slide { display: block; } +.slick-loading .slick-slide { visibility: hidden; } +.slick-vertical .slick-slide { display: block; height: auto; border: 1px solid transparent; } + +/* Icons */ +@font-face { font-family: "slick"; src: url("./fonts/slick.eot"); src: url("./fonts/slick.eot?#iefix") format("embedded-opentype"), url("./fonts/slick.woff") format("woff"), url("./fonts/slick.ttf") format("truetype"), url("./fonts/slick.svg#slick") format("svg"); font-weight: normal; font-style: normal; } +/* Arrows */ +.slick-prev, .slick-next { position: absolute; display: block; height: 20px; width: 20px; line-height: 0; font-size: 0; cursor: pointer; background: transparent; color: transparent; top: 50%; margin-top: -10px; padding: 0; border: none; outline: none; } +.slick-prev:hover, .slick-prev:focus, .slick-next:hover, .slick-next:focus { outline: none; background: transparent; color: transparent; } +.slick-prev:hover:before, .slick-prev:focus:before, .slick-next:hover:before, .slick-next:focus:before { opacity: 1; } +.slick-prev.slick-disabled:before, .slick-next.slick-disabled:before { opacity: 0.25; } + +.slick-prev:before, .slick-next:before { font-family: "slick"; font-size: 20px; line-height: 1; color: white; opacity: 0.75; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } + +.slick-prev { left: -25px; } +[dir="rtl"] .slick-prev { left: auto; right: -25px; } +.slick-prev:before { content: "←"; } +[dir="rtl"] .slick-prev:before { content: "→"; } + +.slick-next { right: -25px; } +[dir="rtl"] .slick-next { left: -25px; right: auto; } +.slick-next:before { content: "→"; } +[dir="rtl"] .slick-next:before { content: "←"; } + +/* Dots */ +.slick-slider { margin-bottom: 30px; } + +.slick-dots { position: absolute; bottom: -45px; list-style: none; display: block; text-align: center; padding: 0; width: 100%; } +.slick-dots li { position: relative; display: inline-block; height: 20px; width: 20px; margin: 0 5px; padding: 0; cursor: pointer; } +.slick-dots li button { border: 0; background: transparent; display: block; height: 20px; width: 20px; outline: none; line-height: 0; font-size: 0; color: transparent; padding: 5px; cursor: pointer; } +.slick-dots li button:hover, .slick-dots li button:focus { outline: none; } +.slick-dots li button:hover:before, .slick-dots li button:focus:before { opacity: 1; } +.slick-dots li button:before { position: absolute; top: 0; left: 0; content: "•"; width: 20px; height: 20px; font-family: "slick"; font-size: 6px; line-height: 20px; text-align: center; color: black; opacity: 0.25; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } +.slick-dots li.slick-active button:before { color: black; opacity: 0.75; } + +/*# sourceMappingURL=slick.css.map */ diff --git a/resources/libs/slick/slick.js b/resources/libs/slick/slick.js new file mode 100644 index 0000000..f0e1760 --- /dev/null +++ b/resources/libs/slick/slick.js @@ -0,0 +1,2011 @@ +/* + _ _ _ _ + ___| (_) ___| | __ (_)___ +/ __| | |/ __| |/ / | / __| +\__ \ | | (__| < _ | \__ \ +|___/_|_|\___|_|\_(_)/ |___/ + |__/ + + Version: 1.3.13 + Author: Ken Wheeler + Website: http://kenwheeler.github.io + Docs: http://kenwheeler.github.io/slick + Repo: http://github.com/kenwheeler/slick + Issues: http://github.com/kenwheeler/slick/issues + + */ + +/* global window, document, define, jQuery, setInterval, clearInterval */ + +(function(factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else if (typeof exports !== 'undefined') { + module.exports = factory(require('jquery')); + } else { + factory(jQuery); + } + +}(function($) { + 'use strict'; + var Slick = window.Slick || {}; + + Slick = (function() { + + var instanceUid = 0; + + function Slick(element, settings) { + + var _ = this, + responsiveSettings, breakpoint; + + _.defaults = { + accessibility: true, + adaptiveHeight: false, + appendArrows: $(element), + appendDots: $(element), + arrows: true, + asNavFor: null, + prevArrow: '<button type="button" data-role="none" class="slick-prev">Previous</button>', + nextArrow: '<button type="button" data-role="none" class="slick-next">Next</button>', + autoplay: false, + autoplaySpeed: 3000, + centerMode: false, + centerPadding: '50px', + cssEase: 'ease', + customPaging: function(slider, i) { + return '<button type="button" data-role="none">' + (i + 1) + '</button>'; + }, + dots: false, + dotsClass: 'slick-dots', + draggable: true, + easing: 'linear', + fade: false, + focusOnSelect: false, + infinite: true, + initialSlide: 0, + lazyLoad: 'ondemand', + onBeforeChange: null, + onAfterChange: null, + onInit: null, + onReInit: null, + pauseOnHover: true, + pauseOnDotsHover: false, + responsive: null, + rtl: false, + slide: 'div', + slidesToShow: 1, + slidesToScroll: 1, + speed: 300, + swipe: true, + swipeToSlide: false, + touchMove: true, + touchThreshold: 5, + useCSS: true, + variableWidth: false, + vertical: false, + waitForAnimate: true + }; + + _.initials = { + animating: false, + dragging: false, + autoPlayTimer: null, + currentDirection: 0, + currentLeft: null, + currentSlide: 0, + direction: 1, + $dots: null, + listWidth: null, + listHeight: null, + loadIndex: 0, + $nextArrow: null, + $prevArrow: null, + slideCount: null, + slideWidth: null, + $slideTrack: null, + $slides: null, + sliding: false, + slideOffset: 0, + swipeLeft: null, + $list: null, + touchObject: {}, + transformsEnabled: false + }; + + $.extend(_, _.initials); + + _.activeBreakpoint = null; + _.animType = null; + _.animProp = null; + _.breakpoints = []; + _.breakpointSettings = []; + _.cssTransitions = false; + _.paused = false; + _.positionProp = null; + _.shouldClick = true; + _.$slider = $(element); + _.$slidesCache = null; + _.transformType = null; + _.transitionType = null; + _.windowWidth = 0; + _.windowTimer = null; + + _.options = $.extend({}, _.defaults, settings); + + _.currentSlide = _.options.initialSlide; + + _.originalSettings = _.options; + responsiveSettings = _.options.responsive || null; + + if (responsiveSettings && responsiveSettings.length > -1) { + for (breakpoint in responsiveSettings) { + if (responsiveSettings.hasOwnProperty(breakpoint)) { + _.breakpoints.push(responsiveSettings[ + breakpoint].breakpoint); + _.breakpointSettings[responsiveSettings[ + breakpoint].breakpoint] = + responsiveSettings[breakpoint].settings; + } + } + _.breakpoints.sort(function(a, b) { + return b - a; + }); + } + + _.autoPlay = $.proxy(_.autoPlay, _); + _.autoPlayClear = $.proxy(_.autoPlayClear, _); + _.changeSlide = $.proxy(_.changeSlide, _); + _.selectHandler = $.proxy(_.selectHandler, _); + _.setPosition = $.proxy(_.setPosition, _); + _.swipeHandler = $.proxy(_.swipeHandler, _); + _.dragHandler = $.proxy(_.dragHandler, _); + _.keyHandler = $.proxy(_.keyHandler, _); + _.autoPlayIterator = $.proxy(_.autoPlayIterator, _); + + _.instanceUid = instanceUid++; + + // A simple way to check for HTML strings + // Strict HTML recognition (must start with <) + // Extracted from jQuery v1.11 source + _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/; + + _.init(); + + } + + return Slick; + + }()); + + Slick.prototype.addSlide = function(markup, index, addBefore) { + + var _ = this; + + if (typeof(index) === 'boolean') { + addBefore = index; + index = null; + } else if (index < 0 || (index >= _.slideCount)) { + return false; + } + + _.unload(); + + if (typeof(index) === 'number') { + if (index === 0 && _.$slides.length === 0) { + $(markup).appendTo(_.$slideTrack); + } else if (addBefore) { + $(markup).insertBefore(_.$slides.eq(index)); + } else { + $(markup).insertAfter(_.$slides.eq(index)); + } + } else { + if (addBefore === true) { + $(markup).prependTo(_.$slideTrack); + } else { + $(markup).appendTo(_.$slideTrack); + } + } + + _.$slides = _.$slideTrack.children(this.options.slide); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slideTrack.append(_.$slides); + + _.$slides.each(function(index, element) { + $(element).attr("index",index); + }); + + _.$slidesCache = _.$slides; + + _.reinit(); + + }; + + Slick.prototype.animateSlide = function(targetLeft, callback) { + + var animProps = {}, _ = this; + + if(_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { + var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); + _.$list.animate({height: targetHeight},_.options.speed); + } + + if (_.options.rtl === true && _.options.vertical === false) { + targetLeft = -targetLeft; + } + if (_.transformsEnabled === false) { + if (_.options.vertical === false) { + _.$slideTrack.animate({ + left: targetLeft + }, _.options.speed, _.options.easing, callback); + } else { + _.$slideTrack.animate({ + top: targetLeft + }, _.options.speed, _.options.easing, callback); + } + + } else { + + if (_.cssTransitions === false) { + + $({ + animStart: _.currentLeft + }).animate({ + animStart: targetLeft + }, { + duration: _.options.speed, + easing: _.options.easing, + step: function(now) { + if (_.options.vertical === false) { + animProps[_.animType] = 'translate(' + + now + 'px, 0px)'; + _.$slideTrack.css(animProps); + } else { + animProps[_.animType] = 'translate(0px,' + + now + 'px)'; + _.$slideTrack.css(animProps); + } + }, + complete: function() { + if (callback) { + callback.call(); + } + } + }); + + } else { + + _.applyTransition(); + + if (_.options.vertical === false) { + animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)'; + } else { + animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)'; + } + _.$slideTrack.css(animProps); + + if (callback) { + setTimeout(function() { + + _.disableTransition(); + + callback.call(); + }, _.options.speed); + } + + } + + } + + }; + + Slick.prototype.asNavFor = function(index) { + var _ = this, asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null; + if(asNavFor != null) asNavFor.slideHandler(index, true); + }; + + Slick.prototype.applyTransition = function(slide) { + + var _ = this, + transition = {}; + + if (_.options.fade === false) { + transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase; + } else { + transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase; + } + + if (_.options.fade === false) { + _.$slideTrack.css(transition); + } else { + _.$slides.eq(slide).css(transition); + } + + }; + + Slick.prototype.autoPlay = function() { + + var _ = this; + + if (_.autoPlayTimer) { + clearInterval(_.autoPlayTimer); + } + + if (_.slideCount > _.options.slidesToShow && _.paused !== true) { + _.autoPlayTimer = setInterval(_.autoPlayIterator, + _.options.autoplaySpeed); + } + + }; + + Slick.prototype.autoPlayClear = function() { + + var _ = this; + if (_.autoPlayTimer) { + clearInterval(_.autoPlayTimer); + } + + }; + + Slick.prototype.autoPlayIterator = function() { + + var _ = this; + + if (_.options.infinite === false) { + + if (_.direction === 1) { + + if ((_.currentSlide + 1) === _.slideCount - + 1) { + _.direction = 0; + } + + _.slideHandler(_.currentSlide + _.options.slidesToScroll); + + } else { + + if ((_.currentSlide - 1 === 0)) { + + _.direction = 1; + + } + + _.slideHandler(_.currentSlide - _.options.slidesToScroll); + + } + + } else { + + _.slideHandler(_.currentSlide + _.options.slidesToScroll); + + } + + }; + + Slick.prototype.buildArrows = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow = $(_.options.prevArrow); + _.$nextArrow = $(_.options.nextArrow); + + if (_.htmlExpr.test(_.options.prevArrow)) { + _.$prevArrow.appendTo(_.options.appendArrows); + } + + if (_.htmlExpr.test(_.options.nextArrow)) { + _.$nextArrow.appendTo(_.options.appendArrows); + } + + if (_.options.infinite !== true) { + _.$prevArrow.addClass('slick-disabled'); + } + + } + + }; + + Slick.prototype.buildDots = function() { + + var _ = this, + i, dotString; + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + dotString = '<ul class="' + _.options.dotsClass + '">'; + + for (i = 0; i <= _.getDotCount(); i += 1) { + dotString += '<li>' + _.options.customPaging.call(this, _, i) + '</li>'; + } + + dotString += '</ul>'; + + _.$dots = $(dotString).appendTo( + _.options.appendDots); + + _.$dots.find('li').first().addClass( + 'slick-active'); + + } + + }; + + Slick.prototype.buildOut = function() { + + var _ = this; + + _.$slides = _.$slider.children(_.options.slide + + ':not(.slick-cloned)').addClass( + 'slick-slide'); + _.slideCount = _.$slides.length; + + _.$slides.each(function(index, element) { + $(element).attr("index",index); + }); + + _.$slidesCache = _.$slides; + + _.$slider.addClass('slick-slider'); + + _.$slideTrack = (_.slideCount === 0) ? + $('<div class="slick-track"/>').appendTo(_.$slider) : + _.$slides.wrapAll('<div class="slick-track"/>').parent(); + + _.$list = _.$slideTrack.wrap( + '<div class="slick-list"/>').parent(); + _.$slideTrack.css('opacity', 0); + + if (_.options.centerMode === true) { + _.options.slidesToScroll = 1; + _.options.slidesToShow = 3; + } + + $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading'); + + _.setupInfinite(); + + _.buildArrows(); + + _.buildDots(); + + _.updateDots(); + + if (_.options.accessibility === true) { + _.$list.prop('tabIndex', 0); + } + + _.setSlideClasses(typeof this.currentSlide === 'number' ? this.currentSlide : 0); + + if (_.options.draggable === true) { + _.$list.addClass('draggable'); + } + + }; + + Slick.prototype.checkResponsive = function() { + + var _ = this, + breakpoint, targetBreakpoint; + + if (_.originalSettings.responsive && _.originalSettings + .responsive.length > -1 && _.originalSettings.responsive !== null) { + + targetBreakpoint = null; + + for (breakpoint in _.breakpoints) { + if (_.breakpoints.hasOwnProperty(breakpoint)) { + if ($(window).width() < _.breakpoints[ + breakpoint]) { + targetBreakpoint = _.breakpoints[ + breakpoint]; + } + } + } + + if (targetBreakpoint !== null) { + if (_.activeBreakpoint !== null) { + if (targetBreakpoint !== _.activeBreakpoint) { + _.activeBreakpoint = + targetBreakpoint; + _.options = $.extend({}, _.originalSettings, + _.breakpointSettings[ + targetBreakpoint]); + _.refresh(); + } + } else { + _.activeBreakpoint = targetBreakpoint; + _.options = $.extend({}, _.originalSettings, + _.breakpointSettings[ + targetBreakpoint]); + _.refresh(); + } + } else { + if (_.activeBreakpoint !== null) { + _.activeBreakpoint = null; + _.options = _.originalSettings; + _.refresh(); + } + } + + } + + }; + + Slick.prototype.changeSlide = function(event) { + + var _ = this, + $target = $(event.target), + indexOffset, slideOffset, unevenOffset; + + // If target is a link, prevent default action. + $target.is('a') && event.preventDefault(); + + unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0); + indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll; + + switch (event.data.message) { + + case 'previous': + slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset; + if (_.slideCount > _.options.slidesToShow) { + _.slideHandler(_.currentSlide - slideOffset); + } + break; + + case 'next': + slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset; + if (_.slideCount > _.options.slidesToShow) { + _.slideHandler(_.currentSlide + slideOffset); + } + break; + + case 'index': + var index = event.data.index === 0 ? 0 : + event.data.index || $(event.target).parent().index() * _.options.slidesToScroll; + _.slideHandler(index); + + default: + return false; + } + + }; + + Slick.prototype.clickHandler = function(event) { + + var _ = this; + + if(_.shouldClick === false) { + event.stopImmediatePropagation(); + event.stopPropagation(); + event.preventDefault(); + } + + } + + Slick.prototype.destroy = function() { + + var _ = this; + + _.autoPlayClear(); + + _.touchObject = {}; + + $('.slick-cloned', _.$slider).remove(); + if (_.$dots) { + _.$dots.remove(); + } + if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) { + _.$prevArrow.remove(); + } + if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) { + _.$nextArrow.remove(); + } + if (_.$slides.parent().hasClass('slick-track')) { + _.$slides.unwrap().unwrap(); + } + + _.$slides.removeClass( + 'slick-slide slick-active slick-center slick-visible') + .removeAttr('index') + .css({ + position: '', + left: '', + top: '', + zIndex: '', + opacity: '', + width: '' + }); + + _.$slider.removeClass('slick-slider'); + _.$slider.removeClass('slick-initialized'); + + _.$list.off('.slick'); + $(window).off('.slick-' + _.instanceUid); + $(document).off('.slick-' + _.instanceUid); + + }; + + Slick.prototype.disableTransition = function(slide) { + + var _ = this, + transition = {}; + + transition[_.transitionType] = ""; + + if (_.options.fade === false) { + _.$slideTrack.css(transition); + } else { + _.$slides.eq(slide).css(transition); + } + + }; + + Slick.prototype.fadeSlide = function(oldSlide, slideIndex, callback) { + + var _ = this; + + if (_.cssTransitions === false) { + + _.$slides.eq(slideIndex).css({ + zIndex: 1000 + }); + + _.$slides.eq(slideIndex).animate({ + opacity: 1 + }, _.options.speed, _.options.easing, callback); + + _.$slides.eq(oldSlide).animate({ + opacity: 0 + }, _.options.speed, _.options.easing); + + } else { + + _.applyTransition(slideIndex); + _.applyTransition(oldSlide); + + _.$slides.eq(slideIndex).css({ + opacity: 1, + zIndex: 1000 + }); + + _.$slides.eq(oldSlide).css({ + opacity: 0 + }); + + if (callback) { + setTimeout(function() { + + _.disableTransition(slideIndex); + _.disableTransition(oldSlide); + + callback.call(); + }, _.options.speed); + } + + } + + }; + + Slick.prototype.filterSlides = function(filter) { + + var _ = this; + + if (filter !== null) { + + _.unload(); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slidesCache.filter(filter).appendTo(_.$slideTrack); + + _.reinit(); + + } + + }; + + Slick.prototype.getCurrent = function() { + + var _ = this; + + return _.currentSlide; + + }; + + Slick.prototype.getDotCount = function() { + + var _ = this; + + return Math.ceil(_.slideCount / _.options.slidesToScroll) - 1; + + }; + + Slick.prototype.getLeft = function(slideIndex) { + + var _ = this, + targetLeft, + verticalHeight, + verticalOffset = 0, + slideWidth, + targetSlide; + + _.slideOffset = 0; + verticalHeight = _.$slides.first().outerHeight(); + + if (_.options.infinite === true) { + if (_.slideCount > _.options.slidesToShow) { + _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1; + verticalOffset = (verticalHeight * _.options.slidesToShow) * -1; + } + if (_.slideCount % _.options.slidesToScroll !== 0) { + if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { + _.slideOffset = ((_.slideCount % _.options.slidesToShow) * _.slideWidth) * -1; + verticalOffset = ((_.slideCount % _.options.slidesToShow) * verticalHeight) * -1; + } + } + } else { + if(slideIndex + _.options.slidesToShow > _.slideCount) { + _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth; + verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight; + } + } + + if (_.slideCount <= _.options.slidesToShow){ + _.slideOffset = 0; + verticalOffset = 0; + } + + if (_.options.centerMode === true && _.options.infinite === true) { + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth; + } else if (_.options.centerMode === true) { + _.slideOffset = 0; + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2); + } + + if (_.options.vertical === false) { + targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset; + } else { + targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset; + } + + if (_.options.variableWidth === true) { + + if(_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); + } else { + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow); + } + targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; + if (_.options.centerMode === true) { + if(_.options.infinite === false) { + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); + } else { + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1); + } + targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; + targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2; + } + } + + return targetLeft; + + }; + + Slick.prototype.getSlideCount = function() { + + var _ = this, slidesTraversed; + + if(_.options.swipeToSlide === true) { + var swipedSlide = null; + _.$slideTrack.find('.slick-slide').each(function(index, slide){ + if (slide.offsetLeft + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) { + swipedSlide = slide; + return false; + } + }); + slidesTraversed = Math.abs($(swipedSlide).attr('index') - _.currentSlide); + return slidesTraversed; + } else { + return _.options.slidesToScroll; + } + + }; + + Slick.prototype.init = function() { + + var _ = this; + + if (!$(_.$slider).hasClass('slick-initialized')) { + + $(_.$slider).addClass('slick-initialized'); + _.buildOut(); + _.setProps(); + _.startLoad(); + _.loadSlider(); + _.initializeEvents(); + _.checkResponsive(); + } + + if (_.options.onInit !== null) { + _.options.onInit.call(this, _); + } + + }; + + Slick.prototype.initArrowEvents = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + _.$prevArrow.on('click.slick', { + message: 'previous' + }, _.changeSlide); + _.$nextArrow.on('click.slick', { + message: 'next' + }, _.changeSlide); + } + + }; + + Slick.prototype.initDotEvents = function() { + + var _ = this; + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + $('li', _.$dots).on('click.slick', { + message: 'index' + }, _.changeSlide); + } + + if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) { + $('li', _.$dots) + .on('mouseenter.slick', function(){ + _.paused = true; + _.autoPlayClear(); + }) + .on('mouseleave.slick', function(){ + _.paused = false; + _.autoPlay(); + }); + } + + }; + + Slick.prototype.initializeEvents = function() { + + var _ = this; + + _.initArrowEvents(); + + _.initDotEvents(); + + _.$list.on('touchstart.slick mousedown.slick', { + action: 'start' + }, _.swipeHandler); + _.$list.on('touchmove.slick mousemove.slick', { + action: 'move' + }, _.swipeHandler); + _.$list.on('touchend.slick mouseup.slick', { + action: 'end' + }, _.swipeHandler); + _.$list.on('touchcancel.slick mouseleave.slick', { + action: 'end' + }, _.swipeHandler); + + _.$list.on('click.slick', _.clickHandler.bind(this)); + + if (_.options.pauseOnHover === true && _.options.autoplay === true) { + _.$list.on('mouseenter.slick', function(){ + _.paused = true; + _.autoPlayClear(); + }); + _.$list.on('mouseleave.slick', function(){ + _.paused = false; + _.autoPlay(); + }); + } + + if(_.options.accessibility === true) { + _.$list.on('keydown.slick', _.keyHandler); + } + + if(_.options.focusOnSelect === true) { + $(_.options.slide, _.$slideTrack).on('click.slick', _.selectHandler); + } + + $(window).on('orientationchange.slick.slick-' + _.instanceUid, function() { + _.checkResponsive(); + _.setPosition(); + }); + + $(window).on('resize.slick.slick-' + _.instanceUid, function() { + if ($(window).width() !== _.windowWidth) { + clearTimeout(_.windowDelay); + _.windowDelay = window.setTimeout(function() { + _.windowWidth = $(window).width(); + _.checkResponsive(); + _.setPosition(); + }, 50); + } + }); + + $('*[draggable!=true]', _.$slideTrack).on('dragstart', function(e){ e.preventDefault(); }) + + $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition); + $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition); + + }; + + Slick.prototype.initUI = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow.show(); + _.$nextArrow.show(); + + } + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + _.$dots.show(); + + } + + if (_.options.autoplay === true) { + + _.autoPlay(); + + } + + }; + + Slick.prototype.keyHandler = function(event) { + + var _ = this; + + if (event.keyCode === 37) { + _.changeSlide({ + data: { + message: 'previous' + } + }); + } else if (event.keyCode === 39) { + _.changeSlide({ + data: { + message: 'next' + } + }); + } + + }; + + Slick.prototype.lazyLoad = function() { + + var _ = this, + loadRange, cloneRange, rangeStart, rangeEnd; + + function loadImages(imagesScope) { + $('img[data-lazy]', imagesScope).each(function() { + var image = $(this), + imageSource = $(this).attr('data-lazy'); + + image + .load(function() { image.animate({ opacity: 1 }, 200); }) + .css({ opacity: 0 }) + .attr('src', imageSource) + .removeAttr('data-lazy') + .removeClass('slick-loading'); + }); + } + + if (_.options.centerMode === true) { + if (_.options.infinite === true) { + rangeStart = _.currentSlide + (_.options.slidesToShow/2 + 1); + rangeEnd = rangeStart + _.options.slidesToShow + 2; + } else { + rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow/2 + 1)); + rangeEnd = 2 + (_.options.slidesToShow/2 + 1) + _.currentSlide; + } + } else { + rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide; + rangeEnd = rangeStart + _.options.slidesToShow; + if (_.options.fade === true ) { + if(rangeStart > 0) rangeStart--; + if(rangeEnd <= _.slideCount) rangeEnd++; + } + } + + loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd); + loadImages(loadRange); + + if (_.slideCount <= _.options.slidesToShow){ + cloneRange = _.$slider.find('.slick-slide') + loadImages(cloneRange) + }else + if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { + cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow); + loadImages(cloneRange) + } else if (_.currentSlide === 0) { + cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1); + loadImages(cloneRange); + } + + }; + + Slick.prototype.loadSlider = function() { + + var _ = this; + + _.setPosition(); + + _.$slideTrack.css({ + opacity: 1 + }); + + _.$slider.removeClass('slick-loading'); + + _.initUI(); + + if (_.options.lazyLoad === 'progressive') { + _.progressiveLazyLoad(); + } + + }; + + Slick.prototype.postSlide = function(index) { + + var _ = this; + + if (_.options.onAfterChange !== null) { + _.options.onAfterChange.call(this, _, index); + } + + _.animating = false; + + _.setPosition(); + + _.swipeLeft = null; + + if (_.options.autoplay === true && _.paused === false) { + _.autoPlay(); + } + + }; + + Slick.prototype.progressiveLazyLoad = function() { + + var _ = this, + imgCount, targetImage; + + imgCount = $('img[data-lazy]').length; + + if (imgCount > 0) { + targetImage = $('img[data-lazy]', _.$slider).first(); + targetImage.attr('src', targetImage.attr('data-lazy')).removeClass('slick-loading').load(function() { + targetImage.removeAttr('data-lazy'); + _.progressiveLazyLoad(); + }) + .error(function () { + targetImage.removeAttr('data-lazy'); + _.progressiveLazyLoad(); + }); + } + + }; + + Slick.prototype.refresh = function() { + + var _ = this, + currentSlide = _.currentSlide; + + _.destroy(); + + $.extend(_, _.initials); + + _.currentSlide = currentSlide; + _.init(); + + }; + + Slick.prototype.reinit = function() { + + var _ = this; + + _.$slides = _.$slideTrack.children(_.options.slide).addClass( + 'slick-slide'); + + _.slideCount = _.$slides.length; + + if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) { + _.currentSlide = _.currentSlide - _.options.slidesToScroll; + } + + if (_.slideCount <= _.options.slidesToShow) { + _.currentSlide = 0; + } + + _.setProps(); + + _.setupInfinite(); + + _.buildArrows(); + + _.updateArrows(); + + _.initArrowEvents(); + + _.buildDots(); + + _.updateDots(); + + _.initDotEvents(); + + if(_.options.focusOnSelect === true) { + $(_.options.slide, _.$slideTrack).on('click.slick', _.selectHandler); + } + + _.setSlideClasses(0); + + _.setPosition(); + + if (_.options.onReInit !== null) { + _.options.onReInit.call(this, _); + } + + }; + + Slick.prototype.removeSlide = function(index, removeBefore) { + + var _ = this; + + if (typeof(index) === 'boolean') { + removeBefore = index; + index = removeBefore === true ? 0 : _.slideCount - 1; + } else { + index = removeBefore === true ? --index : index; + } + + if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) { + return false; + } + + _.unload(); + + _.$slideTrack.children(this.options.slide).eq(index).remove(); + + _.$slides = _.$slideTrack.children(this.options.slide); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slideTrack.append(_.$slides); + + _.$slidesCache = _.$slides; + + _.reinit(); + + }; + + Slick.prototype.setCSS = function(position) { + + var _ = this, + positionProps = {}, x, y; + + if (_.options.rtl === true) { + position = -position; + } + x = _.positionProp == 'left' ? position + 'px' : '0px'; + y = _.positionProp == 'top' ? position + 'px' : '0px'; + + positionProps[_.positionProp] = position; + + if (_.transformsEnabled === false) { + _.$slideTrack.css(positionProps); + } else { + positionProps = {}; + if (_.cssTransitions === false) { + positionProps[_.animType] = 'translate(' + x + ', ' + y + ')'; + _.$slideTrack.css(positionProps); + } else { + positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)'; + _.$slideTrack.css(positionProps); + } + } + + }; + + Slick.prototype.setDimensions = function() { + + var _ = this; + + if (_.options.vertical === false) { + if (_.options.centerMode === true) { + _.$list.css({ + padding: ('0px ' + _.options.centerPadding) + }); + } + } else { + _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow); + if (_.options.centerMode === true) { + _.$list.css({ + padding: (_.options.centerPadding + ' 0px') + }); + } + } + + _.listWidth = _.$list.width(); + _.listHeight = _.$list.height(); + + + if(_.options.vertical === false && _.options.variableWidth === false) { + _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); + _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length))); + + } else if (_.options.variableWidth === true) { + var trackWidth = 0; + _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); + _.$slideTrack.children('.slick-slide').each(function(){ + trackWidth += Math.ceil($(this).outerWidth(true)); + }); + _.$slideTrack.width(Math.ceil(trackWidth) + 1); + } else { + _.slideWidth = Math.ceil(_.listWidth); + _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length))); + } + + var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width(); + if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset); + + }; + + Slick.prototype.setFade = function() { + + var _ = this, + targetLeft; + + _.$slides.each(function(index, element) { + targetLeft = (_.slideWidth * index) * -1; + if (_.options.rtl === true) { + $(element).css({ + position: 'relative', + right: targetLeft, + top: 0, + zIndex: 800, + opacity: 0 + }); + } else { + $(element).css({ + position: 'relative', + left: targetLeft, + top: 0, + zIndex: 800, + opacity: 0 + }); + } + }); + + _.$slides.eq(_.currentSlide).css({ + zIndex: 900, + opacity: 1 + }); + + }; + + Slick.prototype.setHeight = function() { + + var _ = this; + + if(_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { + var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); + _.$list.css('height', targetHeight); + } + + }; + + Slick.prototype.setPosition = function() { + + var _ = this; + + _.setDimensions(); + + _.setHeight(); + + if (_.options.fade === false) { + _.setCSS(_.getLeft(_.currentSlide)); + } else { + _.setFade(); + } + + }; + + Slick.prototype.setProps = function() { + + var _ = this, + bodyStyle = document.body.style; + + _.positionProp = _.options.vertical === true ? 'top' : 'left'; + + if (_.positionProp === 'top') { + _.$slider.addClass('slick-vertical'); + } else { + _.$slider.removeClass('slick-vertical'); + } + + if (bodyStyle.WebkitTransition !== undefined || + bodyStyle.MozTransition !== undefined || + bodyStyle.msTransition !== undefined) { + if(_.options.useCSS === true) { + _.cssTransitions = true; + } + } + + if (bodyStyle.OTransform !== undefined) { + _.animType = 'OTransform'; + _.transformType = "-o-transform"; + _.transitionType = 'OTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; + } + if (bodyStyle.MozTransform !== undefined) { + _.animType = 'MozTransform'; + _.transformType = "-moz-transform"; + _.transitionType = 'MozTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false; + } + if (bodyStyle.webkitTransform !== undefined) { + _.animType = 'webkitTransform'; + _.transformType = "-webkit-transform"; + _.transitionType = 'webkitTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; + } + if (bodyStyle.msTransform !== undefined) { + _.animType = 'msTransform'; + _.transformType = "-ms-transform"; + _.transitionType = 'msTransition'; + if (bodyStyle.msTransform === undefined) _.animType = false; + } + if (bodyStyle.transform !== undefined && _.animType !== false) { + _.animType = 'transform'; + _.transformType = "transform"; + _.transitionType = 'transition'; + } + _.transformsEnabled = (_.animType !== null && _.animType !== false); + + }; + + + Slick.prototype.setSlideClasses = function(index) { + + var _ = this, + centerOffset, allSlides, indexOffset, remainder; + + _.$slider.find('.slick-slide').removeClass('slick-active').removeClass('slick-center'); + allSlides = _.$slider.find('.slick-slide'); + + if (_.options.centerMode === true) { + + centerOffset = Math.floor(_.options.slidesToShow / 2); + + if(_.options.infinite === true) { + + if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) { + _.$slides.slice(index - centerOffset, index + centerOffset + 1).addClass('slick-active'); + } else { + indexOffset = _.options.slidesToShow + index; + allSlides.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2).addClass('slick-active'); + } + + if (index === 0) { + allSlides.eq(allSlides.length - 1 - _.options.slidesToShow).addClass('slick-center'); + } else if (index === _.slideCount - 1) { + allSlides.eq(_.options.slidesToShow).addClass('slick-center'); + } + + } + + _.$slides.eq(index).addClass('slick-center'); + + } else { + + if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) { + _.$slides.slice(index, index + _.options.slidesToShow).addClass('slick-active'); + } else if ( allSlides.length <= _.options.slidesToShow ) { + allSlides.addClass('slick-active'); + } else { + remainder = _.slideCount%_.options.slidesToShow; + indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index; + if(_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) { + allSlides.slice(indexOffset-(_.options.slidesToShow-remainder), indexOffset + remainder).addClass('slick-active'); + } else { + allSlides.slice(indexOffset, indexOffset + _.options.slidesToShow).addClass('slick-active'); + } + } + + } + + if (_.options.lazyLoad === 'ondemand') { + _.lazyLoad(); + } + + }; + + Slick.prototype.setupInfinite = function() { + + var _ = this, + i, slideIndex, infiniteCount; + + if (_.options.fade === true) { + _.options.centerMode = false; + } + + if (_.options.infinite === true && _.options.fade === false) { + + slideIndex = null; + + if (_.slideCount > _.options.slidesToShow) { + + if (_.options.centerMode === true) { + infiniteCount = _.options.slidesToShow + 1; + } else { + infiniteCount = _.options.slidesToShow; + } + + for (i = _.slideCount; i > (_.slideCount - + infiniteCount); i -= 1) { + slideIndex = i - 1; + $(_.$slides[slideIndex]).clone(true).attr('id', '') + .attr('index', slideIndex-_.slideCount) + .prependTo(_.$slideTrack).addClass('slick-cloned'); + } + for (i = 0; i < infiniteCount; i += 1) { + slideIndex = i; + $(_.$slides[slideIndex]).clone(true).attr('id', '') + .attr('index', slideIndex+_.slideCount) + .appendTo(_.$slideTrack).addClass('slick-cloned'); + } + _.$slideTrack.find('.slick-cloned').find('[id]').each(function() { + $(this).attr('id', ''); + }); + + } + + } + + }; + + Slick.prototype.selectHandler = function(event) { + + var _ = this; + var index = parseInt($(event.target).parents('.slick-slide').attr("index")); + if(!index) index = 0; + + if(_.slideCount <= _.options.slidesToShow){ + _.$slider.find('.slick-slide').removeClass('slick-active'); + _.$slides.eq(index).addClass('slick-active'); + if(_.options.centerMode === true) { + _.$slider.find('.slick-slide').removeClass('slick-center'); + _.$slides.eq(index).addClass('slick-center'); + } + _.asNavFor(index); + return; + } + _.slideHandler(index); + + }; + + Slick.prototype.slideHandler = function(index,sync) { + + var targetSlide, animSlide, oldSlide, slideLeft, unevenOffset, targetLeft = null, + _ = this; + + sync = sync || false; + + if (_.animating === true && _.options.waitForAnimate === true) { + return; + } + + if (_.options.fade === true && _.currentSlide === index) { + return; + } + + if (_.slideCount <= _.options.slidesToShow) { + return; + } + + if (sync === false) { + _.asNavFor(index); + } + + targetSlide = index; + targetLeft = _.getLeft(targetSlide); + slideLeft = _.getLeft(_.currentSlide); + + unevenOffset = _.options.slidesToScroll === 1 ? 0 : _.options.slidesToShow - (Math.round(_.slideCount / _.options.slidesToScroll)); + + _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft; + + if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.slideCount - _.options.slidesToShow + unevenOffset)) { + if(_.options.fade === false) { + targetSlide = _.currentSlide; + _.animateSlide(slideLeft, function() { + _.postSlide(targetSlide); + }); + } + return; + } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) { + if(_.options.fade === false) { + targetSlide = _.currentSlide; + _.animateSlide(slideLeft, function() { + _.postSlide(targetSlide); + }); + } + return; + } + + if (_.options.autoplay === true) { + clearInterval(_.autoPlayTimer); + } + + if (targetSlide < 0) { + if (_.slideCount % _.options.slidesToScroll !== 0) { + animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll); + } else { + animSlide = _.slideCount + targetSlide; + } + } else if (targetSlide >= _.slideCount) { + if (_.slideCount % _.options.slidesToScroll !== 0) { + animSlide = 0; + } else { + animSlide = targetSlide - _.slideCount; + } + } else { + animSlide = targetSlide; + } + + _.animating = true; + + if (_.options.onBeforeChange !== null && index !== _.currentSlide) { + _.options.onBeforeChange.call(this, _, _.currentSlide, animSlide); + } + + oldSlide = _.currentSlide; + _.currentSlide = animSlide; + + _.setSlideClasses(_.currentSlide); + + _.updateDots(); + _.updateArrows(); + + if (_.options.fade === true) { + _.fadeSlide(oldSlide,animSlide, function() { + _.postSlide(animSlide); + }); + return; + } + + _.animateSlide(targetLeft, function() { + _.postSlide(animSlide); + }); + + }; + + Slick.prototype.startLoad = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow.hide(); + _.$nextArrow.hide(); + + } + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + _.$dots.hide(); + + } + + _.$slider.addClass('slick-loading'); + + }; + + Slick.prototype.swipeDirection = function() { + + var xDist, yDist, r, swipeAngle, _ = this; + + xDist = _.touchObject.startX - _.touchObject.curX; + yDist = _.touchObject.startY - _.touchObject.curY; + r = Math.atan2(yDist, xDist); + + swipeAngle = Math.round(r * 180 / Math.PI); + if (swipeAngle < 0) { + swipeAngle = 360 - Math.abs(swipeAngle); + } + + if ((swipeAngle <= 45) && (swipeAngle >= 0)) { + return 'left'; + } + if ((swipeAngle <= 360) && (swipeAngle >= 315)) { + return 'left'; + } + if ((swipeAngle >= 135) && (swipeAngle <= 225)) { + return 'right'; + } + + return 'vertical'; + + }; + + Slick.prototype.swipeEnd = function(event) { + + var _ = this, slideCount; + + _.dragging = false; + + _.shouldClick = (_.touchObject.swipeLength > 10) ? false : true; + + if (_.touchObject.curX === undefined) { + return false; + } + + if (_.touchObject.swipeLength >= _.touchObject.minSwipe) { + + switch (_.swipeDirection()) { + case 'left': + _.slideHandler(_.currentSlide + _.getSlideCount()); + _.currentDirection = 0; + _.touchObject = {}; + break; + + case 'right': + _.slideHandler(_.currentSlide - _.getSlideCount()); + _.currentDirection = 1; + _.touchObject = {}; + break; + } + } else { + if(_.touchObject.startX !== _.touchObject.curX) { + _.slideHandler(_.currentSlide); + _.touchObject = {}; + } + } + + }; + + Slick.prototype.swipeHandler = function(event) { + + var _ = this; + + if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) { + return; + } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) { + return; + } + + _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ? + event.originalEvent.touches.length : 1; + + _.touchObject.minSwipe = _.listWidth / _.options + .touchThreshold; + + switch (event.data.action) { + + case 'start': + _.swipeStart(event); + break; + + case 'move': + _.swipeMove(event); + break; + + case 'end': + _.swipeEnd(event); + break; + + } + + }; + + Slick.prototype.swipeMove = function(event) { + + var _ = this, + curLeft, swipeDirection, positionOffset, touches; + + touches = event.originalEvent !== undefined ? event.originalEvent.touches : null; + + if (!_.dragging || touches && touches.length !== 1) { + return false; + } + + curLeft = _.getLeft(_.currentSlide); + + _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX; + _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY; + + _.touchObject.swipeLength = Math.round(Math.sqrt( + Math.pow(_.touchObject.curX - _.touchObject.startX, 2))); + + swipeDirection = _.swipeDirection(); + + if (swipeDirection === 'vertical') { + return; + } + + if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) { + event.preventDefault(); + } + + positionOffset = _.touchObject.curX > _.touchObject.startX ? 1 : -1; + + if (_.options.vertical === false) { + _.swipeLeft = curLeft + _.touchObject.swipeLength * positionOffset; + } else { + _.swipeLeft = curLeft + (_.touchObject + .swipeLength * (_.$list.height() / _.listWidth)) * positionOffset; + } + + if (_.options.fade === true || _.options.touchMove === false) { + return false; + } + + if (_.animating === true) { + _.swipeLeft = null; + return false; + } + + _.setCSS(_.swipeLeft); + + }; + + Slick.prototype.swipeStart = function(event) { + + var _ = this, + touches; + + if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) { + _.touchObject = {}; + return false; + } + + if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) { + touches = event.originalEvent.touches[0]; + } + + _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX; + _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY; + + _.dragging = true; + + }; + + Slick.prototype.unfilterSlides = function() { + + var _ = this; + + if (_.$slidesCache !== null) { + + _.unload(); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slidesCache.appendTo(_.$slideTrack); + + _.reinit(); + + } + + }; + + Slick.prototype.unload = function() { + + var _ = this; + + $('.slick-cloned', _.$slider).remove(); + if (_.$dots) { + _.$dots.remove(); + } + if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) { + _.$prevArrow.remove(); + } + if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) { + _.$nextArrow.remove(); + } + _.$slides.removeClass( + 'slick-slide slick-active slick-visible').css('width', ''); + + }; + + Slick.prototype.updateArrows = function() { + + var _ = this, centerOffset; + + centerOffset = Math.floor(_.options.slidesToShow / 2) + + if (_.options.arrows === true && _.options.infinite !== + true && _.slideCount > _.options.slidesToShow) { + _.$prevArrow.removeClass('slick-disabled'); + _.$nextArrow.removeClass('slick-disabled'); + if (_.currentSlide === 0) { + _.$prevArrow.addClass('slick-disabled'); + _.$nextArrow.removeClass('slick-disabled'); + } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) { + _.$nextArrow.addClass('slick-disabled'); + _.$prevArrow.removeClass('slick-disabled'); + } else if (_.currentSlide > _.slideCount - _.options.slidesToShow + centerOffset && _.options.centerMode === true) { + _.$nextArrow.addClass('slick-disabled'); + _.$prevArrow.removeClass('slick-disabled'); + } + } + + }; + + Slick.prototype.updateDots = function() { + + var _ = this; + + if (_.$dots !== null) { + + _.$dots.find('li').removeClass('slick-active'); + _.$dots.find('li').eq(Math.floor(_.currentSlide / _.options.slidesToScroll)).addClass('slick-active'); + + } + + }; + + $.fn.slick = function(options) { + var _ = this; + return _.each(function(index, element) { + + element.slick = new Slick(element, options); + + }); + }; + + $.fn.slickAdd = function(slide, slideIndex, addBefore) { + var _ = this; + return _.each(function(index, element) { + + element.slick.addSlide(slide, slideIndex, addBefore); + + }); + }; + + $.fn.slickCurrentSlide = function() { + var _ = this; + return _.get(0).slick.getCurrent(); + }; + + $.fn.slickFilter = function(filter) { + var _ = this; + return _.each(function(index, element) { + + element.slick.filterSlides(filter); + + }); + }; + + $.fn.slickGoTo = function(slide) { + var _ = this; + return _.each(function(index, element) { + + element.slick.changeSlide({ + data: { + message: 'index', + index: parseInt(slide) + } + }); + + }); + }; + + $.fn.slickNext = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.changeSlide({ + data: { + message: 'next' + } + }); + + }); + }; + + $.fn.slickPause = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.autoPlayClear(); + element.slick.paused = true; + + }); + }; + + $.fn.slickPlay = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.paused = false; + element.slick.autoPlay(); + + }); + }; + + $.fn.slickPrev = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.changeSlide({ + data: { + message: 'previous' + } + }); + + }); + }; + + $.fn.slickRemove = function(slideIndex, removeBefore) { + var _ = this; + return _.each(function(index, element) { + + element.slick.removeSlide(slideIndex, removeBefore); + + }); + }; + + $.fn.slickGetOption = function(option) { + var _ = this; + return _.get(0).slick.options[option]; + }; + + $.fn.slickSetOption = function(option, value, refresh) { + var _ = this; + return _.each(function(index, element) { + + element.slick.options[option] = value; + + if (refresh === true) { + element.slick.unload(); + element.slick.reinit(); + } + + }); + }; + + $.fn.slickUnfilter = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.unfilterSlides(); + + }); + }; + + $.fn.unslick = function() { + var _ = this; + return _.each(function(index, element) { + + if (element.slick) { + element.slick.destroy(); + } + + }); + }; + + $.fn.getSlick = function() { + var s = null; + var _ = this; + _.each(function(index, element) { + s = element.slick; + }); + + return s; + }; + +})); diff --git a/tests/phpunit/Slick_Test.php b/tests/phpunit/Slick_Test.php new file mode 100644 index 0000000..cbab1f9 --- /dev/null +++ b/tests/phpunit/Slick_Test.php @@ -0,0 +1,46 @@ +<?php +namespace PhpTags; + +class PhpTagsWidgets_Slick_Test extends \MediaWikiTestCase { + + public function testRun_property_style() { + $this->assertEquals( + Runtime::runSource( '$s = new Slick( ["sTyLe"=>"myStyle"] ); echo $s->StYlE;' ), + array( 'myStyle' ) + ); + } + + public function testRun_property_unset_1() { + $this->assertEquals( + Runtime::runSource( '$s = new Slick( ["style"=>"myStyle"] ); echo $s->style; $s->sTyle = null; echo $s->style;' ), + array( 'myStyle', null ) + ); + } + public function testRun_property_unset_2() { + $this->assertEquals( + Runtime::runSource( '$s = new Slick( ["dotS"=>"it must be boolean true"] ); echo $s->dOts; $s->Dots = null; echo $s->doTs;' ), + array( true, null ) + ); + } + + public function testRun_property_rtl() { + $this->assertEquals( + Runtime::runSource( '$s = new Slick( ["rTl"=>"it must be boolean true"] ); echo $s->RtL, $s->diR;' ), + array( true, 'rtl' ) + ); + } + + public function testRun_property_asNavFor() { + $this->assertEquals( + Runtime::runSource( ' +$one = new Slick(); echo $one->asNavFor; +$two = new Slick(); echo $two->asNavFor; +$one->asNavFor = $two; +echo $one->asNavFor === $two ? "true1" : "false1", $two->asNavFor === $one ? "true2" : "false2"; +$two->asNavFor = null; +echo $one->asNavFor === null ? "true1" : "false1", $two->asNavFor === null ? "true2" : "false2";' ), + array( null, null, 'true1', 'true2', 'true1', 'true2' ) + ); + } + +} -- To view, visit https://gerrit.wikimedia.org/r/172222 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ifb57ca9716953389f3601373fe875e0d14d6fb7f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/PhpTagsWidgets Gerrit-Branch: master Gerrit-Owner: Pastakhov <pastak...@yandex.ru> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits