├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .npmignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── dist ├── owl.carousel2.thumbs.js └── owl.carousel2.thumbs.min.js ├── package.json └── src └── owl.carousel2.thumbs.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | indent_style = space 11 | indent_size = 4 12 | 13 | end_of_line = lf 14 | charset = utf-8 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | 21 | [{*.json,*.yml}] 22 | indent_size = 2 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | _site 4 | *.zip 5 | *.rar 6 | /.idea 7 | /demo 8 | 9 | # Ignore files beginning with a # 10 | \#* 11 | 12 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": false, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 4, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "asi" : true, 22 | "boss" : true, 23 | "browser" : true, 24 | "debug" : true, 25 | "devel" : true, 26 | "eqeqeq" : false, 27 | "eqnull" : true, 28 | "expr" : true, 29 | "laxbreak" : true, 30 | "unused" : false, 31 | "validthis": true, 32 | "globals": { 33 | "jQuery": true, 34 | "define": true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .editorconfig 2 | .gitattributes 3 | .gitignore 4 | .jshintrc 5 | .travis.yml 6 | *.zip 7 | *.rar 8 | 9 | bower.json 10 | /example 11 | /.idea 12 | /demo -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | 'use strict'; 4 | 5 | // Load grunt tasks automatically 6 | require('load-grunt-tasks')(grunt); 7 | 8 | // Time how long tasks take. Can help when optimizing build times 9 | require('time-grunt')(grunt); 10 | 11 | // Project configuration. 12 | grunt.initConfig({ 13 | 14 | config: { 15 | src: 'src', 16 | dist: 'dist' 17 | }, 18 | 19 | pkg: require('./package'), 20 | 21 | meta: { 22 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> | ' + 23 | '(c) <%= grunt.template.today("yyyy") %> @gijsroge | ' + 24 | '<%= pkg.license.type %> license | <%= pkg.homepage %> */\n' 25 | }, 26 | 27 | // Watches files for changes and runs tasks based on the changed files 28 | watch: { 29 | jshint: { 30 | files: '<%= config.src %>/{,*/}*.js', 31 | tasks: ['jshint'] 32 | }, 33 | 34 | concat: { 35 | files: '<%= config.src %>/{,*/}*.js', 36 | tasks: ['concat:dist', 'uglify:dist'] 37 | } 38 | }, 39 | 40 | // Make sure code styles are up to par and there are no obvious mistakes 41 | jshint: { 42 | options: { 43 | jshintrc: '.jshintrc', 44 | reporter: require('jshint-stylish') 45 | }, 46 | all: [ 47 | 'Gruntfile.js', 48 | '<%= config.src %>/{,*/}*.js' 49 | ], 50 | }, 51 | 52 | // Prepend a banner to the files 53 | concat: { 54 | options: { 55 | banner: '<%= meta.banner %>' 56 | }, 57 | dist: { 58 | src: ['<%= config.src %>/<%= pkg.name %>.js'], 59 | dest: '<%= config.dist %>/<%= pkg.name %>.js' 60 | } 61 | }, 62 | 63 | // Generate a minified version 64 | uglify: { 65 | options: { 66 | banner: '<%= meta.banner %>' 67 | }, 68 | dist: { 69 | src: ['<%= config.dist %>/<%= pkg.name %>.js'], 70 | dest: '<%= config.dist %>/<%= pkg.name %>.min.js' 71 | } 72 | }, 73 | 74 | // Increment version 75 | bump: { 76 | options: { 77 | files: [ 78 | 'bower.json', 79 | 'package.json', 80 | '<%= pkg.name %>.jquery.json' 81 | ], 82 | updateConfigs: ['pkg'], 83 | commitMessage: 'v%VERSION%', 84 | commitFiles: [ 85 | 'bower.json', 86 | 'package.json', 87 | 'dist' 88 | ], 89 | createTag: false, 90 | push: true, 91 | pushTo: 'origin master' 92 | } 93 | }, 94 | 95 | //create package 96 | compress: { 97 | main: { 98 | options: { 99 | archive: '<%= pkg.name %>-v<%= pkg.version %>.zip' 100 | }, 101 | expand: true, 102 | cwd: '<%= config.dist %>/', 103 | src: ['**/*'], 104 | dest: '/' 105 | } 106 | } 107 | }); 108 | 109 | // Build task 110 | grunt.registerTask('build', ['jshint', 'concat:dist', 'uglify:dist']); 111 | 112 | // Release task 113 | grunt.registerTask('release', [ 114 | 'bump-only', 115 | 'build', 116 | 'compress:main', 117 | 'bump-commit' 118 | ]); 119 | }; 120 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 gijsroge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Owl Carousel 2 Thumbnails plugin 2 | Enables thumbnail support for Owl Carousel 2.0 3 | 4 | ## Quick start 5 | grab the [latest release](https://github.com/gijsroge/OwlCarousel2-Thumbs/archive/0.1.7.tar.gz) and slam it behind the default owl carousel plugin. 6 | 7 | ##### Enable thumbs 8 | ```javascript 9 | $(document).ready(function(){ 10 | $('.owl-carousel').owlCarousel({ 11 | thumbs: true 12 | }); 13 | }); 14 | ``` 15 | 16 | ## Use pre-rendered html as thumbnails. **_recommended_** 17 | ```javascript 18 | $(document).ready(function(){ 19 | $('.owl-carousel').owlCarousel({ 20 | thumbs: true, 21 | thumbsPrerendered: true 22 | }); 23 | }); 24 | ``` 25 | 26 | ##### Add thumbnails (link slider and thumbnails with data-slider-id attribute) 27 | ```html 28 | 34 |
35 | 36 | 37 | 38 | 39 |
40 | ``` 41 | 42 | ## Or add data-thumb attribute to your slides 43 | ```html 44 | 50 | ``` 51 | 52 | #### [demo](http://gijsroge.github.io/owl-carousel2-thumbs) 53 | 54 | ## Available options 55 | ```javascript 56 | $(document).ready(function(){ 57 | $('.owl-carousel').owlCarousel({ 58 | // Enable thumbnails 59 | thumbs: true, 60 | 61 | // When only using images in your slide (like the demo) use this option to dynamicly create thumbnails without using the attribute data-thumb. 62 | thumbImage: false, 63 | 64 | // Enable this if you have pre-rendered thumbnails in your html instead of letting this plugin generate them. This is recommended as it will prevent FOUC 65 | thumbsPrerendered: true, 66 | 67 | // Class that will be used on the thumbnail container 68 | thumbContainerClass: 'owl-thumbs', 69 | 70 | // Class that will be used on the thumbnail item's 71 | thumbItemClass: 'owl-thumb-item' 72 | }); 73 | }); 74 | ``` 75 | 76 | ## npm 77 | ``` 78 | npm install owl.carousel2.thumbs 79 | ``` 80 | 81 | ## bower 82 | ``` 83 | bower install owl.carousel2.thumbs 84 | ``` 85 | 86 | with <3 in Belgium by [@GijsRoge](https://twitter.com/GijsRoge) 87 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "owl.carousel2.thumbs", 3 | "version": "0.1.8", 4 | "homepage": "https://github.com/gijsroge/OwlCarousel2-Thumbs", 5 | "authors": [ 6 | { "name" : "Gijs Rogé", 7 | "homepage" : "http://twitter.com/gijsroge" 8 | } 9 | ], 10 | "description": "Enables thumbnail support for Owl Carousel 2.0", 11 | "main": "dist/owl.carousel2.thumbs.min.js", 12 | "license": "MIT", 13 | "keywords": [ 14 | "Owl", 15 | "Carousel", 16 | "Thumbs", 17 | "Thumbnails", 18 | "jQuery" 19 | ], 20 | "ignore": [ 21 | "**/.*", 22 | "*.json", 23 | "src", 24 | "example", 25 | "node_modules", 26 | "bower_components", 27 | "Gruntfile.js" 28 | ], 29 | "repository" : 30 | { 31 | "type" : "git", 32 | "url" : "https://github.com/gijsroge/OwlCarousel2-Thumbs" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dist/owl.carousel2.thumbs.js: -------------------------------------------------------------------------------- 1 | /*! owl.carousel2.thumbs - v0.1.8 | (c) 2016 @gijsroge | MIT license | https://github.com/gijsroge/OwlCarousel2-Thumbs */ 2 | /** 3 | * Thumbs Plugin 4 | * @version 2.0.0 5 | * @author Gijs Rogé 6 | * @license The MIT License (MIT) 7 | */ 8 | (function ($, window, document, undefined) { 9 | 'use strict'; 10 | 11 | /** 12 | * Creates the thumbs plugin. 13 | * @class The thumbs Plugin 14 | * @param {Owl} carousel - The Owl Carousel 15 | */ 16 | var Thumbs = function (carousel) { 17 | 18 | 19 | /** 20 | * Reference to the core. 21 | * @protected 22 | * @type {Owl} 23 | */ 24 | this.owl = carousel; 25 | 26 | 27 | /** 28 | * All DOM elements for thumbnails 29 | * @protected 30 | * @type {Object} 31 | */ 32 | this._thumbcontent = []; 33 | 34 | 35 | /** 36 | * Instance identiefier 37 | * @type {number} 38 | * @private 39 | */ 40 | this._identifier = 0; 41 | 42 | 43 | /** 44 | * Return current item regardless of clones 45 | * @protected 46 | * @type {Object} 47 | */ 48 | this.owl_currentitem = this.owl.options.startPosition; 49 | 50 | 51 | /** 52 | * The carousel element. 53 | * @type {jQuery} 54 | */ 55 | this.$element = this.owl.$element; 56 | 57 | 58 | /** 59 | * All event handlers. 60 | * @protected 61 | * @type {Object} 62 | */ 63 | this._handlers = { 64 | 'prepared.owl.carousel': $.proxy(function (e) { 65 | if (e.namespace && this.owl.options.thumbs && !this.owl.options.thumbImage && !this.owl.options.thumbsPrerendered && !this.owl.options.thumbImage) { 66 | if ($(e.content).find('[data-thumb]').attr('data-thumb') !== undefined) { 67 | this._thumbcontent.push($(e.content).find('[data-thumb]').attr('data-thumb')); 68 | } 69 | } else if (e.namespace && this.owl.options.thumbs && this.owl.options.thumbImage) { 70 | var innerImage = $(e.content).find('img'); 71 | this._thumbcontent.push(innerImage); 72 | } 73 | }, this), 74 | 75 | 'initialized.owl.carousel': $.proxy(function (e) { 76 | if (e.namespace && this.owl.options.thumbs) { 77 | this.render(); 78 | this.listen(); 79 | this._identifier = this.owl.$element.data('slider-id'); 80 | this.setActive(); 81 | } 82 | }, this), 83 | 84 | 'changed.owl.carousel': $.proxy(function (e) { 85 | if (e.namespace && e.property.name === 'position' && this.owl.options.thumbs) { 86 | this._identifier = this.owl.$element.data('slider-id'); 87 | this.setActive(); 88 | } 89 | }, this) 90 | }; 91 | 92 | // set default options 93 | this.owl.options = $.extend({}, Thumbs.Defaults, this.owl.options); 94 | 95 | // register the event handlers 96 | this.owl.$element.on(this._handlers); 97 | }; 98 | 99 | 100 | /** 101 | * Default options. 102 | * @public 103 | */ 104 | Thumbs.Defaults = { 105 | thumbs: true, 106 | thumbImage: false, 107 | thumbContainerClass: 'owl-thumbs', 108 | thumbItemClass: 'owl-thumb-item', 109 | moveThumbsInside: false 110 | }; 111 | 112 | 113 | /** 114 | * Listen for thumbnail click 115 | * @protected 116 | */ 117 | Thumbs.prototype.listen = function () { 118 | 119 | //set default options 120 | var options = this.owl.options; 121 | 122 | if (options.thumbsPrerendered) { 123 | this._thumbcontent._thumbcontainer = $('.' + options.thumbContainerClass); 124 | } 125 | 126 | //check what thumbitem has been clicked and move slider to that item 127 | $(this._thumbcontent._thumbcontainer).on('click', this._thumbcontent._thumbcontainer.children(), $.proxy(function (e) { 128 | 129 | // find relative slider 130 | this._identifier = $(e.target).closest('.' + options.thumbContainerClass).data('slider-id'); 131 | 132 | // get index of clicked thumbnail 133 | var index = $(e.target).parent().is(this._thumbcontent._thumbcontainer) ? $(e.target).index() : $(e.target).closest('.'+options.thumbItemClass).index(); 134 | 135 | if (options.thumbsPrerendered) { 136 | // slide to slide :) 137 | $('[data-slider-id=' + this._identifier + ']').trigger('to.owl.carousel', [index, options.dotsSpeed, true]); 138 | } else { 139 | this.owl.to(index, options.dotsSpeed); 140 | } 141 | 142 | e.preventDefault(); 143 | }, this)); 144 | }; 145 | 146 | 147 | /** 148 | * Builds thumbnails 149 | * @protected 150 | */ 151 | Thumbs.prototype.render = function () { 152 | 153 | //set default options 154 | var options = this.owl.options; 155 | 156 | //create thumbcontainer 157 | if (!options.thumbsPrerendered) { 158 | this._thumbcontent._thumbcontainer = $('
').addClass(options.thumbContainerClass).appendTo(this.$element); 159 | } else { 160 | this._thumbcontent._thumbcontainer = $('.' + options.thumbContainerClass + ''); 161 | if(options.moveThumbsInside){ 162 | this._thumbcontent._thumbcontainer.appendTo(this.$element); 163 | } 164 | } 165 | 166 | //create thumb items 167 | var i; 168 | if (!options.thumbImage) { 169 | for (i = 0; i < this._thumbcontent.length; ++i) { 170 | this._thumbcontent._thumbcontainer.append(''); 171 | } 172 | } else { 173 | for (i = 0; i < this._thumbcontent.length; ++i) { 174 | this._thumbcontent._thumbcontainer.append(''); 175 | } 176 | } 177 | }; 178 | 179 | 180 | /** 181 | * Updates active class on thumbnails 182 | * @protected 183 | */ 184 | Thumbs.prototype.setActive = function () { 185 | 186 | // get startslide 187 | this.owl_currentitem = this.owl._current - (this.owl._clones.length / 2); 188 | if (this.owl_currentitem === this.owl._items.length) { 189 | this.owl_currentitem = 0; 190 | } 191 | 192 | //set default options 193 | var options = this.owl.options; 194 | 195 | // set relative thumbnail container 196 | var thumbContainer = options.thumbsPrerendered ? $('.' + options.thumbContainerClass + '[data-slider-id="' + this._identifier + '"]') : this._thumbcontent._thumbcontainer; 197 | thumbContainer.children().filter('.active').removeClass('active'); 198 | thumbContainer.children().eq(this.owl_currentitem).addClass('active'); 199 | }; 200 | 201 | 202 | /** 203 | * Destroys the plugin. 204 | * @public 205 | */ 206 | Thumbs.prototype.destroy = function () { 207 | var handler, property; 208 | for (handler in this._handlers) { 209 | this.owl.$element.off(handler, this._handlers[handler]); 210 | } 211 | for (property in Object.getOwnPropertyNames(this)) { 212 | typeof this[property] !== 'function' && (this[property] = null); 213 | } 214 | }; 215 | 216 | $.fn.owlCarousel.Constructor.Plugins.Thumbs = Thumbs; 217 | 218 | })(window.Zepto || window.jQuery, window, document); -------------------------------------------------------------------------------- /dist/owl.carousel2.thumbs.min.js: -------------------------------------------------------------------------------- 1 | /*! owl.carousel2.thumbs - v0.1.8 | (c) 2016 @gijsroge | MIT license | https://github.com/gijsroge/OwlCarousel2-Thumbs */ 2 | !function(a,b,c,d){"use strict";var e=function(b){this.owl=b,this._thumbcontent=[],this._identifier=0,this.owl_currentitem=this.owl.options.startPosition,this.$element=this.owl.$element,this._handlers={"prepared.owl.carousel":a.proxy(function(b){if(!b.namespace||!this.owl.options.thumbs||this.owl.options.thumbImage||this.owl.options.thumbsPrerendered||this.owl.options.thumbImage){if(b.namespace&&this.owl.options.thumbs&&this.owl.options.thumbImage){var c=a(b.content).find("img");this._thumbcontent.push(c)}}else a(b.content).find("[data-thumb]").attr("data-thumb")!==d&&this._thumbcontent.push(a(b.content).find("[data-thumb]").attr("data-thumb"))},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this.owl.options.thumbs&&(this.render(),this.listen(),this._identifier=this.owl.$element.data("slider-id"),this.setActive())},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&"position"===a.property.name&&this.owl.options.thumbs&&(this._identifier=this.owl.$element.data("slider-id"),this.setActive())},this)},this.owl.options=a.extend({},e.Defaults,this.owl.options),this.owl.$element.on(this._handlers)};e.Defaults={thumbs:!0,thumbImage:!1,thumbContainerClass:"owl-thumbs",thumbItemClass:"owl-thumb-item",moveThumbsInside:!1},e.prototype.listen=function(){var b=this.owl.options;b.thumbsPrerendered&&(this._thumbcontent._thumbcontainer=a("."+b.thumbContainerClass)),a(this._thumbcontent._thumbcontainer).on("click",this._thumbcontent._thumbcontainer.children(),a.proxy(function(c){this._identifier=a(c.target).closest("."+b.thumbContainerClass).data("slider-id");var d=a(c.target).parent().is(this._thumbcontent._thumbcontainer)?a(c.target).index():a(c.target).closest("."+b.thumbItemClass).index();b.thumbsPrerendered?a("[data-slider-id="+this._identifier+"]").trigger("to.owl.carousel",[d,b.dotsSpeed,!0]):this.owl.to(d,b.dotsSpeed),c.preventDefault()},this))},e.prototype.render=function(){var b=this.owl.options;b.thumbsPrerendered?(this._thumbcontent._thumbcontainer=a("."+b.thumbContainerClass),b.moveThumbsInside&&this._thumbcontent._thumbcontainer.appendTo(this.$element)):this._thumbcontent._thumbcontainer=a("
").addClass(b.thumbContainerClass).appendTo(this.$element);var c;if(b.thumbImage)for(c=0;c');else for(c=0;c"+this._thumbcontent[c]+"")},e.prototype.setActive=function(){this.owl_currentitem=this.owl._current-this.owl._clones.length/2,this.owl_currentitem===this.owl._items.length&&(this.owl_currentitem=0);var b=this.owl.options,c=b.thumbsPrerendered?a("."+b.thumbContainerClass+'[data-slider-id="'+this._identifier+'"]'):this._thumbcontent._thumbcontainer;c.children().filter(".active").removeClass("active"),c.children().eq(this.owl_currentitem).addClass("active")},e.prototype.destroy=function(){var a,b;for(a in this._handlers)this.owl.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.Thumbs=e}(window.Zepto||window.jQuery,window,document); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "owl.carousel2.thumbs", 3 | "title": "Owl Carousel 2 Thumbnails", 4 | "description": "Enables thumbnail support for Owl Carousel 2.0", 5 | "version": "0.1.8", 6 | "main": "dist/owl.carousel2.thumbs.min.js", 7 | "homepage": "https://github.com/gijsroge/OwlCarousel2-Thumbs", 8 | "author": { 9 | "name": "Gijs Rogé", 10 | "url": "http://twitter.com/gijsroge" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/gijsroge/OwlCarousel2-Thumbs.git" 15 | }, 16 | "keywords": [ 17 | "Owl", 18 | "Carousel", 19 | "Thumbs", 20 | "Thumbnails", 21 | "jQuery" 22 | ], 23 | "license": { 24 | "type": "MIT", 25 | "url": "https://github.com/gijsroge/OwlCarousel2-Thumbs/blob/master/LICENSE" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/gijsroge/OwlCarousel2-Thumbs/issues" 29 | }, 30 | "engines": { 31 | "node": ">=0.8.0" 32 | }, 33 | "dependencies": {}, 34 | "devDependencies": { 35 | "crayola": "0.0.1", 36 | "grunt": "~0.4.2", 37 | "grunt-bump": "0.0.15", 38 | "grunt-contrib-compress": "^0.13.0", 39 | "grunt-contrib-concat": "~0.3.0", 40 | "grunt-contrib-jshint": "~0.8.0", 41 | "grunt-contrib-uglify": "~0.2.7", 42 | "grunt-contrib-watch": "~0.5.2", 43 | "jshint-stylish": "~0.1.5", 44 | "load-grunt-tasks": "~0.2.1", 45 | "time-grunt": "~0.2.7" 46 | }, 47 | "scripts": { 48 | "test": "grunt jshint" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/owl.carousel2.thumbs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Thumbs Plugin 3 | * @version 2.0.0 4 | * @author Gijs Rogé 5 | * @license The MIT License (MIT) 6 | */ 7 | (function ($, window, document, undefined) { 8 | 'use strict'; 9 | 10 | /** 11 | * Creates the thumbs plugin. 12 | * @class The thumbs Plugin 13 | * @param {Owl} carousel - The Owl Carousel 14 | */ 15 | var Thumbs = function (carousel) { 16 | 17 | 18 | /** 19 | * Reference to the core. 20 | * @protected 21 | * @type {Owl} 22 | */ 23 | this.owl = carousel; 24 | 25 | 26 | /** 27 | * All DOM elements for thumbnails 28 | * @protected 29 | * @type {Object} 30 | */ 31 | this._thumbcontent = []; 32 | 33 | 34 | /** 35 | * Instance identiefier 36 | * @type {number} 37 | * @private 38 | */ 39 | this._identifier = 0; 40 | 41 | 42 | /** 43 | * Return current item regardless of clones 44 | * @protected 45 | * @type {Object} 46 | */ 47 | this.owl_currentitem = this.owl.options.startPosition; 48 | 49 | 50 | /** 51 | * The carousel element. 52 | * @type {jQuery} 53 | */ 54 | this.$element = this.owl.$element; 55 | 56 | 57 | /** 58 | * All event handlers. 59 | * @protected 60 | * @type {Object} 61 | */ 62 | this._handlers = { 63 | 'prepared.owl.carousel': $.proxy(function (e) { 64 | if (e.namespace && this.owl.options.thumbs && !this.owl.options.thumbImage && !this.owl.options.thumbsPrerendered && !this.owl.options.thumbImage) { 65 | if ($(e.content).find('[data-thumb]').attr('data-thumb') !== undefined) { 66 | this._thumbcontent.push($(e.content).find('[data-thumb]').attr('data-thumb')); 67 | } 68 | } else if (e.namespace && this.owl.options.thumbs && this.owl.options.thumbImage) { 69 | var innerImage = $(e.content).find('img'); 70 | this._thumbcontent.push(innerImage); 71 | } 72 | }, this), 73 | 74 | 'initialized.owl.carousel': $.proxy(function (e) { 75 | if (e.namespace && this.owl.options.thumbs) { 76 | this.render(); 77 | this.listen(); 78 | this._identifier = this.owl.$element.data('slider-id'); 79 | this.setActive(); 80 | } 81 | }, this), 82 | 83 | 'changed.owl.carousel': $.proxy(function (e) { 84 | if (e.namespace && e.property.name === 'position' && this.owl.options.thumbs) { 85 | this._identifier = this.owl.$element.data('slider-id'); 86 | this.setActive(); 87 | } 88 | }, this) 89 | }; 90 | 91 | // set default options 92 | this.owl.options = $.extend({}, Thumbs.Defaults, this.owl.options); 93 | 94 | // register the event handlers 95 | this.owl.$element.on(this._handlers); 96 | }; 97 | 98 | 99 | /** 100 | * Default options. 101 | * @public 102 | */ 103 | Thumbs.Defaults = { 104 | thumbs: true, 105 | thumbImage: false, 106 | thumbContainerClass: 'owl-thumbs', 107 | thumbItemClass: 'owl-thumb-item', 108 | moveThumbsInside: false 109 | }; 110 | 111 | 112 | /** 113 | * Listen for thumbnail click 114 | * @protected 115 | */ 116 | Thumbs.prototype.listen = function () { 117 | 118 | //set default options 119 | var options = this.owl.options; 120 | 121 | if (options.thumbsPrerendered) { 122 | this._thumbcontent._thumbcontainer = $('.' + options.thumbContainerClass); 123 | } 124 | 125 | //check what thumbitem has been clicked and move slider to that item 126 | $(this._thumbcontent._thumbcontainer).on('click', this._thumbcontent._thumbcontainer.children(), $.proxy(function (e) { 127 | 128 | // find relative slider 129 | this._identifier = $(e.target).closest('.' + options.thumbContainerClass).data('slider-id'); 130 | 131 | // get index of clicked thumbnail 132 | var index = $(e.target).parent().is(this._thumbcontent._thumbcontainer) ? $(e.target).index() : $(e.target).closest('.'+options.thumbItemClass).index(); 133 | 134 | if (options.thumbsPrerendered) { 135 | // slide to slide :) 136 | $('[data-slider-id=' + this._identifier + ']').trigger('to.owl.carousel', [index, options.dotsSpeed, true]); 137 | } else { 138 | this.owl.to(index, options.dotsSpeed); 139 | } 140 | 141 | e.preventDefault(); 142 | }, this)); 143 | }; 144 | 145 | 146 | /** 147 | * Builds thumbnails 148 | * @protected 149 | */ 150 | Thumbs.prototype.render = function () { 151 | 152 | //set default options 153 | var options = this.owl.options; 154 | 155 | //create thumbcontainer 156 | if (!options.thumbsPrerendered) { 157 | this._thumbcontent._thumbcontainer = $('
').addClass(options.thumbContainerClass).appendTo(this.$element); 158 | } else { 159 | this._thumbcontent._thumbcontainer = $('.' + options.thumbContainerClass + ''); 160 | if(options.moveThumbsInside){ 161 | this._thumbcontent._thumbcontainer.appendTo(this.$element); 162 | } 163 | } 164 | 165 | //create thumb items 166 | var i; 167 | if (!options.thumbImage) { 168 | for (i = 0; i < this._thumbcontent.length; ++i) { 169 | this._thumbcontent._thumbcontainer.append(''); 170 | } 171 | } else { 172 | for (i = 0; i < this._thumbcontent.length; ++i) { 173 | this._thumbcontent._thumbcontainer.append(''); 174 | } 175 | } 176 | }; 177 | 178 | 179 | /** 180 | * Updates active class on thumbnails 181 | * @protected 182 | */ 183 | Thumbs.prototype.setActive = function () { 184 | 185 | // get startslide 186 | this.owl_currentitem = this.owl._current - (this.owl._clones.length / 2); 187 | if (this.owl_currentitem === this.owl._items.length) { 188 | this.owl_currentitem = 0; 189 | } 190 | 191 | //set default options 192 | var options = this.owl.options; 193 | 194 | // set relative thumbnail container 195 | var thumbContainer = options.thumbsPrerendered ? $('.' + options.thumbContainerClass + '[data-slider-id="' + this._identifier + '"]') : this._thumbcontent._thumbcontainer; 196 | thumbContainer.children().filter('.active').removeClass('active'); 197 | thumbContainer.children().eq(this.owl_currentitem).addClass('active'); 198 | }; 199 | 200 | 201 | /** 202 | * Destroys the plugin. 203 | * @public 204 | */ 205 | Thumbs.prototype.destroy = function () { 206 | var handler, property; 207 | for (handler in this._handlers) { 208 | this.owl.$element.off(handler, this._handlers[handler]); 209 | } 210 | for (property in Object.getOwnPropertyNames(this)) { 211 | typeof this[property] !== 'function' && (this[property] = null); 212 | } 213 | }; 214 | 215 | $.fn.owlCarousel.Constructor.Plugins.Thumbs = Thumbs; 216 | 217 | })(window.Zepto || window.jQuery, window, document); --------------------------------------------------------------------------------