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="&#8594;" 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="&#8592;" 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="&#8226;" 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="&#97;" 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

Reply via email to