code:
$(document).ready(function() {

    $('#config-text').keyup(function() {
      eval($(this).val());
    });

    $('.configurator input, .configurator select').change(function() {
      updateConfig();
    });

    $('.demo i').click(function() {
      $(this).parent().find('input').click();
    });

    $('#startDate').daterangepicker({
      singleDatePicker: true,
      startDate: moment().subtract(6, 'days')
    });

    $('#endDate').daterangepicker({
      singleDatePicker: true,
      startDate: moment()
    });

    //updateConfig();

    function updateConfig() {
      var options = {};

      if ($('#singleDatePicker').is(':checked'))
        options.singleDatePicker = true;

      if ($('#showDropdowns').is(':checked'))
        options.showDropdowns = true;

      if ($('#minYear').val().length && $('#minYear').val() != 1)
        options.minYear = parseInt($('#minYear').val(), 10);

      if ($('#maxYear').val().length && $('#maxYear').val() != 1)
        options.maxYear = parseInt($('#maxYear').val(), 10);

      if ($('#showWeekNumbers').is(':checked'))
        options.showWeekNumbers = true;

      if ($('#showISOWeekNumbers').is(':checked'))
        options.showISOWeekNumbers = true;

      if ($('#timePicker').is(':checked'))
        options.timePicker = true;

      if ($('#timePicker24Hour').is(':checked'))
        options.timePicker24Hour = true;

      if ($('#timePickerIncrement').val().length && $('#timePickerIncrement').val() != 1)
        options.timePickerIncrement = parseInt($('#timePickerIncrement').val(), 10);

      if ($('#timePickerSeconds').is(':checked'))
        options.timePickerSeconds = true;

      if ($('#autoApply').is(':checked'))
        options.autoApply = true;

      if ($('#maxSpan').is(':checked'))
        options.maxSpan = { days: 7 };

      if ($('#ranges').is(':checked')) {
        options.ranges = {
          'Today': [moment(), moment()],
          'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
          'Last 7 Days': [moment().subtract(6, 'days'), moment()],
          'Last 30 Days': [moment().subtract(29, 'days'), moment()],
          'This Month': [moment().startOf('month'), moment().endOf('month')],
          'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
        };
      }

      if ($('#locale').is(':checked')) {
        options.locale = {
          format: 'MM/DD/YYYY',
          separator: ' - ',
          applyLabel: 'Apply',
          cancelLabel: 'Cancel',
          fromLabel: 'From',
          toLabel: 'To',
          customRangeLabel: 'Custom',
          weekLabel: 'W',
          daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr','Sa'],
          monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
          firstDay: 1
        };
      }

      if (!$('#linkedCalendars').is(':checked'))
        options.linkedCalendars = false;

      if (!$('#autoUpdateInput').is(':checked'))
        options.autoUpdateInput = false;

      if (!$('#showCustomRangeLabel').is(':checked'))
        options.showCustomRangeLabel = false;

      if ($('#alwaysShowCalendars').is(':checked'))
        options.alwaysShowCalendars = true;

      if ($('#parentEl').val().length)
        options.parentEl = $('#parentEl').val();

      if ($('#startDate').val().length)
        options.startDate = $('#startDate').val();

      if ($('#endDate').val().length)
        options.endDate = $('#endDate').val();

      if ($('#minDate').val().length)
        options.minDate = $('#minDate').val();

      if ($('#maxDate').val().length)
        options.maxDate = $('#maxDate').val();

      if ($('#opens').val().length && $('#opens').val() != 'right')
        options.opens = $('#opens').val();

      if ($('#drops').val().length && $('#drops').val() != 'down')
        options.drops = $('#drops').val();

      if ($('#buttonClasses').val().length && $('#buttonClasses').val() != 'btn btn-sm')
        options.buttonClasses = $('#buttonClasses').val();

      if ($('#applyButtonClasses').val().length && $('#applyButtonClasses').val() != 'btn-primary')
        options.applyButtonClasses = $('#applyButtonClasses').val();

      if ($('#cancelButtonClasses').val().length && $('#cancelButtonClasses').val() != 'btn-default')
        options.cancelClass = $('#cancelButtonClasses').val();

      $('#config-demo').daterangepicker(options, function(start, end, label) { console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')'); });

      if (typeof options.ranges !== 'undefined') {
        options.ranges = {};
      }

      var option_text = JSON.stringify(options, null, '    ');

      var replacement = "ranges: {\n"
          + "        'Today': [moment(), moment()],\n"
          + "        'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],\n"
          + "        'Last 7 Days': [moment().subtract(6, 'days'), moment()],\n"
          + "        'Last 30 Days': [moment().subtract(29, 'days'), moment()],\n"
          + "        'This Month': [moment().startOf('month'), moment().endOf('month')],\n"
          + "        'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]\n"
          + "    }";
      option_text = option_text.replace(new RegExp('"ranges"\: \{\}', 'g'), replacement);

      $('#config-text').val("$('#demo').daterangepicker(" + option_text + ", function(start, end, label) {\n  console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')');\n});");

    }

    $(window).scroll(function (event) {
        var scroll = $(window).scrollTop();
        if (scroll > 180) {
          $('.leftcol').css('position', 'fixed');
          $('.leftcol').css('top', '10px');
        } else {
          $('.leftcol').css('position', 'absolute');
          $('.leftcol').css('top', '180px');
        }
    });

    var bg = new Trianglify({
      x_colors: ["#e1f3fd", "#eeeeee", "#407dbf"],
      y_colors: 'match_x',
      width: document.body.clientWidth,
      height: 150,
      stroke_width: 0,
      cell_size: 20
    });

    $('#jumbo').css('background-image', 'url(' + bg.png() + ')');

});


code:
<!DOCTYPE html>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>Date Range Picker — JavaScript Date & Time Picker Library</title>

        <link rel="stylesheet" type="text/css" href="daterangepicker.css" />

        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">

        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" crossorigin="anonymous">

        <link rel="stylesheet" type="text/css" href="website.css" />

        <meta name="google-site-verification" content="1fP-Eo9i1ozV4MUlqZv2vsLv1r7tvYutUb6i38v0_vg" />

  Date Range Picker

  Improvely

  W3Counter

  Website Goodies

Date Range Picker

                            A JavaScript component for choosing date ranges,
                            dates and times.

                              View on GitHub

                              Download ZIP

                        Getting Started
                        Examples
                        Options, Methods & Events
                        Configuration Generator
                        License & Comments

Originally created for reports at Improvely, the Date Range Picker can be attached to any webpage element to pop up two calendars for selecting dates, times, or predefined ranges like "Last 30 Days".

Getting Started

                        To get started, include jQuery, Moment.js and Date Range Picker's files in your webpage:

                        Then attach a date range picker to whatever you want to trigger it:

                            Code:

                            Produces:
                            <input type="text" name="dates" class="form-control pull-right" />

                        You can customize Date Range Picker with options, and get notified when the user chooses new dates by providing a callback function.

Examples

Simple Date Range Picker With a Callback

                                Code:

                                Produces:
                                <input type="text" name="daterange" class="form-control" value="1/01/2018 - 01/15/2018" />

Date Range Picker With Times

                                Code:

                                Produces:
                                <input type="text" name="datetimes" class="form-control pull-right" />

Single Date Picker

                                Code:

                                Produces:
                                <input type="text" name="birthday" class="form-control pull-right" value="10/24/1984" />

Predefined Date Ranges

                                Code:

                                Produces:

Input Initially Empty

                                Code:

                                Produces:
                                <input type="text" name="datefilter" class="form-control pull-right" value="" />

Options

                            startDate (Date or string) The beginning date of the initially selected date range. If you provide a string, it must match the date format string set in your locale setting.

                            endDate: (Date or string) The end date of the initially selected date range.

                            minDate: (Date or string) The earliest date a user may select.

                            maxDate: (Date or string) The latest date a user may select.

                            maxSpan: (object) The maximum span between the selected start and end dates. Check off maxSpan in the configuration generator for an example of how to use this. You can provide any object the moment library would let you add to a date.

                            showDropdowns: (true/false) Show year and month select boxes above calendars to jump to a specific month and year.

                            minYear: (number) The minimum year shown in the dropdowns when showDropdowns is set to true.

                            maxYear: (number) The maximum year shown in the dropdowns when showDropdowns is set to true.

                            showWeekNumbers: (true/false) Show localized week numbers at the start of each week on the calendars.

                            showISOWeekNumbers: (true/false) Show ISO week numbers at the start of each week on the calendars.

                            timePicker: (true/false) Adds select boxes to choose times in addition to dates.

                            timePickerIncrement: (number) Increment of the minutes selection list for times (i.e. 30 to allow only selection of times ending in 0 or 30).

                            timePicker24Hour: (true/false) Use 24-hour instead of 12-hour times, removing the AM/PM selection.

                            timePickerSeconds: (true/false) Show seconds in the timePicker.

                            ranges: (object) Set predefined date ranges the user can select from. Each key is the label for the range, and its value an array with two dates representing the bounds of the range. Click ranges in the configuration generator for examples.

                            showCustomRangeLabel: (true/false) Displays "Custom Range" at
                            the end of the list of predefined ranges, when the ranges option is used.
                            This option will be highlighted whenever the current date range selection does not match one of the predefined ranges. Clicking it will display the calendars to select a new range.

                            alwaysShowCalendars: (true/false) Normally, if you use the ranges option to specify pre-defined date ranges, calendars for choosing a custom date range are not shown until the user clicks "Custom Range". When this option is set to true, the calendars for choosing a custom date range are always shown instead.

                            opens: ('left'/'right'/'center') Whether the picker appears aligned to the left, to the right, or centered under the HTML element it's attached to.

                            drops: ('down'/'up') Whether the picker appears below (default) or above the HTML element it's attached to.

                            buttonClasses: (string) CSS class names that will be added to both the apply and cancel buttons.

                            applyButtonClasses: (string) CSS class names that will be added only to the apply button.

                            cancelButtonClasses: (string) CSS class names that will be added only to the cancel button.

                            locale: (object) Allows you to provide localized strings for buttons and labels, customize the date format, and change the first day of week for the calendars.
                            Check off locale in the configuration generator to see how
                            to customize these options.

                            singleDatePicker: (true/false) Show only a single calendar to choose one date, instead of a range picker with two calendars. The start and end dates provided to your callback will be the same single date chosen.

                            autoApply: (true/false) Hide the apply and cancel buttons, and automatically apply a new date range as soon as two dates are clicked.

                            linkedCalendars: (true/false) When enabled, the two calendars displayed will always be for two sequential months (i.e. January and February), and both will be advanced when clicking the left or right arrows above the calendars. When disabled, the two calendars can be individually advanced and display any month/year.

                            isInvalidDate: (function) A function that is passed each date in the two
                            calendars before they are displayed, and may return true or false to indicate whether
                            that date should be available for selection or not.

                            isCustomDate: (function) A function that is passed each date in the two
                            calendars before they are displayed, and may return a string or array of CSS class names
                            to apply to that date's calendar cell.

                            autoUpdateInput: (true/false) Indicates whether the date range picker should
                            automatically update the value of the <input> element it's attached to at initialization and when the selected dates change.

                            parentEl: (string) jQuery selector of the parent element that the date range picker will be added to, if not provided this will be 'body'

Methods

                        You can programmatically update the startDate and endDate
                        in the picker using the setStartDate and setEndDate methods.
                        You can access the Date Range Picker object and its functions and properties through
                        data properties of the element you attached it to.

                            setStartDate(Date or string): Sets the date range picker's currently selected start date to the provided date

                            setEndDate(Date or string): Sets the date range picker's currently selected end date to the provided date

Example usage:

Events

                        Several events are triggered on the element you attach the picker to, which you can listen for.

                            show.daterangepicker: Triggered when the picker is shown

                            hide.daterangepicker: Triggered when the picker is hidden

                            showCalendar.daterangepicker: Triggered when the calendar(s) are shown

                            hideCalendar.daterangepicker: Triggered when the calendar(s) are hidden

                            apply.daterangepicker: Triggered when the apply button is clicked,
                            or when a predefined range is clicked

                            cancel.daterangepicker: Triggered when the cancel button is clicked

                        Some applications need a "clear" instead of a "cancel" functionality, which can be achieved by changing the button label and watching for the cancel event:

                        While passing in a callback to the constructor is the easiest way to listen for changes in the selected date range, you can also do something every time the apply button is clicked even if the selection hasn't changed:

Configuration Generator

                      <form>

                                parentEl
                                <input type="text" class="form-control" id="parentEl" value="" placeholder="body">

                                startDate
                                <input type="text" class="form-control" id="startDate" value="07/01/2017">

                                endDate
                                <input type="text" class="form-control" id="endDate" value="07/15/2017">

                                minDate
                                <input type="text" class="form-control" id="minDate" value="" placeholder="MM/DD/YYYY">

                                maxDate
                                <input type="text" class="form-control" id="maxDate" value="" placeholder="MM/DD/YYYY">

                                opens
                                <select id="opens" class="form-control">
                                  <option value="right" selected>right</option>
                                  <option value="left">left</option>
                                  <option value="center">center</option>
                                </select>

                                drops
                                <select id="drops" class="form-control">
                                  <option value="down" selected>down</option>
                                  <option value="up">up</option>
                                </select>

                                  <input type="checkbox" id="showDropdowns"> showDropdowns

                                minYear
                                <input type="text" class="form-control" id="minYear" value="">

                                maxYear
                                <input type="text" class="form-control" id="maxYear" value="">

                                  <input type="checkbox" id="showWeekNumbers"> showWeekNumbers

                                  <input type="checkbox" id="showISOWeekNumbers"> showISOWeekNumbers

                                  <input type="checkbox" id="singleDatePicker"> singleDatePicker

                                  <input type="checkbox" id="timePicker"> timePicker

                                  <input type="checkbox" id="timePicker24Hour"> timePicker24Hour

                                timePickerIncrement (in minutes)
                                <input type="text" class="form-control" id="timePickerIncrement" value="1">

                                  <input type="checkbox" id="timePickerSeconds"> timePickerSeconds

                                  <input type="checkbox" id="maxSpan"> maxSpan (example value)

                                  <input type="checkbox" id="locale"> locale (example settings)

                                  <input type="checkbox" id="autoApply"> autoApply

                                buttonClasses
                                <input type="text" class="form-control" id="buttonClasses" value="btn btn-sm">

                                applyButtonClasses
                                <input type="text" class="form-control" id="applyButtonClasses" value="btn-primary">

                                cancelButtonClasses
                                <input type="text" class="form-control" id="cancelButtonClasses" value="btn-default">

                                  <input type="checkbox" id="ranges"> ranges (with example predefined ranges)

                                  <input type="checkbox" id="alwaysShowCalendars"> alwaysShowCalendars

                                  <input type="checkbox" id="showCustomRangeLabel" checked="checked"> showCustomRangeLabel

                                  <input type="checkbox" id="linkedCalendars" checked="checked"> linkedCalendars

                                  <input type="checkbox" id="autoUpdateInput" checked="checked"> autoUpdateInput

                      </form>

Your Date Range Picker

                            <input type="text" id="config-demo" class="form-control">

Your Configuration to Copy

                          <textarea id="config-text" style="height: 300px; width: 100%; padding: 10px"></textarea>

License

The MIT License (MIT)

Copyright (c) 2012-2019 Dan Grossman

                        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.

Comments

                    Please enable JavaScript to view the comments powered by Disqus.

            Copyright © 2012-2018 Dan Grossman.

repo_name: tkkonline/php

license: mit


code:
body {
    font-size: 15px;
    line-height: 1.6em;
    position: relative;
    margin: 0;
}

.navbar .nav-item {
    padding: 8px 0 8px 20px;
}

.navbar .nav-link {
    font-weight: bold;
    font-size: 14px;
    padding: 0;
}

.navbar-expand-sm .navbar-nav .nav-link {
    padding: 0;
}

.well {
    background: #f5f5f5;
    border-radius: 4px;
    padding: 20px;
}

h1 {
    font-size: 20px;
    margin-bottom: 1em;
    padding-bottom: 5px;
    border-bottom: 1px dotted #08c;
}

h1:before {
    content: '#';
    color: #666;
    position: relative;
    padding-right: 5px;
}

h2 {
    padding: 0;
    margin: 20px 0 0 0;
    font-size: 18px;
}

h2 a {
    color: #444;
    display: block;
    background: #eee;
    padding: 8px 12px;
    margin-bottom: 0;
    cursor: default;
    text-decoration: none;
}

input.form-control {
    font-size: 14px;
}

.collapsable {
    border: 1px solid #eee;
    padding: 12px;
    display: block;
}

label {
    font-size: 13px;
    font-weight: bold;
}

.gist {
   overflow: auto;
}

.gist .blob-wrapper.data {
   max-height: 350px;
   overflow: auto;
}

.list-group-item {
    padding: 4px 0;
    border: 0;
    font-size: 16px;
}

.leftcol {
    position: absolute;
    top: 180px;
}

.rightcol {
    max-width: 950px;
}

.container {
    max-width: 1300px;
}

@media (min-width: 980px) {
    .rightcol {
        margin-left: 320px;
    }
}

p, pre {
    margin-bottom: 2em;
}

ul.nobullets {
    margin: 0;
    padding: 0;
    list-style: none;
}
ul.nobullets li {
    padding-bottom: 1em;
    margin-bottom: 1em;
    border-bottom: 1px dotted #ddd;
}

input[type="text"] {
    padding: 6px;
    width: 100%;
    border-radius: 4px;
}

#footer {
    background: #222;
    margin-top: 80px;
    padding: 10px;
    color: #fff;
    text-align: center;
}
#footer a:link, #footer a:visited {
    color: #fff;
    border-bottom: 1px dotted #fff;
}
#jumbo {
    background: #c1deef;
    color: #000;
    padding: 20px 0;
    margin-bottom: 20px;
}

#jumbo h1 {
    font-size: 28px;
}
#jumbo .btn {
    border-radius: 0;
    font-size: 16px;
}


code:
/*!
 * Lightbox for Bootstrap by @ashleydw
 * https://github.com/ashleydw/lightbox
 *
 * License: https://github.com/ashleydw/lightbox/blob/master/LICENSE
 */
+function ($) {

'use strict';

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

var Lightbox = (function ($) {

	var NAME = 'ekkoLightbox';
	var JQUERY_NO_CONFLICT = $.fn[NAME];

	var Default = {
		title: '',
		footer: '',
		maxWidth: 9999,
		maxHeight: 9999,
		showArrows: true, //display the left / right arrows or not
		wrapping: true, //if true, gallery loops infinitely
		type: null, //force the lightbox into image / youtube mode. if null, or not image|youtube|vimeo; detect it
		alwaysShowClose: false, //always show the close button, even if there is no title
		loadingMessage: '

', // http://tobiasahlin.com/spinkit/
		leftArrow: '❮',
		rightArrow: '❯',
		strings: {
			close: 'Close',
			fail: 'Failed to load image:',
			type: 'Could not detect remote target type. Force the type using data-type'
		},
		doc: document, // if in an iframe can specify top.document
		onShow: function onShow() {},
		onShown: function onShown() {},
		onHide: function onHide() {},
		onHidden: function onHidden() {},
		onNavigate: function onNavigate() {},
		onContentLoaded: function onContentLoaded() {}
	};

	var Lightbox = (function () {
		_createClass(Lightbox, null, [{
			key: 'Default',

			/**
       Class properties:
   	 _$element: null -> the  element currently being displayed
    _$modal: The bootstrap modal generated
       _$modalDialog: The .modal-dialog
       _$modalContent: The .modal-content
       _$modalBody: The .modal-body
       _$modalHeader: The .modal-header
       _$modalFooter: The .modal-footer
    _$lightboxContainerOne: Container of the first lightbox element
    _$lightboxContainerTwo: Container of the second lightbox element
    _$lightboxBody: First element in the container
    _$modalArrows: The overlayed arrows container
   	 _$galleryItems: Other 's available for this gallery
    _galleryName: Name of the current data('gallery') showing
    _galleryIndex: The current index of the _$galleryItems being shown
   	 _config: {} the options for the modal
    _modalId: unique id for the current lightbox
    _padding / _border: CSS properties for the modal container; these are used to calculate the available space for the content
   	 */

			get: function get() {
				return Default;
			}
		}]);

		function Lightbox($element, config) {
			var _this = this;

			_classCallCheck(this, Lightbox);

			this._config = $.extend({}, Default, config);
			this._$modalArrows = null;
			this._galleryIndex = 0;
			this._galleryName = null;
			this._padding = null;
			this._border = null;
			this._titleIsShown = false;
			this._footerIsShown = false;
			this._wantedWidth = 0;
			this._wantedHeight = 0;
			this._touchstartX = 0;
			this._touchendX = 0;

			this._modalId = 'ekkoLightbox-' + Math.floor(Math.random() * 1000 + 1);
			this._$element = $element instanceof jQuery ? $element : $($element);

			this._isBootstrap3 = $.fn.modal.Constructor.VERSION[0] == 3;

			var h4 = '
' + (this._config.title || " ") + '
';
			var btn = '<button type="button" class="close" data-dismiss="modal" aria-label="' + this._config.strings.close + '">×</button>';

			var header = '
' + (this._isBootstrap3 ? btn + h4 : h4 + btn) + '
';
			var footer = '
' + (this._config.footer || " ") + '
';
			var body = '

';
			var dialog = '

' + header + body + footer + '

';
			$(this._config.doc.body).append('
' + dialog + '
');

			this._$modal = $('#' + this._modalId, this._config.doc);
			this._$modalDialog = this._$modal.find('.modal-dialog').first();
			this._$modalContent = this._$modal.find('.modal-content').first();
			this._$modalBody = this._$modal.find('.modal-body').first();
			this._$modalHeader = this._$modal.find('.modal-header').first();
			this._$modalFooter = this._$modal.find('.modal-footer').first();

			this._$lightboxContainer = this._$modalBody.find('.ekko-lightbox-container').first();
			this._$lightboxBodyOne = this._$lightboxContainer.find('> div:first-child').first();
			this._$lightboxBodyTwo = this._$lightboxContainer.find('> div:last-child').first();

			this._border = this._calculateBorders();
			this._padding = this._calculatePadding();

			this._galleryName = this._$element.data('gallery');
			if (this._galleryName) {
				this._$galleryItems = $(document.body).find('*[data-gallery="' + this._galleryName + '"]');
				this._galleryIndex = this._$galleryItems.index(this._$element);
				$(document).on('keydown.ekkoLightbox', this._navigationalBinder.bind(this));

				// add the directional arrows to the modal
				if (this._config.showArrows && this._$galleryItems.length > 1) {
					this._$lightboxContainer.append('
' + this._config.leftArrow + '' + this._config.rightArrow + '
');
					this._$modalArrows = this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay').first();
					this._$lightboxContainer.on('click', 'a:first-child', function (event) {
						event.preventDefault();
						return _this.navigateLeft();
					});
					this._$lightboxContainer.on('click', 'a:last-child', function (event) {
						event.preventDefault();
						return _this.navigateRight();
					});
					this.updateNavigation();
				}
			}

			this._$modal.on('show.bs.modal', this._config.onShow.bind(this)).on('shown.bs.modal', function () {
				_this._toggleLoading(true);
				_this._handle();
				return _this._config.onShown.call(_this);
			}).on('hide.bs.modal', this._config.onHide.bind(this)).on('hidden.bs.modal', function () {
				if (_this._galleryName) {
					$(document).off('keydown.ekkoLightbox');
					$(window).off('resize.ekkoLightbox');
				}
				_this._$modal.remove();
				return _this._config.onHidden.call(_this);
			}).modal(this._config);

			$(window).on('resize.ekkoLightbox', function () {
				_this._resize(_this._wantedWidth, _this._wantedHeight);
			});
			this._$lightboxContainer.on('touchstart', function () {
				_this._touchstartX = event.changedTouches[0].screenX;
			}).on('touchend', function () {
				_this._touchendX = event.changedTouches[0].screenX;
				_this._swipeGesure();
			});
		}

		_createClass(Lightbox, [{
			key: 'element',
			value: function element() {
				return this._$element;
			}
		}, {
			key: 'modal',
			value: function modal() {
				return this._$modal;
			}
		}, {
			key: 'navigateTo',
			value: function navigateTo(index) {

				if (index < 0 || index > this._$galleryItems.length - 1) return this;

				this._galleryIndex = index;

				this.updateNavigation();

				this._$element = $(this._$galleryItems.get(this._galleryIndex));
				this._handle();
			}
		}, {
			key: 'navigateLeft',
			value: function navigateLeft() {

				if (!this._$galleryItems) return;

				if (this._$galleryItems.length === 1) return;

				if (this._galleryIndex === 0) {
					if (this._config.wrapping) this._galleryIndex = this._$galleryItems.length - 1;else return;
				} else //circular
					this._galleryIndex--;

				this._config.onNavigate.call(this, 'left', this._galleryIndex);
				return this.navigateTo(this._galleryIndex);
			}
		}, {
			key: 'navigateRight',
			value: function navigateRight() {

				if (!this._$galleryItems) return;

				if (this._$galleryItems.length === 1) return;

				if (this._galleryIndex === this._$galleryItems.length - 1) {
					if (this._config.wrapping) this._galleryIndex = 0;else return;
				} else //circular
					this._galleryIndex++;

				this._config.onNavigate.call(this, 'right', this._galleryIndex);
				return this.navigateTo(this._galleryIndex);
			}
		}, {
			key: 'updateNavigation',
			value: function updateNavigation() {
				if (!this._config.wrapping) {
					var $nav = this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay');
					if (this._galleryIndex === 0) $nav.find('a:first-child').addClass('disabled');else $nav.find('a:first-child').removeClass('disabled');

					if (this._galleryIndex === this._$galleryItems.length - 1) $nav.find('a:last-child').addClass('disabled');else $nav.find('a:last-child').removeClass('disabled');
				}
			}
		}, {
			key: 'close',
			value: function close() {
				return this._$modal.modal('hide');
			}

			// helper private methods
		}, {
			key: '_navigationalBinder',
			value: function _navigationalBinder(event) {
				event = event || window.event;
				if (event.keyCode === 39) return this.navigateRight();
				if (event.keyCode === 37) return this.navigateLeft();
			}

			// type detection private methods
		}, {
			key: '_detectRemoteType',
			value: function _detectRemoteType(src, type) {

				type = type || false;

				if (!type && this._isImage(src)) type = 'image';
				if (!type && this._getYoutubeId(src)) type = 'youtube';
				if (!type && this._getVimeoId(src)) type = 'vimeo';
				if (!type && this._getInstagramId(src)) type = 'instagram';

				if (!type || ['image', 'youtube', 'vimeo', 'instagram', 'video', 'url'].indexOf(type) < 0) type = 'url';

				return type;
			}
		}, {
			key: '_isImage',
			value: function _isImage(string) {
				return string && string.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
			}
		}, {
			key: '_containerToUse',
			value: function _containerToUse() {
				var _this2 = this;

				// if currently showing an image, fade it out and remove
				var $toUse = this._$lightboxBodyTwo;
				var $current = this._$lightboxBodyOne;

				if (this._$lightboxBodyTwo.hasClass('in')) {
					$toUse = this._$lightboxBodyOne;
					$current = this._$lightboxBodyTwo;
				}

				$current.removeClass('in show');
				setTimeout(function () {
					if (!_this2._$lightboxBodyTwo.hasClass('in')) _this2._$lightboxBodyTwo.empty();
					if (!_this2._$lightboxBodyOne.hasClass('in')) _this2._$lightboxBodyOne.empty();
				}, 500);

				$toUse.addClass('in show');
				return $toUse;
			}
		}, {
			key: '_handle',
			value: function _handle() {

				var $toUse = this._containerToUse();
				this._updateTitleAndFooter();

				var currentRemote = this._$element.attr('data-remote') || this._$element.attr('href');
				var currentType = this._detectRemoteType(currentRemote, this._$element.attr('data-type') || false);

				if (['image', 'youtube', 'vimeo', 'instagram', 'video', 'url'].indexOf(currentType) < 0) return this._error(this._config.strings.type);

				switch (currentType) {
					case 'image':
						this._preloadImage(currentRemote, $toUse);
						this._preloadImageByIndex(this._galleryIndex, 3);
						break;
					case 'youtube':
						this._showYoutubeVideo(currentRemote, $toUse);
						break;
					case 'vimeo':
						this._showVimeoVideo(this._getVimeoId(currentRemote), $toUse);
						break;
					case 'instagram':
						this._showInstagramVideo(this._getInstagramId(currentRemote), $toUse);
						break;
					case 'video':
						this._showHtml5Video(currentRemote, $toUse);
						break;
					default:
						// url
						this._loadRemoteContent(currentRemote, $toUse);
						break;
				}

				return this;
			}
		}, {
			key: '_getYoutubeId',
			value: function _getYoutubeId(string) {
				if (!string) return false;
				var matches = string.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);
				return matches && matches[2].length === 11 ? matches[2] : false;
			}
		}, {
			key: '_getVimeoId',
			value: function _getVimeoId(string) {
				return string && string.indexOf('vimeo') > 0 ? string : false;
			}
		}, {
			key: '_getInstagramId',
			value: function _getInstagramId(string) {
				return string && string.indexOf('instagram') > 0 ? string : false;
			}

			// layout private methods
		}, {
			key: '_toggleLoading',
			value: function _toggleLoading(show) {
				show = show || false;
				if (show) {
					this._$modalDialog.css('display', 'none');
					this._$modal.removeClass('in show');
					$('.modal-backdrop').append(this._config.loadingMessage);
				} else {
					this._$modalDialog.css('display', 'block');
					this._$modal.addClass('in show');
					$('.modal-backdrop').find('.ekko-lightbox-loader').remove();
				}
				return this;
			}
		}, {
			key: '_calculateBorders',
			value: function _calculateBorders() {
				return {
					top: this._totalCssByAttribute('border-top-width'),
					right: this._totalCssByAttribute('border-right-width'),
					bottom: this._totalCssByAttribute('border-bottom-width'),
					left: this._totalCssByAttribute('border-left-width')
				};
			}
		}, {
			key: '_calculatePadding',
			value: function _calculatePadding() {
				return {
					top: this._totalCssByAttribute('padding-top'),
					right: this._totalCssByAttribute('padding-right'),
					bottom: this._totalCssByAttribute('padding-bottom'),
					left: this._totalCssByAttribute('padding-left')
				};
			}
		}, {
			key: '_totalCssByAttribute',
			value: function _totalCssByAttribute(attribute) {
				return parseInt(this._$modalDialog.css(attribute), 10) + parseInt(this._$modalContent.css(attribute), 10) + parseInt(this._$modalBody.css(attribute), 10);
			}
		}, {
			key: '_updateTitleAndFooter',
			value: function _updateTitleAndFooter() {
				var title = this._$element.data('title') || "";
				var caption = this._$element.data('footer') || "";

				this._titleIsShown = false;
				if (title || this._config.alwaysShowClose) {
					this._titleIsShown = true;
					this._$modalHeader.css('display', '').find('.modal-title').html(title || " ");
				} else this._$modalHeader.css('display', 'none');

				this._footerIsShown = false;
				if (caption) {
					this._footerIsShown = true;
					this._$modalFooter.css('display', '').html(caption);
				} else this._$modalFooter.css('display', 'none');

				return this;
			}
		}, {
			key: '_showYoutubeVideo',
			value: function _showYoutubeVideo(remote, $containerForElement) {
				var id = this._getYoutubeId(remote);
				var query = remote.indexOf('&') > 0 ? remote.substr(remote.indexOf('&')) : '';
				var width = this._$element.data('width') || 560;
				var height = this._$element.data('height') || width / (560 / 315);
				return this._showVideoIframe('//www.youtube.com/embed/' + id + '?badge=0&autoplay=1&html5=1' + query, width, height, $containerForElement);
			}
		}, {
			key: '_showVimeoVideo',
			value: function _showVimeoVideo(id, $containerForElement) {
				var width = this._$element.data('width') || 500;
				var height = this._$element.data('height') || width / (560 / 315);
				return this._showVideoIframe(id + '?autoplay=1', width, height, $containerForElement);
			}
		}, {
			key: '_showInstagramVideo',
			value: function _showInstagramVideo(id, $containerForElement) {
				// instagram load their content into iframe's so this can be put straight into the element
				var width = this._$element.data('width') || 612;
				var height = width + 80;
				id = id.substr(-1) !== '/' ? id + '/' : id; // ensure id has trailing slash
				$containerForElement.html('');
				this._resize(width, height);
				this._config.onContentLoaded.call(this);
				if (this._$modalArrows) //hide the arrows when showing video
					this._$modalArrows.css('display', 'none');
				this._toggleLoading(false);
				return this;
			}
		}, {
			key: '_showVideoIframe',
			value: function _showVideoIframe(url, width, height, $containerForElement) {
				// should be used for videos only. for remote content use loadRemoteContent (data-type=url)
				height = height || width; // default to square
				$containerForElement.html('

');
				this._resize(width, height);
				this._config.onContentLoaded.call(this);
				if (this._$modalArrows) this._$modalArrows.css('display', 'none'); //hide the arrows when showing video
				this._toggleLoading(false);
				return this;
			}
		}, {
			key: '_showHtml5Video',
			value: function _showHtml5Video(url, $containerForElement) {
				// should be used for videos only. for remote content use loadRemoteContent (data-type=url)
				var width = this._$element.data('width') || 560;
				var height = this._$element.data('height') || width / (560 / 315);
				$containerForElement.html('
<video width="' + width + '" height="' + height + '" src="' + url + '" preload="auto" autoplay controls class="embed-responsive-item"></video>
');
				this._resize(width, height);
				this._config.onContentLoaded.call(this);
				if (this._$modalArrows) this._$modalArrows.css('display', 'none'); //hide the arrows when showing video
				this._toggleLoading(false);
				return this;
			}
		}, {
			key: '_loadRemoteContent',
			value: function _loadRemoteContent(url, $containerForElement) {
				var _this3 = this;

				var width = this._$element.data('width') || 560;
				var height = this._$element.data('height') || 560;

				var disableExternalCheck = this._$element.data('disableExternalCheck') || false;
				this._toggleLoading(false);

				// external urls are loading into an iframe
				// local ajax can be loaded into the container itself
				if (!disableExternalCheck && !this._isExternal(url)) {
					$containerForElement.load(url, $.proxy(function () {
						return _this3._$element.trigger('loaded.bs.modal');l;
					}));
				} else {
					$containerForElement.html('');
					this._config.onContentLoaded.call(this);
				}

				if (this._$modalArrows) //hide the arrows when remote content
					this._$modalArrows.css('display', 'none');

				this._resize(width, height);
				return this;
			}
		}, {
			key: '_isExternal',
			value: function _isExternal(url) {
				var match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);
				if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== location.protocol) return true;

				if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(':(' + ({
					"http:": 80,
					"https:": 443
				})[location.protocol] + ')?$'), "") !== location.host) return true;

				return false;
			}
		}, {
			key: '_error',
			value: function _error(message) {
				console.error(message);
				this._containerToUse().html(message);
				this._resize(300, 300);
				return this;
			}
		}, {
			key: '_preloadImageByIndex',
			value: function _preloadImageByIndex(startIndex, numberOfTimes) {

				if (!this._$galleryItems) return;

				var next = $(this._$galleryItems.get(startIndex), false);
				if (typeof next == 'undefined') return;

				var src = next.attr('data-remote') || next.attr('href');
				if (next.attr('data-type') === 'image' || this._isImage(src)) this._preloadImage(src, false);

				if (numberOfTimes > 0) return this._preloadImageByIndex(startIndex + 1, numberOfTimes - 1);
			}
		}, {
			key: '_preloadImage',
			value: function _preloadImage(src, $containerForImage) {
				var _this4 = this;

				$containerForImage = $containerForImage || false;

				var img = new Image();
				if ($containerForImage) {
					(function () {

						// if loading takes > 200ms show a loader
						var loadingTimeout = setTimeout(function () {
							$containerForImage.append(_this4._config.loadingMessage);
						}, 200);

						img.onload = function () {
							if (loadingTimeout) clearTimeout(loadingTimeout);
							loadingTimeout = null;
							var image = $('');
							image.attr('src', img.src);
							image.addClass('img-fluid');

							// backward compatibility for bootstrap v3
							image.css('width', '100%');

							$containerForImage.html(image);
							if (_this4._$modalArrows) _this4._$modalArrows.css('display', ''); // remove display to default to css property

							_this4._resize(img.width, img.height);
							_this4._toggleLoading(false);
							return _this4._config.onContentLoaded.call(_this4);
						};
						img.onerror = function () {
							_this4._toggleLoading(false);
							return _this4._error(_this4._config.strings.fail + ('  ' + src));
						};
					})();
				}

				img.src = src;
				return img;
			}
		}, {
			key: '_swipeGesure',
			value: function _swipeGesure() {
				if (this._touchendX < this._touchstartX) {
					return this.navigateRight();
				}
				if (this._touchendX > this._touchstartX) {
					return this.navigateLeft();
				}
			}
		}, {
			key: '_resize',
			value: function _resize(width, height) {

				height = height || width;
				this._wantedWidth = width;
				this._wantedHeight = height;

				var imageAspecRatio = width / height;

				// if width > the available space, scale down the expected width and height
				var widthBorderAndPadding = this._padding.left + this._padding.right + this._border.left + this._border.right;

				// force 10px margin if window size > 575px
				var addMargin = this._config.doc.body.clientWidth > 575 ? 20 : 0;
				var discountMargin = this._config.doc.body.clientWidth > 575 ? 0 : 20;

				var maxWidth = Math.min(width + widthBorderAndPadding, this._config.doc.body.clientWidth - addMargin, this._config.maxWidth);

				if (width + widthBorderAndPadding > maxWidth) {
					height = (maxWidth - widthBorderAndPadding - discountMargin) / imageAspecRatio;
					width = maxWidth;
				} else width = width + widthBorderAndPadding;

				var headerHeight = 0,
				    footerHeight = 0;

				// as the resize is performed the modal is show, the calculate might fail
				// if so, default to the default sizes
				if (this._footerIsShown) footerHeight = this._$modalFooter.outerHeight(true) || 55;

				if (this._titleIsShown) headerHeight = this._$modalHeader.outerHeight(true) || 67;

				var borderPadding = this._padding.top + this._padding.bottom + this._border.bottom + this._border.top;

				//calculated each time as resizing the window can cause them to change due to Bootstraps fluid margins
				var margins = parseFloat(this._$modalDialog.css('margin-top')) + parseFloat(this._$modalDialog.css('margin-bottom'));

				var maxHeight = Math.min(height, $(window).height() - borderPadding - margins - headerHeight - footerHeight, this._config.maxHeight - borderPadding - headerHeight - footerHeight);

				if (height > maxHeight) {
					// if height > the available height, scale down the width
					width = Math.ceil(maxHeight * imageAspecRatio) + widthBorderAndPadding;
				}

				this._$lightboxContainer.css('height', maxHeight);
				this._$modalDialog.css('flex', 1).css('maxWidth', width);

				var modal = this._$modal.data('bs.modal');
				if (modal) {
					// v4 method is mistakenly protected
					try {
						modal._handleUpdate();
					} catch (Exception) {
						modal.handleUpdate();
					}
				}
				return this;
			}
		}], [{
			key: '_jQueryInterface',
			value: function _jQueryInterface(config) {
				var _this5 = this;

				config = config || {};
				return this.each(function () {
					var $this = $(_this5);
					var _config = $.extend({}, Lightbox.Default, $this.data(), typeof config === 'object' && config);

					new Lightbox(_this5, _config);
				});
			}
		}]);

		return Lightbox;
	})();

	$.fn[NAME] = Lightbox._jQueryInterface;
	$.fn[NAME].Constructor = Lightbox;
	$.fn[NAME].noConflict = function () {
		$.fn[NAME] = JQUERY_NO_CONFLICT;
		return Lightbox._jQueryInterface;
	};

	return Lightbox;
})(jQuery);
//# sourceMappingURL=ekko-lightbox.js.map

}(jQuery);


code:
;(function () {
	'use strict';

	/**
	 * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
	 *
	 * @codingstandard ftlabs-jsv2
	 * @copyright The Financial Times Limited [All Rights Reserved]
	 * @license MIT License (see LICENSE.txt)
	 */

	/*jslint browser:true, node:true*/
	/*global define, Event, Node*/

	/**
	 * Instantiate fast-clicking listeners on the specified layer.
	 *
	 * @constructor
	 * @param {Element} layer The layer to listen on
	 * @param {Object} [options={}] The options to override the defaults
	 */
	function FastClick(layer, options) {
		var oldOnClick;

		options = options || {};

		/**
		 * Whether a click is currently being tracked.
		 *
		 * @type boolean
		 */
		this.trackingClick = false;

		/**
		 * Timestamp for when click tracking started.
		 *
		 * @type number
		 */
		this.trackingClickStart = 0;

		/**
		 * The element being tracked for a click.
		 *
		 * @type EventTarget
		 */
		this.targetElement = null;

		/**
		 * X-coordinate of touch start event.
		 *
		 * @type number
		 */
		this.touchStartX = 0;

		/**
		 * Y-coordinate of touch start event.
		 *
		 * @type number
		 */
		this.touchStartY = 0;

		/**
		 * ID of the last touch, retrieved from Touch.identifier.
		 *
		 * @type number
		 */
		this.lastTouchIdentifier = 0;

		/**
		 * Touchmove boundary, beyond which a click will be cancelled.
		 *
		 * @type number
		 */
		this.touchBoundary = options.touchBoundary || 10;

		/**
		 * The FastClick layer.
		 *
		 * @type Element
		 */
		this.layer = layer;

		/**
		 * The minimum time between tap(touchstart and touchend) events
		 *
		 * @type number
		 */
		this.tapDelay = options.tapDelay || 200;

		/**
		 * The maximum time for a tap
		 *
		 * @type number
		 */
		this.tapTimeout = options.tapTimeout || 700;

		if (FastClick.notNeeded(layer)) {
			return;
		}

		// Some old versions of Android don't have Function.prototype.bind
		function bind(method, context) {
			return function() { return method.apply(context, arguments); };
		}

		var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
		var context = this;
		for (var i = 0, l = methods.length; i < l; i++) {
			context[methods[i]] = bind(context[methods[i]], context);
		}

		// Set up event handlers as required
		if (deviceIsAndroid) {
			layer.addEventListener('mouseover', this.onMouse, true);
			layer.addEventListener('mousedown', this.onMouse, true);
			layer.addEventListener('mouseup', this.onMouse, true);
		}

		layer.addEventListener('click', this.onClick, true);
		layer.addEventListener('touchstart', this.onTouchStart, false);
		layer.addEventListener('touchmove', this.onTouchMove, false);
		layer.addEventListener('touchend', this.onTouchEnd, false);
		layer.addEventListener('touchcancel', this.onTouchCancel, false);

		// Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
		// which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
		// layer when they are cancelled.
		if (!Event.prototype.stopImmediatePropagation) {
			layer.removeEventListener = function(type, callback, capture) {
				var rmv = Node.prototype.removeEventListener;
				if (type === 'click') {
					rmv.call(layer, type, callback.hijacked || callback, capture);
				} else {
					rmv.call(layer, type, callback, capture);
				}
			};

			layer.addEventListener = function(type, callback, capture) {
				var adv = Node.prototype.addEventListener;
				if (type === 'click') {
					adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
						if (!event.propagationStopped) {
							callback(event);
						}
					}), capture);
				} else {
					adv.call(layer, type, callback, capture);
				}
			};
		}

		// If a handler is already declared in the element's onclick attribute, it will be fired before
		// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
		// adding it as listener.
		if (typeof layer.onclick === 'function') {

			// Android browser on at least 3.2 requires a new reference to the function in layer.onclick
			// - the old one won't work if passed to addEventListener directly.
			oldOnClick = layer.onclick;
			layer.addEventListener('click', function(event) {
				oldOnClick(event);
			}, false);
			layer.onclick = null;
		}
	}

	/**
	* Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
	*
	* @type boolean
	*/
	var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;

	/**
	 * Android requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;

	/**
	 * iOS requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;

	/**
	 * iOS 4 requires an exception for select elements.
	 *
	 * @type boolean
	 */
	var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);

	/**
	 * iOS 6.0-7.* requires the target element to be manually derived
	 *
	 * @type boolean
	 */
	var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);

	/**
	 * BlackBerry requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;

	/**
	 * Determine whether a given element requires a native click.
	 *
	 * @param {EventTarget|Element} target Target DOM element
	 * @returns {boolean} Returns true if the element needs a native click
	 */
	FastClick.prototype.needsClick = function(target) {
		switch (target.nodeName.toLowerCase()) {

		// Don't send a synthetic click to disabled inputs (issue #62)
		case 'button':
		case 'select':
		case 'textarea':
			if (target.disabled) {
				return true;
			}

			break;
		case 'input':

			// File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
			if ((deviceIsIOS && target.type === 'file') || target.disabled) {
				return true;
			}

			break;
		case 'label':
		case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
		case 'video':
			return true;
		}

		return (/\bneedsclick\b/).test(target.className);
	};

	/**
	 * Determine whether a given element requires a call to focus to simulate click into element.
	 *
	 * @param {EventTarget|Element} target Target DOM element
	 * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
	 */
	FastClick.prototype.needsFocus = function(target) {
		switch (target.nodeName.toLowerCase()) {
		case 'textarea':
			return true;
		case 'select':
			return !deviceIsAndroid;
		case 'input':
			switch (target.type) {
			case 'button':
			case 'checkbox':
			case 'file':
			case 'image':
			case 'radio':
			case 'submit':
				return false;
			}

			// No point in attempting to focus disabled inputs
			return !target.disabled && !target.readOnly;
		default:
			return (/\bneedsfocus\b/).test(target.className);
		}
	};

	/**
	 * Send a click event to the specified element.
	 *
	 * @param {EventTarget|Element} targetElement
	 * @param {Event} event
	 */
	FastClick.prototype.sendClick = function(targetElement, event) {
		var clickEvent, touch;

		// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
		if (document.activeElement && document.activeElement !== targetElement) {
			document.activeElement.blur();
		}

		touch = event.changedTouches[0];

		// Synthesise a click event, with an extra attribute so it can be tracked
		clickEvent = document.createEvent('MouseEvents');
		clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
		clickEvent.forwardedTouchEvent = true;
		targetElement.dispatchEvent(clickEvent);
	};

	FastClick.prototype.determineEventType = function(targetElement) {

		//Issue #159: Android Chrome Select Box does not open with a synthetic click event
		if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
			return 'mousedown';
		}

		return 'click';
	};

	/**
	 * @param {EventTarget|Element} targetElement
	 */
	FastClick.prototype.focus = function(targetElement) {
		var length;

		// Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
		if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
			length = targetElement.value.length;
			targetElement.setSelectionRange(length, length);
		} else {
			targetElement.focus();
		}
	};

	/**
	 * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
	 *
	 * @param {EventTarget|Element} targetElement
	 */
	FastClick.prototype.updateScrollParent = function(targetElement) {
		var scrollParent, parentElement;

		scrollParent = targetElement.fastClickScrollParent;

		// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
		// target element was moved to another parent.
		if (!scrollParent || !scrollParent.contains(targetElement)) {
			parentElement = targetElement;
			do {
				if (parentElement.scrollHeight > parentElement.offsetHeight) {
					scrollParent = parentElement;
					targetElement.fastClickScrollParent = parentElement;
					break;
				}

				parentElement = parentElement.parentElement;
			} while (parentElement);
		}

		// Always update the scroll top tracker if possible.
		if (scrollParent) {
			scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
		}
	};

	/**
	 * @param {EventTarget} targetElement
	 * @returns {Element|EventTarget}
	 */
	FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {

		// On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
		if (eventTarget.nodeType === Node.TEXT_NODE) {
			return eventTarget.parentNode;
		}

		return eventTarget;
	};

	/**
	 * On touch start, record the position and scroll offset.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchStart = function(event) {
		var targetElement, touch, selection;

		// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
		if (event.targetTouches.length > 1) {
			return true;
		}

		targetElement = this.getTargetElementFromEventTarget(event.target);
		touch = event.targetTouches[0];

		if (deviceIsIOS) {

			// Only trusted events will deselect text on iOS (issue #49)
			selection = window.getSelection();
			if (selection.rangeCount && !selection.isCollapsed) {
				return true;
			}

			if (!deviceIsIOS4) {

				// Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
				// when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
				// with the same identifier as the touch event that previously triggered the click that triggered the alert.
				// Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
				// immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
				// Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
				// which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
				// random integers, it's safe to to continue if the identifier is 0 here.
				if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
					event.preventDefault();
					return false;
				}

				this.lastTouchIdentifier = touch.identifier;

				// If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
				// 1) the user does a fling scroll on the scrollable layer
				// 2) the user stops the fling scroll with another tap
				// then the event.target of the last 'touchend' event will be the element that was under the user's finger
				// when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
				// is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
				this.updateScrollParent(targetElement);
			}
		}

		this.trackingClick = true;
		this.trackingClickStart = event.timeStamp;
		this.targetElement = targetElement;

		this.touchStartX = touch.pageX;
		this.touchStartY = touch.pageY;

		// Prevent phantom clicks on fast double-tap (issue #36)
		if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
			event.preventDefault();
		}

		return true;
	};

	/**
	 * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.touchHasMoved = function(event) {
		var touch = event.changedTouches[0], boundary = this.touchBoundary;

		if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
			return true;
		}

		return false;
	};

	/**
	 * Update the last position.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchMove = function(event) {
		if (!this.trackingClick) {
			return true;
		}

		// If the touch has moved, cancel the click tracking
		if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
			this.trackingClick = false;
			this.targetElement = null;
		}

		return true;
	};

	/**
	 * Attempt to find the labelled control for the given label element.
	 *
	 * @param {EventTarget|HTMLLabelElement} labelElement
	 * @returns {Element|null}
	 */
	FastClick.prototype.findControl = function(labelElement) {

		// Fast path for newer browsers supporting the HTML5 control attribute
		if (labelElement.control !== undefined) {
			return labelElement.control;
		}

		// All browsers under test that support touch events also support the HTML5 htmlFor attribute
		if (labelElement.htmlFor) {
			return document.getElementById(labelElement.htmlFor);
		}

		// If no for attribute exists, attempt to retrieve the first labellable descendant element
		// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
		return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
	};

	/**
	 * On touch end, determine whether to send a click event at once.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchEnd = function(event) {
		var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;

		if (!this.trackingClick) {
			return true;
		}

		// Prevent phantom clicks on fast double-tap (issue #36)
		if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
			this.cancelNextClick = true;
			return true;
		}

		if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
			return true;
		}

		// Reset to prevent wrong click cancel on input (issue #156).
		this.cancelNextClick = false;

		this.lastClickTime = event.timeStamp;

		trackingClickStart = this.trackingClickStart;
		this.trackingClick = false;
		this.trackingClickStart = 0;

		// On some iOS devices, the targetElement supplied with the event is invalid if the layer
		// is performing a transition or scroll, and has to be re-detected manually. Note that
		// for this to function correctly, it must be called *after* the event target is checked!
		// See issue #57; also filed as rdar://13048589 .
		if (deviceIsIOSWithBadTarget) {
			touch = event.changedTouches[0];

			// In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
			targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
			targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
		}

		targetTagName = targetElement.tagName.toLowerCase();
		if (targetTagName === 'label') {
			forElement = this.findControl(targetElement);
			if (forElement) {
				this.focus(targetElement);
				if (deviceIsAndroid) {
					return false;
				}

				targetElement = forElement;
			}
		} else if (this.needsFocus(targetElement)) {

			// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
			// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
			if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
				this.targetElement = null;
				return false;
			}

			this.focus(targetElement);
			this.sendClick(targetElement, event);

			// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
			// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
			if (!deviceIsIOS || targetTagName !== 'select') {
				this.targetElement = null;
				event.preventDefault();
			}

			return false;
		}

		if (deviceIsIOS && !deviceIsIOS4) {

			// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
			// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
			scrollParent = targetElement.fastClickScrollParent;
			if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
				return true;
			}
		}

		// Prevent the actual click from going though - unless the target node is marked as requiring
		// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
		if (!this.needsClick(targetElement)) {
			event.preventDefault();
			this.sendClick(targetElement, event);
		}

		return false;
	};

	/**
	 * On touch cancel, stop tracking the click.
	 *
	 * @returns {void}
	 */
	FastClick.prototype.onTouchCancel = function() {
		this.trackingClick = false;
		this.targetElement = null;
	};

	/**
	 * Determine mouse events which should be permitted.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onMouse = function(event) {

		// If a target element was never set (because a touch event was never fired) allow the event
		if (!this.targetElement) {
			return true;
		}

		if (event.forwardedTouchEvent) {
			return true;
		}

		// Programmatically generated events targeting a specific element should be permitted
		if (!event.cancelable) {
			return true;
		}

		// Derive and check the target element to see whether the mouse event needs to be permitted;
		// unless explicitly enabled, prevent non-touch click events from triggering actions,
		// to prevent ghost/doubleclicks.
		if (!this.needsClick(this.targetElement) || this.cancelNextClick) {

			// Prevent any user-added listeners declared on FastClick element from being fired.
			if (event.stopImmediatePropagation) {
				event.stopImmediatePropagation();
			} else {

				// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
				event.propagationStopped = true;
			}

			// Cancel the event
			event.stopPropagation();
			event.preventDefault();

			return false;
		}

		// If the mouse event is permitted, return true for the action to go through.
		return true;
	};

	/**
	 * On actual clicks, determine whether this is a touch-generated click, a click action occurring
	 * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
	 * an actual click which should be permitted.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onClick = function(event) {
		var permitted;

		// It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
		if (this.trackingClick) {
			this.targetElement = null;
			this.trackingClick = false;
			return true;
		}

		// Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
		if (event.target.type === 'submit' && event.detail === 0) {
			return true;
		}

		permitted = this.onMouse(event);

		// Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
		if (!permitted) {
			this.targetElement = null;
		}

		// If clicks are permitted, return true for the action to go through.
		return permitted;
	};

	/**
	 * Remove all FastClick's event listeners.
	 *
	 * @returns {void}
	 */
	FastClick.prototype.destroy = function() {
		var layer = this.layer;

		if (deviceIsAndroid) {
			layer.removeEventListener('mouseover', this.onMouse, true);
			layer.removeEventListener('mousedown', this.onMouse, true);
			layer.removeEventListener('mouseup', this.onMouse, true);
		}

		layer.removeEventListener('click', this.onClick, true);
		layer.removeEventListener('touchstart', this.onTouchStart, false);
		layer.removeEventListener('touchmove', this.onTouchMove, false);
		layer.removeEventListener('touchend', this.onTouchEnd, false);
		layer.removeEventListener('touchcancel', this.onTouchCancel, false);
	};

	/**
	 * Check whether FastClick is needed.
	 *
	 * @param {Element} layer The layer to listen on
	 */
	FastClick.notNeeded = function(layer) {
		var metaViewport;
		var chromeVersion;
		var blackberryVersion;
		var firefoxVersion;

		// Devices that don't support touch don't need FastClick
		if (typeof window.ontouchstart === 'undefined') {
			return true;
		}

		// Chrome version - zero for other browsers
		chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];

		if (chromeVersion) {

			if (deviceIsAndroid) {
				metaViewport = document.querySelector('meta[name=viewport]');

				if (metaViewport) {
					// Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
					if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
						return true;
					}
					// Chrome 32 and above with width=device-width or less don't need FastClick
					if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
						return true;
					}
				}

			// Chrome desktop doesn't need FastClick (issue #15)
			} else {
				return true;
			}
		}

		if (deviceIsBlackBerry10) {
			blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);

			// BlackBerry 10.3+ does not require Fastclick library.
			// https://github.com/ftlabs/fastclick/issues/251
			if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
				metaViewport = document.querySelector('meta[name=viewport]');

				if (metaViewport) {
					// user-scalable=no eliminates click delay.
					if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
						return true;
					}
					// width=device-width (or less than device-width) eliminates click delay.
					if (document.documentElement.scrollWidth <= window.outerWidth) {
						return true;
					}
				}
			}
		}

		// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
		if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
			return true;
		}

		// Firefox version - zero for other browsers
		firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];

		if (firefoxVersion >= 27) {
			// Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896

			metaViewport = document.querySelector('meta[name=viewport]');
			if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
				return true;
			}
		}

		// IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
		// http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
		if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
			return true;
		}

		return false;
	};

	/**
	 * Factory method for creating a FastClick object
	 *
	 * @param {Element} layer The layer to listen on
	 * @param {Object} [options={}] The options to override the defaults
	 */
	FastClick.attach = function(layer, options) {
		return new FastClick(layer, options);
	};

	if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {

		// AMD. Register as an anonymous module.
		define(function() {
			return FastClick;
		});
	} else if (typeof module !== 'undefined' && module.exports) {
		module.exports = FastClick.attach;
		module.exports.FastClick = FastClick;
	} else {
		window.FastClick = FastClick;
	}
}());


code:
import { Filter } from './types';
/**
 * ActiveFilter represents the currently active filter over
 * the grid.
 *
 * It can be a plain string value or an array of strings.
 */
export default class ActiveFilter {
    private filter;
    constructor(filter: Filter);
    get(): Filter;
    set(targetFilter: Filter): void;
    toggle(targetFilter: string): void;
    private toggleFilter;
}


code:
/**
 * A wrapper class around the window object to manage the
 * resize event.
 *
 * When the user resizes the window, Filterizr needs to trigger
 * a refiltering of the grid so that the grid items can assume
 * their new positions.
 */
export default class BrowserWindow {
    private resizeHandler?;
    constructor();
    private debounceEventHandler;
    destroy(): void;
    setResizeEventHandler(resizeHandler: EventListener): void;
    private removeResizeHandler;
}


code:
import { Destructible } from './types/interfaces';
declare type Receiver = NodeListOf<Element> | Element | Window;
export default class EventReceiver implements Destructible {
    private receiver;
    private eventDictionary;
    constructor(receiver: Receiver);
    on(eventType: string, eventHandler: EventListener): void;
    off(eventType: string): void;
    destroy(): void;
    private removeAllEvents;
}
export {};


code:
import { RawOptionsCallbacks } from './FilterizrOptions/defaultOptions';
import FilterizrOptions from './FilterizrOptions/FilterizrOptions';
import FilterItems from './FilterItems';
/**
 * Resembles the grid of items within Filterizr.
 */
export default class FilterContainer {
    node: Element;
    options: FilterizrOptions;
    filterItems: FilterItems;
    dimensions: {
        width: number;
        height: number;
    };
    private onTransitionEndHandler?;
    constructor(node: Element, options: FilterizrOptions);
    destroy(): void;
    /**
     * Turn the HTML elements in the grid to FilterItem
     * instances and return a collection of them.
     */
    makeFilterItems(options: FilterizrOptions): FilterItems;
    /**
     * Inserts a new item into the grid.
     * @param node - HTML node to instantiate as FilterItem and append to the grid
     * @param options - Filterizr options
     */
    insertItem(node: Element, options: FilterizrOptions): void;
    calculateColumns(): number;
    updateDimensions(): void;
    updateHeight(newHeight: number): void;
    bindEvents(callbacks: RawOptionsCallbacks): void;
    unbindEvents(callbacks: RawOptionsCallbacks): void;
    trigger(eventType: string): void;
    private updateWidth;
}


code:
import { FilterizrState } from '../types';
import FilterizrOptions from '../FilterizrOptions';
import FilterItems from '../FilterItems';
import FilterizrElement from '../FilterizrElement';
import StyledFilterContainer from './StyledFilterContainer';
/**
 * Resembles the grid of items within Filterizr.
 */
export default class FilterContainer extends FilterizrElement {
    filterItems: FilterItems;
    protected styledNode: StyledFilterContainer;
    private _filterizrState;
    constructor(node: Element, options: FilterizrOptions);
    readonly styles: StyledFilterContainer;
    filterizrState: FilterizrState;
    destroy(): void;
    /**
     * Turn the HTML elements in the grid to FilterItem
     * instances and return a collection of them.
     * @throws when no filter items are found in the grid.
     */
    makeFilterItems(options: FilterizrOptions): FilterItems;
    insertItem(node: HTMLElement): void;
    removeItem(node: HTMLElement): void;
    setHeight(newHeight: number): void;
    bindEvents(): void;
    unbindEvents(): void;
}


code:
import StyledFilterizrElement from '../StyledFilterizrElement';
export default class StyledFilterContainer extends StyledFilterizrElement {
    initialize(): void;
    updatePaddings(): void;
    setHeight(newHeight: number): void;
}


code: export { default } from './FilterContainer';


code:
import FilterizrOptions from '../FilterizrOptions';
export declare const makePaddingStyles: (options: FilterizrOptions) => object;
export declare const makeInitialStyles: (options: FilterizrOptions) => object;
export declare const makeHeightStyles: (height: number) => object;


code:
import Filterizr from './Filterizr';
import { Destructible } from './types/interfaces';
export default class FilterControls implements Destructible {
    private filterControls;
    private filterizr;
    private multiFilterControls;
    private searchControls;
    private selector;
    private shuffleControls;
    private sortAscControls;
    private sortDescControls;
    /**
     * @param filterizr keep a ref to the Filterizr object to control actions
     * @param selector selector of controls in case of multiple Filterizr instances
     */
    constructor(filterizr: Filterizr, selector?: string);
    destroy(): void;
    private initialize;
}


code:
import { Dictionary } from './types/interfaces/Dictionary';
import FilterizrOptions from './FilterizrOptions/FilterizrOptions';
export interface Position {
    left: number;
    top: number;
}
/**
 * Resembles an item in the grid of Filterizr.
 */
export default class FilterItem {
    node: Element;
    options: FilterizrOptions;
    dimensions: {
        width: number;
        height: number;
    };
    private data;
    private sortData;
    private index;
    private filteredOut;
    private lastPosition;
    private onTransitionEndHandler;
    constructor(node: Element, index: number, options: FilterizrOptions);
    /**
     * Destroys the FilterItem instance
     */
    destroy(): void;
    /**
     * Filters in a specific FilterItem out of the grid.
     * @param targetPosition the position towards which the element should animate
     * @param cssOptions for the animation
     */
    filterIn(targetPosition: Position, cssOptions: Dictionary): void;
    /**
     * Filters out a specific FilterItem out of the grid.
     * @param cssOptions for the animation
     */
    filterOut(cssOptions: Dictionary): void;
    /**
     * Helper method to calculate the animation delay for a given grid item
     * @param delay in ms
     * @param delayMode can be 'alternate' or 'progressive'
     */
    getTransitionDelay(delay: number, delayMode: 'progressive' | 'alternate'): number;
    /**
     * Returns true if the text contents of the FilterItem match the search term
     * @param searchTerm to look up
     * @return if the innerText matches the term
     */
    contentsMatchSearch(searchTerm: string): boolean;
    /**
     * Recalculates the dimensions of the element and updates them in the state
     */
    updateDimensions(): void;
    /**
     * Returns all categories of the grid items data-category attribute
     * with a regexp regarding all whitespace.
     * @return {String[]} an array of the categories the item belongs to
     */
    getCategories(): string[];
    /**
     * Returns the value of the sort attribute
     * @param sortAttribute "index", "sortData" or custom user data-attribute by which to sort
     */
    getSortAttribute(sortAttribute: string): string | number;
    /**
     * Helper method for the search method of Filterizr
     * @return {String} innerText of the FilterItem in lowercase
     */
    private getContentsLowercase;
    /**
     * Sets up the events related to the FilterItem instance
     */
    private bindEvents;
    /**
     * Removes all events related to the FilterItem instance
     */
    private unbindEvents;
    /**
     * Calculates and returns the transition css property based on options.
     */
    private getTransitionStyle;
    /**
     * Sets the transition css property as an inline style on the FilterItem.
     *
     * The idea here is that during the very first render items should assume
     * their positions directly.
     *
     * Following renders should actually trigger the transitions, which is why
     * we need to delay setting the transition property.
     *
     * Unfortunately, JavaScript code executes on the same thread as the
     * browser's rendering. Everything that needs to be drawn waits for
     * JavaScript execution to complete. Thus, we need to use a setTimeout
     * here to defer setting the transition style at the first rendering cycle.
     */
    private setTransitionStyle;
}


code:
import { Position } from '../types/interfaces';
import FilterizrOptions from '../FilterizrOptions';
import FilterizrElement from '../FilterizrElement';
import StyledFilterItem from './StyledFilterItem';
/**
 * Resembles an item in the grid of Filterizr.
 */
export default class FilterItem extends FilterizrElement {
    protected styledNode: StyledFilterItem;
    private filteredOut;
    private lastPosition;
    private sortData;
    constructor(node: Element, index: number, options: FilterizrOptions);
    readonly styles: StyledFilterItem;
    /**
     * Destroys the FilterItem instance
     */
    destroy(): void;
    /**
     * Filters in a specific FilterItem out of the grid.
     */
    filterIn(targetPosition: Position): void;
    /**
     * Filters out a specific FilterItem out of the grid.
     */
    filterOut(): void;
    /**
     * Returns true if the text contents of the FilterItem match the search term
     * @param searchTerm to look up
     */
    contentsMatchSearch(searchTerm: string): boolean;
    /**
     * Returns all categories of the grid items data-category attribute
     * with a regexp regarding all whitespace.
     */
    getCategories(): string[];
    /**
     * Returns the value of the sort attribute
     * @param sortAttribute "index", "sortData" or custom user data-attribute by which to sort
     */
    getSortAttribute(sortAttribute: string): string | number;
    protected bindEvents(): void;
    protected unbindEvents(): void;
}


code:
import { Position } from './../types/interfaces';
import StyledFilterizrElement from '../StyledFilterizrElement';
import FilterizrOptions from '../FilterizrOptions';
export default class StyledFilterItem extends StyledFilterizrElement {
    private _index;
    constructor(node: HTMLElement, index: number, options: FilterizrOptions);
    initialize(): void;
    setFilteredStyles(position: Position, cssOptions: object): void;
    updateTransitionStyle(): void;
    updateWidth(): void;
    /**
     * Sets the transition css property as an inline style on the FilterItem.
     *
     * The idea here is that during the very first render items should assume
     * their positions directly.
     *
     * Following renders should actually trigger the transitions, which is why
     * we need to delay setting the transition property.
     *
     * Unfortunately, JavaScript code executes on the same thread as the
     * browser's rendering. Everything that needs to be drawn waits for
     * JavaScript execution to complete. Thus, we need to use a setTimeout
     * here to defer setting the transition style at the first rendering cycle.
     */
    enableTransitions(): Promise<void>;
    disableTransitions(): void;
    setZIndex(zIndex: number): void;
    removeZIndex(): void;
    removeWidth(): void;
}


code: export { default } from './FilterItem';


code:
import FilterizrOptions from '../FilterizrOptions';
import { Dictionary, Position } from '../types/interfaces';
export declare const makeInitialStyles: (options: FilterizrOptions) => object;
export declare const makeFilteringStyles: (targetPosition: Position, cssOptions: Dictionary) => object;
export declare const makeTransitionStyles: (index: number, options: FilterizrOptions) => object;


code:
import { Filter } from './ActiveFilter';
import FilterItem from './FilterItem';
import FilterizrOptions from './FilterizrOptions/FilterizrOptions';
export default class FilterItems {
    private filterItems;
    private options;
    constructor(filterItems: FilterItem[], options: FilterizrOptions);
    readonly length: number;
    get(): FilterItem[];
    getItem(index: number): FilterItem;
    set(filterItems: FilterItem[]): void;
    destroy(): void;
    updateTransitionStyle(): void;
    updateDimensions(): void;
    push(filterItem: FilterItem): number;
    getFiltered(filter: Filter): FilterItem[];
    getFilteredOut(filter: Filter): FilterItem[];
    getSorted(sortAttr?: string, sortOrder?: 'asc' | 'desc'): FilterItem[];
    getSearched(searchTerm: string): FilterItem[];
    getShuffled(): FilterItem[];
    private shouldBeFiltered;
}


code:
import StyledFilterItems from './StyledFilterItems';
import { Filter } from '../types';
import FilterItem from '../FilterItem';
import FilterizrOptions from '../FilterizrOptions/FilterizrOptions';
import { Destructible, Styleable } from '../types/interfaces';
export default class FilterItems implements Destructible, Styleable {
    private filterItems;
    private styledFilterItems;
    private options;
    constructor(filterItems: FilterItem[], options: FilterizrOptions);
    readonly styles: StyledFilterItems;
    readonly length: number;
    getItem(index: number): FilterItem;
    destroy(): void;
    push(filterItem: FilterItem): number;
    remove(node: HTMLElement): void;
    getFiltered(filter: Filter): FilterItem[];
    getFilteredOut(filter: Filter): FilterItem[];
    sort(sortAttr?: string, sortOrder?: 'asc' | 'desc'): void;
    shuffle(): void;
    private search;
    private shouldBeFiltered;
}


code:
import StyledFilterizrElements from '../StyledFilterizrElements';
import FilterItem from '../FilterItem/FilterItem';
export default class StyledFilterItems extends StyledFilterizrElements {
    private _filterItems;
    constructor(elements: FilterItem[]);
    removeWidth(): void;
    updateWidth(): void;
    updateTransitionStyle(): void;
    disableTransitions(): void;
    enableTransitions(): Promise<void>;
    updateWidthWithTransitionsDisabled(): void;
}


code: export { default } from './FilterItems';


code:
import FilterizrOptions from './FilterizrOptions/FilterizrOptions';
import FilterContainer from './FilterContainer';
import FilterItem from './FilterItem';
import { Filter } from './ActiveFilter';
import { RawOptions } from './FilterizrOptions/defaultOptions';
export default class Filterizr {
    /**
     * Main Filterizr classes exported as static members
     */
    static FilterContainer: typeof FilterContainer;
    static FilterItem: typeof FilterItem;
    static defaultOptions: RawOptions;
    /**
     * Static method that receives the jQuery object and extends
     * its prototype with a .filterizr method.
     */
    static installAsJQueryPlugin: Function;
    options: FilterizrOptions;
    private browserWindow;
    private filterContainer;
    private filterControls?;
    private filterizrState;
    constructor(selectorOrNode?: string | HTMLElement, userOptions?: RawOptions);
    private readonly filterItems;
    /**
     * Filters the items in the grid by a category
     * @param category by which to filter
     */
    filter(category: Filter): void;
    destroy(): void;
    /**
     * Inserts a new FilterItem in the Filterizr grid
     * @param node DOM node to append
     */
    insertItem(node: HTMLElement): void;
    /**
     * Sorts the FilterItems in the grid
     * @param sortAttr the attribute by which to perform the sort
     * @param sortOrder ascending or descending
     */
    sort(sortAttr?: string, sortOrder?: 'asc' | 'desc'): void;
    /**
     * Searches through the FilterItems for a given string and adds an additional filter layer.
     * @param searchTerm the term for which to search
     */
    search(searchTerm?: string): void;
    /**
     * Shuffles the FilterItems in the grid, making sure their positions have changed.
     */
    shuffle(): void;
    /**
     * Updates the perferences of the users for rendering the Filterizr grid,
     * additionally performs error checking on the new options passed.
     * @param newOptions to override the defaults.
     */
    setOptions(newOptions: RawOptions): void;
    /**
     * Performs multifiltering with AND/OR logic.
     * @param toggledFilter the filter to toggle
     */
    toggleFilter(toggledFilter: string): void;
    private render;
    private onTransitionEndCallback;
    private rebindFilterContainerEvents;
    private bindEvents;
    /**
     * If it contains images it makes use of the imagesloaded npm package
     * to trigger the first render after the images have finished loading
     * in the DOM. Otherwise, overlapping can occur if the images do not
     * have the height attribute explicitly set on them.
     *
     * In case the grid contains no images, then a simple render is performed.
     */
    private renderWithImagesLoaded;
    private updateDimensionsAndRerender;
}


code:
import { Filter } from '../types';
import { RawOptions, Destructible } from '../types/interfaces';
import FilterizrOptions from '../FilterizrOptions';
import FilterContainer from '../FilterContainer';
import FilterItem from '../FilterItem';
export default class Filterizr implements Destructible {
    /**
     * Main Filterizr classes exported as static members
     */
    static FilterContainer: typeof FilterContainer;
    static FilterItem: typeof FilterItem;
    static defaultOptions: RawOptions;
    /**
     * Static method that receives the jQuery object and extends
     * its prototype with a .filterizr method.
     */
    static installAsJQueryPlugin: Function;
    options: FilterizrOptions;
    private windowEventReceiver;
    private filterContainer;
    private filterControls?;
    private imagesHaveLoaded;
    private spinner?;
    constructor(selectorOrNode?: string | HTMLElement, userOptions?: RawOptions);
    private readonly filterItems;
    /**
     * Filters the items in the grid by a category
     * @param category by which to filter
     */
    filter(category: Filter): void;
    destroy(): void;
    /**
     * Inserts a new FilterItem into the grid
     */
    insertItem(node: HTMLElement): Promise<void>;
    /**
     * Removes a FilterItem from the grid
     */
    removeItem(node: HTMLElement): void;
    /**
     * Sorts the FilterItems in the grid
     * @param sortAttr the attribute by which to perform the sort
     * @param sortOrder ascending or descending
     */
    sort(sortAttr?: string, sortOrder?: 'asc' | 'desc'): void;
    /**
     * Searches through the FilterItems for a given string and adds an additional filter layer.
     */
    search(searchTerm?: string): void;
    /**
     * Shuffles the FilterItems in the grid, making sure their positions have changed.
     */
    shuffle(): void;
    /**
     * Updates the perferences of the users for rendering the Filterizr grid,
     * additionally performs error checking on the new options passed.
     * @param newOptions to override the defaults.
     */
    setOptions(newOptions: RawOptions): void;
    /**
     * Performs multifiltering with AND/OR logic.
     * @param toggledFilter the filter to toggle
     */
    toggleFilter(toggledFilter: string): void;
    private render;
    /**
     * Initialization sequence of Filterizr when the grid is first loaded
     */
    private initialize;
    private bindEvents;
    /**
     * Resolves when the images of the grid have finished loading into the DOM
     */
    private waitForImagesToLoad;
}


code: export { default } from './Filterizr';


code: export default function installAsJQueryPlugin($: any): void;


code:
import { Destructible, Dimensions, Resizable, Styleable } from './types/interfaces';
import FilterizrOptions from './FilterizrOptions';
import EventReceiver from './EventReceiver';
import StyledFilterizrElement from './StyledFilterizrElement';
export default abstract class FilterizrElement implements Destructible, Resizable, Styleable {
    node: Element;
    options: FilterizrOptions;
    protected eventReceiver: EventReceiver;
    constructor(node: Element, options: FilterizrOptions);
    readonly dimensions: Dimensions;
    destroy(): void | Promise<void>;
    trigger(eventType: string): void;
    abstract readonly styles: StyledFilterizrElement;
    protected abstract bindEvents(): void;
    protected abstract unbindEvents(): void;
}


code:
import { BaseOptions, RawOptions } from './../types/interfaces';
import ActiveFilter from '../ActiveFilter';
import { Filter } from '../types';
export interface Options extends BaseOptions {
    filter: ActiveFilter;
}
export default class FilterizrOptions {
    private options;
    constructor(userOptions: RawOptions);
    readonly isSpinnerEnabled: boolean;
    readonly areControlsEnabled: boolean;
    readonly controlsSelector: string;
    filter: Filter;
    toggleFilter(filter: string): void;
    searchTerm: string;
    get(): Options;
    getRaw(): RawOptions;
    set(newUserOptions: RawOptions): void;
    private convertToFilterizrOptions;
    private convertToOptions;
    private validate;
}


code:
import { RawOptions } from '../types/interfaces';
declare const defaultOptions: RawOptions;
export default defaultOptions;


code:
export { default as defaultOptions } from './defaultOptions';
export { default } from './FilterizrOptions';


code:
import { Destructible, Styleable } from '../types/interfaces';
import FilterizrOptions from '../FilterizrOptions';
import FilterContainer from '../FilterContainer';
import StyledSpinner from './StyledSpinner';
export default class Spinner implements Destructible, Styleable {
    private node;
    private styledNode;
    private filterContainer;
    constructor(filterContainer: FilterContainer, options: FilterizrOptions);
    readonly styles: StyledSpinner;
    destroy(): Promise<void>;
    private initialize;
}


code:
import StyledFilterizrElement from '../StyledFilterizrElement';
export default class StyledSpinner extends StyledFilterizrElement {
    initialize(): void;
    fadeOut(): Promise<void>;
}


code: export { default } from './Spinner';


code:
import { SpinnerOptions } from '../types/interfaces';
export declare function makeSpinner({ fillColor }: SpinnerOptions): HTMLElement;


code:
import { Destructible } from './types/interfaces/Destructible';
import FilterizrOptions from './FilterizrOptions';
export default abstract class StyledFilterizrElement implements Destructible {
    protected options: FilterizrOptions;
    protected node: HTMLElement;
    constructor(node: HTMLElement, options: FilterizrOptions);
    destroy(): void;
    protected animate(targetStyles: object): Promise<void>;
    protected set(targetStyles: object): void;
    protected remove(propertyName: string): void;
    abstract initialize(): void | Promise<void>;
}


code:
export default abstract class StyledFilterizrElements {
}


code:
declare class Animator {
    static animate(node: HTMLElement, targetStyles: object): Promise<void>;
    private static process;
}
declare const _default: typeof Animator.animate;
export default _default;


code:
/**
 * A Regexp to validate potential values for the CSS easing property of transitions.
 */
export declare const cssEasingValuesRegexp: RegExp;


code:
interface FilterizrState {
    IDLE: 'IDLE';
    FILTERING: 'FILTERING';
    SORTING: 'SORTING';
    SHUFFLING: 'SHUFFLING';
}
/**
 * Possible animation states for Filterizr
 */
export declare const FILTERIZR_STATE: FilterizrState;
export {};


code:
export { FILTERIZR_STATE } from './filterizrState';
export { LAYOUT } from './layout';
export { cssEasingValuesRegexp } from './cssEasingValuesRegexp';


code:
interface Layout {
    SAME_SIZE: 'sameSize';
    SAME_HEIGHT: 'sameHeight';
    SAME_WIDTH: 'sameWidth';
    PACKED: 'packed';
    HORIZONTAL: 'horizontal';
    VERTICAL: 'vertical';
}
/**
 * Possible grid layout modes
 */
export declare const LAYOUT: Layout;
export {};


code:
import { Position } from './FilterItem';
import FilterContainer from './FilterContainer';
/**
 * Calculates and returns an array of objects representing
 * the next positions the FilterItems are supposed to assume.
 * @param layout name of helper method to be used
 * @param filterizr instance
 */
declare const getLayoutPositions: (layout: string, filterContainer: FilterContainer) => Position[];
export default getLayoutPositions;


code:
/**
 * Filterizr is a JavaScript library that sorts, shuffles and applies stunning
 * filters over responsive galleries using CSS3 transitions and
 * custom CSS effects.
 * @author Yiotis Kaltsikis
 * @see {@link http://yiotis.net/filterizr}
 * @license MIT
 */
export { default } from './Filterizr';


code:
/**
 * Filterizr is a JavaScript library that sorts, shuffles and applies stunning filters over
 * responsive galleries using CSS3 transitions and custom CSS effects.
 *
 * @author Yiotis Kaltsikis
 * @see {@link http://yiotis.net/filterizr}
 * @license MIT
 */
import Filterizr from './Filterizr';
export default Filterizr;


code: export default function installAsJQueryPlugin($: any): void;