Monday, November 20, 2017

Play #1:Garnishing Jquery

The purpose of my life. One of the purpose of life is to share our knowledge and would like to take this forum to share my knowledge.

Beeing a senior software engineer I would like to share my experience in couple of my projects or modules. A single blog is not enough so I will release in the form of plays where each play discusses about a module and how we solved the module.

In this play I am going to discuss about the module we developed for a intranet website. The requirement is to display the news headlines in couple of landing pages and obviously to design a editor page to edit the headline. Might seems easy to the other eye but journey was quite a learning and interesting.

The tools we used is ASP.NET, C#, LINQ, JQUERY.

The Challenges:
The first task we started is the editor module to do the DML operation. What!! DML operation, I am hearing the voice but the design itself had a challenge where we had to make our choices.

1. HTMLExtender:
We have to pick up a editor where we have to add the html content, the flashy thought I got is using the HTML Extender in ajaxcontroltoolkit along with the textbox and there comes the question how to add it into our project.

It's straightforward unless you know what you are doing

There are different ways in which you can install the ajaxcontrolkit but I prefer nugget tools available in the visual studio. Below provides other ways you can install the ajaxcontroltoolkit.

http://www.codingfusion.com/Post/3-Different-ways-to-add-AjaxControlToolkit-in-Asp

Note: Once installed, the HtmlSanitizer is also gets installed which is  a .NET library for cleaning HTML fragments and documents from constructs that can lead to XSS attacks. It uses AngleSharp to parse, manipulate, and render HTML and CSS.

There are various control which is supported by ajaxcontroltoolkit which discussed in below link.

http://www.ajaxcontroltoolkit.net/


Once installed make sure an entry is added into the web.config file as below


In web.config:
<configSections>
<section name="ajaxControlToolkit" type="AjaxControlToolkit.AjaxControlToolkitConfigSection, AjaxControlToolkit"/>
</configSections>

Now the tool has been added into the application and how to use below are the steps.

Step1:
Register the ajaxcontroltoolkit
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

Step2:
Add the ScriptManager
<asp:ScriptManager ID="sm" runat="server"></asp:ScriptManager>


Step3:
We need a HTMLEditorExtender and a textbox to leverage the HTML Editor
<asp:TextBox ID="txtEditor" runat="server" Width="100%" Height="200" />
<ajaxToolkit:HtmlEditorExtender ID="htmlEditorExtender" runat="server" TargetControlID="txtEditor"></ajaxToolkit:HtmlEditorExtender>

Step4:
For the JQuery and ajaxcontroltoolkit to work together we need to add the below in the pageload event.

this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;

What the next step, enter you html content into the editor :-).

2. Datepicker:

There are many datepicker in the google world starting from javascript, jquery enabled one, Github code where you can get.

But one that you can neatly make use of it is jquery-ui controls which support datepicker. Below is the url.


Below are the steps to make use of it.

Step 1:
The setup process.
Add the jquery-ui.css and jquery-ui.js file into scripts and css folder. Also make sure you include those file into your application.

The jquery comes with the minified version of the files which is less weight. Always feel free to use it.

<script type="text/javascript" src="../Content/scripts/jquery-ui.min.js"></script>
<link rel="stylesheet" href="/Content/Styles/jquery-ui.min.css" />

Step 2:
Add a textbox.
<asp:TextBox ID="txtStartDate" runat="server"></asp:TextBox>


Step 3:
Jquery code

$(document).ready(function () {
$(function () {
        $('#txtStartDate').datepicker();

        //enable the date only from today
        $('#txtEndDate').datepicker({ minDate: 0 });
    });
});

The interesting part is the minDate property is difference between the today date and previous date which should be disabled.

So as the comment suggests it disables all the date before today.

3. The Thumbnail Image Editor:

The requirement we received for this is where a user should able to enter the content and add a thumbnail image from the Thumbnail folder available in the server.

The first answer would be using the image option available in the HTMLExtender but the facility it provides is that we can upload the image only from the client side.

But we need to show the thumbnail images from the server side there are third party tools like fck editor, doesn't that provide the solution. Well the answer is kind of YES and NO because here we can upload multiple images, which brings up to the point where we need to do the validation if the user has added multiple images which I thought was not a good idea and we finally came up the solution lets build a jquery thumbnail editor by our-self. It was a good solution which avoids the multiple validation and we had a good pat from our client.

The tools needed for that is as follows.
1. Jquery UI Dialog box.
2. Webapi to communication to the server to retrieve the thumbnail images.
3. Jquery AJAX to call web api.

Note: 
I have differentiated with the color to indicate where it has been used.

Step to add the dialog box.
Step 1: 
Add the below html content into the html file.
<%//Jquery popup %>
<div id="dlgthumbnailImageSelector" title="Thumbnail Picker">
    <div class="selectable">
        <%// load the image dynamically  %>
    </div>
</div>



Step 2:
Add the dialog box inside the document ready

$(document).ready(function () {


//thumbnail dialog box

    $("#dlgthumbnailImageSelector").dialog({

        autoOpen: false,

        buttons: {

            Ok: function () {
                var imageName = $("#hiddenThumbnailImage").val();
                $('#lblThumbnailImage').val(imageName);
                $("#lblThumbnailImage").html(imageName);
                $(this).dialog("close");
            }
        },
        modal: true,
       maxWidth: 450,
        maxHeight: 500,
        width: 450,
        height: 500
    });
});


The OK is the keyword and we have used the hidden field to store the selected value and we have used the label to show the selected image to the user.

Step 3:
The thumbnail image editor is opened when the button is click inside the editor.

Highlighted the one which calls the dialog button.


$(document).ready(function () {

//open dialog
    $("#btnthumbnailImageSelector").click(function () {
        //initialize the the thumnail images
        //if create
        if (thumbnailImageLength == null)
            GetThumbnails();
        else { // if edit
            AssignThumbnailByName();
            AssignThumbnail();
        }

        $('#dlgthumbnailImageSelector').dialog("open");

    });
});

Step 4:
Configure the web-api.
/// <summary>
    /// Webapi service for retrieving images in the thumbnail folder.
    /// </summary>
    public class HeadlinesController : ApiController
    {
        // GET api/Headlines/GetThumbailnailImages
        public string[] GetThumbailnailImages()
        {
            string[] filePaths =Directory.GetFiles(HostingEnvironment.MapPath("~/Content/images/thumbnails/"),"*.jpg");

            for (int i = 0; i < filePaths.Length; i++)
                filePaths[i] = Path.GetFileName(filePaths[i]);

            return filePaths;
        }
    }

The above can be placed in any of the business logic file, this logic has been placed inside the Headlines.cs file under App_Code folder.

The webapi is self hosted within the application and if it need to called with the help of the JQUERY API then we need to add the below code inside the Application_Start available inside the Global.asax file.



 void Application_Start(object sender, EventArgs e)

              {



                //routing url for accessing webapi restful service to load the thumbnail images.               

                GlobalConfiguration.Configure(config =>
                {
                    config.MapHttpAttributeRoutes();

                    config.Routes.MapHttpRoute(
                        name: "DefaultApi",
                        routeTemplate: "api/{controller}/{id}",
                        defaults: new { id = RouteParameter.Optional }
                    );
                }); 

Step 5:
If the thumbnail dialog loading then we need to contact the webapi using JQUERY AJAX.  Below is the steps.


//dynamic thumbnail images retrieval using jquery-ajax and web-api.
var GetThumbnails = function ()  {
    $.ajax({  
        //the webapi url
        url: "/api/Headlines/GetThumbailnailImages",
        dataType: "json",  
        type: "GET",                
        contentType: "application/json; charset=utf-8",  
        success: function (data) {
            if (data != null) {
                var thumbnailTemplate = "<img id='{1}' src='../Content/images/thumbnails/{0}' alt='{0}' width='100' height='90'  />";

                //construct the thumbnail image and append to the dialog box
                $.each(data, function (index, thumbnail) {
                    image = thumbnailTemplate.replace('{0}', thumbnail);
                    image = image.replace('{0}', thumbnail);
                    image = image.replace('{1}', index.toString());
                    $(".selectable").append(image);                    
                });

                //set the first/last/length of the thumbnail dialog box.
                thumbnailFirstElement = $(".selectable img").first();
                thumbnailLastElement = $(".selectable img").last();
                thumbnailImageLength = $(".selectable img").length;

                AssignThumbnailByName();
                AssignThumbnail();
            }
        },             
        error: function (d) {
            alert(d.status + " " + d.statusText);           
        }  
    });

Step 6:
The below code is used during the edit operation

//retrieve the selected image name
var AssignThumbnail = function () {
   
    var element = $("img.ui-selected");

        //retrieves the selected text
    if (element.hasClass("ui-selected")) {
        var selectedThumbnail = element.attr("alt");
            $("#hiddenThumbnailImage").val(selectedThumbnail);
        }  
}


//assign thumbnail based on selected image name used on edit operation.
var AssignThumbnailByName = function() {

    var selectedImage = $("#hiddenThumbnailImage").val();
       var selectedElement = null;
   
    //assign the value of edit thumbnail image.      
       var searchElement = "img[alt='{0}']".replace('{0}', selectedImage);
       selectedElement = $(searchElement);
      
    //select the image based on the thumbnail image name
       selectedElement.addClass("ui-selectee");
       selectedElement.addClass("ui-selected");

    //scroll to the position of the thumbnail image.
       selectedElement.get(0).scrollIntoView();

}


Step 7:
The below code is used for navigation for arrow when moved by the arrows inside the thumbnail image dialog box.

Also place the code inside the document.ready.


/key navigation for selecting thumbnail
    $(document).keydown(function (event) {

        var nextElement = null;
        var currentElement = $(".selectable img.ui-selected");
        var pos;
        var newPos;

        if (currentElement != null) {
            if (currentElement.length > 0) {
                var currentId = currentElement[0].id;

                switch (event.keyCode) {
                    case 37: //left arrow image selection
                        nextElement = currentElement.prev();

                        //on first element select last element
                        if (nextElement == null || nextElement.length == 0)
                            nextElement = thumbnailLastElement;

                        break;
                    case 38: //up arrow image selection                     
                        pos = parseInt(currentId) - column;

                        if (pos >= 0) //select next element
                            nextElement = $(".selectable img#" + pos);
                        else //if top position select the last element
                        {
                            newPos = thumbnailImageLength - (column - currentId);
                            nextElement = $(".selectable img#" + newPos);
                        }

                        break;
                    case 39: //right arrow image selection                   
                        nextElement = currentElement.next();

                        if (nextElement == null)
                            if (nextElement.length > 0) {
                                nextElement = thumbnailFirstElement;
                            }

                        break;
                    case 40: //down arrow image selection                   
                        pos = parseInt(currentId) + column;

                        if (pos < thumbnailImageLength) //not an last element select the down element
                            nextElement = $(".selectable img#" + pos);
                        else { // if last select the first element of that column
                            newPos = currentId % column;
                            nextElement = $(".selectable img#" + newPos);
                        }

                        break;
                }
            }

            if (currentElement != null) {
                if (currentElement.length > 0) {
                    currentElement.removeClass("ui-selected");
                }
            }

            if (nextElement != null) {
                if (nextElement.length > 0) {
                    nextElement.addClass("ui-selectee");
                    nextElement.addClass("ui-selected");
                    nextElement.click();
                }
            }
        }

        if (event.keyCode >= 37 && event.keyCode <= 40)
            event.preventDefault();
    });
});

Step 8:
The below code is used to activate the selectable event for focusing the image inside retrieving the image name when selected.

Also place the code inside the document.ready.

 //operation to display the selected file
        $(".selectable").selectable({
            selected: function () {
                AssignThumbnail();
            },
            selecting: function (event, ui) {
                if ($(".ui-selected, .ui-selecting").length > 1)
                    $(ui.selecting).removeClass("ui-selecting");
            }
        });
    });

Step 9:
Add the below style for selectable color

/*border style of thumbnail image when selecting*/
.selectable .ui-selecting {
    border2px solid #fcf9f9;
}

/* border style of thumbnail image when selected*/
.selectable .ui-selected {
    border2px solid #f95757;
    -webkit-box-shadow0px 0px 8px 0px rgba(249, 87, 87, 1);
    -moz-box-shadow0px 0px 8px 0px rgba(249, 87, 87, 1);
    box-shadow0px 0px 8px 0px rgba(249, 87, 87, 1);
}

/*spacing style for images*/
.selectable img {
    margin5px;
    padding5px;
    border2px solid #fcf9f9;
}


4. Validation Controls:

The validation control is one of the important aspect of an application, which avoids much of the error caused by the user.  The typical application should do both the client side and the server side.

Here we are going to validate the title, date, landing pages checkbox list using the validation summary, required field validator and custom validator controls.

Step 1:
Add the validation summary control.
<asp:ValidationSummary
                            ID="vsHeadlines"
                            runat="server"
                            HeaderText="Following error occurs....."
                            ShowMessageBox="false"
                            DisplayMode="BulletList"
                            ShowSummary="true"
                            BackColor="Snow"
                            Width="100%"
                            ForeColor="Red"
                            Font-Size="Medium"
                            ValidationGroup="Headline" />

Notable properties:
HeaderText, ShowMessageBox, ValidationGroup.

Step 2:
Add the required field validation control

<asp:TextBox ID="txtTitle" runat="server" Width="100%"></asp:TextBox>
                        <asp:RequiredFieldValidator ID="rfvTitle" runat="server" ControlToValidate="txtTitle" ErrorMessage="Please enter Title"
                            SetFocusOnError="true" ValidationGroup="Headline">
                        </asp:RequiredFieldValidator>


Notable properties:
ControlToValidate, ErrorMessage, SetFocusOnError, ValidationGroup.

Step 3:
Add the customValidator for the landing pages checkbox.

<asp:CheckBoxList ID="chkInternet"runat="server" RepeatLayout="flow" Enabled="false"></asp:CheckBoxList>
<asp:CustomValidator runat="server" ID="cvLandingPages"
                            ClientValidationFunction="IsLandingPagesChecked"
                            ValidationGroup="Headline"
                            ErrorMessage="Please select Landing Page(s)" SetFocusOnError="true"></asp:CustomValidator>

Notable properties:
ClientValidationFunction, ValidationGroup, ErrorMessage, SetFocusOnError.

Script:
//validates if atleast on checkbox is selected.
function IsLandingPagesChecked(sender, args) {

    args.IsValid = false;

    //check if intranet landing pages is selected
    if ($("#cblIntranet input:checked").length > 0)
        args.IsValid = true;
}


Step 4:
Add the date validation for From Date and To Date textbox.

Below custom validator to validate the date.
                        <asp:CustomValidator runat="server" ID="cvStartDate"

                            ClientValidationFunction="IsStartDateValid"
                            ValidationGroup="Headline"
                            ErrorMessage="Please enter valid start date" ControlToValidate="txtStartDate" SetFocusOnError="true"></asp:CustomValidator>


                        <asp:CustomValidator runat="server" ID="cvEndDate"
                            ClientValidationFunction="IsEndDateValid"
                            ValidationGroup="Headline"
                            ErrorMessage="Please enter valid end date" ControlToValidate="txtStartDate" SetFocusOnError="true"></asp:CustomValidator>

Script

//validates if the valid start date is enetered used in custom validation
function IsStartDateValid(sender, args) {

    args.IsValid = false;
    var start = $('#txtStartDate').val();

    if (Date.parse(start))
        args.IsValid = true;  
}

//validates if the valid end date is entered used in custom validation
function IsEndDateValid(sender, args) {

    args.IsValid = false;
    var end = $('#txtEndDate').val();

    if (Date.parse(end))
        args.IsValid = true;   
}

Step 5:
Add the submit and the cancel button.
<asp:Button ID="btnSubmit" runat="server" ValidationGroup="Headline" Text="Submit" OnClientClick="return IsValidPage();" OnClick="btnSubmit_Click" />

 Add the below code in the server side
//checks if the clientside validation succeeded.
if (Page.IsValid)
{
 Submit();
}

Notable Properties: 
ValidationGroup


Step 6:
When you click the submit button the error occurs both in the summary and also next to each control we had a requirement to display only the summary.

Below is the css to disable it.
/*disable the error message*/
#rfvTitle#rfvEndDate,#rfvStartDate,#cvLandingPages,#cvStartDate,#cvEndDate,#cvDateRange
{
    visibilityhidden;
    displaynone;
}



5. UpdatePanel:
To disable the postback we used the following functionality and also we have implemented the search functionality with the help of checkboxlist option.

Step 1:

Add the checkbox list and the display button inside the updatepanel.

<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Always">
//add the button which needs the postback operation used when you want to refresh the page.
                    <Triggers>                       
                        <asp:PostBackTrigger ControlID="btnCreate" />                      
                    </Triggers>
                    <ContentTemplate>
           
                                                    <asp:CheckBoxList ID="chkInternet"runat="server" RepeatLayout="flow" Enabled="false"></asp:CheckBoxList>
                                                    <asp:CheckBoxList ID="chkIntranet"runat="server" RepeatLayout="flow" RepeatDirection="Vertical"></asp:CheckBoxList>
                                               
<asp:Button ID="btnDisplay" runat="server" Text="Display" OnClientClick="return IsSearchChecked()" OnClick="btnDisplay_Click" />


</ContentTemplate>
</asp:UpdatePanel>

Add the below script for search validation.

//check if the search checkbox is selected
function IsSearchChecked() {
    var success = true;

    if ($("#chkIntranet input:checked").length == 0) {
        success = false;
        $("#lblMessage").addClass("info");
        $("#lblMessage").html("Please select atleast one parameter");
    }

    return success;
}

5. Slider Headline:

For the slide line editor we used one of the feature known as the light-weight slider which uses the jquery and I have tweaked a little in-order to the support the  slider functionality.  It also supports tool tip when focused on a particular headline and configurable number of items to be displayed in the light slider.



Business logic js

$(document).ready(function () {
            $("#content-slider").lightSlider({              
                keyPress: true,
                pauseOnHover: true,
                auto: true,                                        
                item: 5,
                controls: false,
                slideMove: 5,
                slideMargin: 20,
                autoWidth: false,
                pager: true
            });
        });

        $(function () {
            $("#container").tooltip({               
                tooltipClass: "custom-tooltip-styling",              
                content: function () {
                    return this.getAttribute("title");
                },
                close: function (event, ui) {
                    ui.tooltip.hover(function () {
                        $(this).stop(true).fadeTo(500, 1);
                    },
                    function () {
                        $(this).fadeOut('500', function () {
                            $(this).remove();
                        });
                    });
                }
            });
        });



--lightslider.js
/*! lightslider - v1.1.6 - 2016-10-25
* https://github.com/sachinchoolur/lightslider
* Copyright (c) 2016 Sachin N; Licensed MIT */

//notes - commented 1002 and 1004 inorder to set the loop functionality as the mandatory option.
(function ($, undefined) {
    'use strict';
    var defaults = {
        item: 3,
        autoWidth: false,
        slideMove: 3,
        slideMargin: 10,
        addClass: '',
        mode: 'slide',
        useCSS: true,
        cssEasing: 'ease', //'cubic-bezier(0.25, 0, 0.25, 1)',
        easing: 'linear', //'for jquery animation',//
        speed: 5000, //ms'
        auto: false,
        pauseOnHover: false,
        loop: false,
        slideEndAnimation: true,
        pause: 7000,
        keyPress: false,
        controls: true,
        prevHtml: '',
        nextHtml: '',
        rtl: false,
        adaptiveHeight: false,
        vertical: false,
        verticalHeight: 500,
        vThumbWidth: 100,
        thumbItem: 10,
        pager: true,
        gallery: false,
        galleryMargin: 5,
        thumbMargin: 5,
        currentPagerPosition: 'middle',
        enableTouch: true,
        enableDrag: true,
        freeMove: true,
        swipeThreshold: 40,
        responsive: [],
        /* jshint ignore:start */
        //hide the content-slide when loading and show after the slider is loaded
        onBeforeStart: function ($el) { $("#content-slider").hide(); },      
        onSliderLoad: function ($el) { $("#content-slider").show(); },
        onBeforeSlide: function ($el, scene) {},
        onAfterSlide: function ($el, scene) {},
        onBeforeNextSlide: function ($el, scene) {},
        onBeforePrevSlide: function ($el, scene) {}
        /* jshint ignore:end */
    };
    $.fn.lightSlider = function (options) {
        if (this.length === 0) {
            return this;
        }

        if (this.length > 1) {
            this.each(function () {
                $(this).lightSlider(options);
            });
            return this;
        }

        var plugin = {},
            settings = $.extend(true, {}, defaults, options),
            settingsTemp = {},
            $el = this;
        plugin.$el = this;

        if (settings.mode === 'fade') {
            settings.vertical = false;
        }
        var $children = $el.children(),
            windowW = $(window).width(),
            breakpoint = null,
            resposiveObj = null,
            length = 0,
            w = 0,
            on = false,
            elSize = 0,
            $slide = '',
            scene = 0,
            property = (settings.vertical === true) ? 'height' : 'width',
            gutter = (settings.vertical === true) ? 'margin-bottom' : 'margin-right',
            slideValue = 0,
            pagerWidth = 0,
            slideWidth = 0,
            thumbWidth = 0,
            interval = null,
            isTouch = ('ontouchstart' in document.documentElement);
        var refresh = {};

        refresh.chbreakpoint = function () {
            windowW = $(window).width();
            if (settings.responsive.length) {
                var item;
                if (settings.autoWidth === false) {
                    item = settings.item;
                }
                if (windowW < settings.responsive[0].breakpoint) {
                    for (var i = 0; i < settings.responsive.length; i++) {
                        if (windowW < settings.responsive[i].breakpoint) {
                            breakpoint = settings.responsive[i].breakpoint;
                            resposiveObj = settings.responsive[i];
                        }
                    }
                }
                if (typeof resposiveObj !== 'undefined' && resposiveObj !== null) {
                    for (var j in resposiveObj.settings) {
                        if (resposiveObj.settings.hasOwnProperty(j)) {
                            if (typeof settingsTemp[j] === 'undefined' || settingsTemp[j] === null) {
                                settingsTemp[j] = settings[j];
                            }
                            settings[j] = resposiveObj.settings[j];
                        }
                    }
                }
                if (!$.isEmptyObject(settingsTemp) && windowW > settings.responsive[0].breakpoint) {
                    for (var k in settingsTemp) {
                        if (settingsTemp.hasOwnProperty(k)) {
                            settings[k] = settingsTemp[k];
                        }
                    }
                }
                if (settings.autoWidth === false) {
                    if (slideValue > 0 && slideWidth > 0) {
                        if (item !== settings.item) {
                            scene = Math.round(slideValue / ((slideWidth + settings.slideMargin) * settings.slideMove));
                        }
                    }
                }
            }
        };

        refresh.calSW = function () {
            if (settings.autoWidth === false) {
                slideWidth = (elSize - ((settings.item * (settings.slideMargin)) - settings.slideMargin)) / settings.item;
            }
        };

        refresh.calWidth = function (cln) {
            var ln = cln === true ? $slide.find('.lslide').length : $children.length;
            if (settings.autoWidth === false) {
                w = ln * (slideWidth + settings.slideMargin);
            } else {
                w = 0;
                for (var i = 0; i < ln; i++) {
                    w += (parseInt($children.eq(i).width()) + settings.slideMargin);
                }
            }
            return w;
        };
        plugin = {
            doCss: function () {
                var support = function () {
                    var transition = ['transition', 'MozTransition', 'WebkitTransition', 'OTransition', 'msTransition', 'KhtmlTransition'];
                    var root = document.documentElement;
                    for (var i = 0; i < transition.length; i++) {
                        if (transition[i] in root.style) {
                            return true;
                        }
                    }
                };
                if (settings.useCSS && support()) {
                    return true;
                }
                return false;
            },
            keyPress: function () {
                if (settings.keyPress) {
                    $(document).on('keyup.lightslider', function (e) {
                        if (!$(':focus').is('input, textarea')) {
                            if (e.preventDefault) {
                                e.preventDefault();
                            } else {
                                e.returnValue = false;
                            }
                            if (e.keyCode === 37) {
                                $el.goToPrevSlide();
                            } else if (e.keyCode === 39) {
                                $el.goToNextSlide();
                            }
                        }
                    });
                }
            },
            controls: function () {
                if (settings.controls) {
                    $el.after('<div class="lSAction"><a class="lSPrev">' + settings.prevHtml + '</a><a class="lSNext">' + settings.nextHtml + '</a></div>');
                    if (!settings.autoWidth) {
                        if (length <= settings.item) {
                            $slide.find('.lSAction').hide();
                        }
                    } else {
                        if (refresh.calWidth(false) < elSize) {
                            $slide.find('.lSAction').hide();
                        }
                    }
                    $slide.find('.lSAction a').on('click', function (e) {
                        if (e.preventDefault) {
                            e.preventDefault();
                        } else {
                            e.returnValue = false;
                        }
                        if ($(this).attr('class') === 'lSPrev') {
                            $el.goToPrevSlide();
                        } else {
                            $el.goToNextSlide();
                        }
                        return false;
                    });
                }
            },
            initialStyle: function () {
                var $this = this;
                if (settings.mode === 'fade') {
                    settings.autoWidth = false;
                    settings.slideEndAnimation = false;
                }
                if (settings.auto) {
                    settings.slideEndAnimation = false;
                }
                if (settings.autoWidth) {
                    settings.slideMove = 1;
                    settings.item = 1;
                }
                if (settings.loop) {
                    //settings.slideMove = 1;
                    settings.freeMove = false;
                }
                settings.onBeforeStart.call(this, $el);
                refresh.chbreakpoint();
                $el.addClass('lightSlider').wrap('<div class="lSSlideOuter ' + settings.addClass + '"><div class="lSSlideWrapper"></div></div>');
                $slide = $el.parent('.lSSlideWrapper');
                if (settings.rtl === true) {
                    $slide.parent().addClass('lSrtl');
                }
                if (settings.vertical) {
                    $slide.parent().addClass('vertical');
                    elSize = settings.verticalHeight;
                    $slide.css('height', elSize + 'px');
                } else {
                    elSize = $el.outerWidth();
                }
                $children.addClass('lslide');
                if (settings.loop === true && settings.mode === 'slide') {
                    refresh.calSW();
                    refresh.clone = function () {
                        if (refresh.calWidth(true) > elSize) {
                            /**/
                            var tWr = 0,
                                tI = 0;
                            for (var k = 0; k < $children.length; k++) {
                                tWr += (parseInt($el.find('.lslide').eq(k).width()) + settings.slideMargin);
                                tI++;
                                if (tWr >= (elSize + settings.slideMargin)) {
                                    break;
                                }
                            }
                            var tItem = settings.autoWidth === true ? tI : settings.item;

                            /**/
                            if (tItem < $el.find('.clone.left').length) {
                                for (var i = 0; i < $el.find('.clone.left').length - tItem; i++) {
                                    $children.eq(i).remove();
                                }
                            }
                            if (tItem < $el.find('.clone.right').length) {
                                for (var j = $children.length - 1; j > ($children.length - 1 - $el.find('.clone.right').length); j--) {
                                    scene--;
                                    $children.eq(j).remove();
                                }
                            }
                            /**/
                            for (var n = $el.find('.clone.right').length; n < tItem; n++) {
                                $el.find('.lslide').eq(n).clone().removeClass('lslide').addClass('clone right').appendTo($el);
                                scene++;
                            }
                            for (var m = $el.find('.lslide').length - $el.find('.clone.left').length; m > ($el.find('.lslide').length - tItem); m--) {
                                $el.find('.lslide').eq(m - 1).clone().removeClass('lslide').addClass('clone left').prependTo($el);
                            }
                            $children = $el.children();
                        } else {
                            if ($children.hasClass('clone')) {
                                $el.find('.clone').remove();
                                $this.move($el, 0);
                            }
                        }
                    };
                    refresh.clone();
                }
                refresh.sSW = function () {
                    length = $children.length;
                    if (settings.rtl === true && settings.vertical === false) {
                        gutter = 'margin-left';
                    }
                    if (settings.autoWidth === false) {
                        $children.css(property, slideWidth + 'px');
                    }
                    $children.css(gutter, settings.slideMargin + 'px');
                    w = refresh.calWidth(false);
                    $el.css(property, w + 'px');
                    if (settings.loop === true && settings.mode === 'slide') {
                        if (on === false) {
                            scene = $el.find('.clone.left').length;
                        }
                    }
                };
                refresh.calL = function () {
                    $children = $el.children();
                    length = $children.length;
                };
                if (this.doCss()) {
                    $slide.addClass('usingCss');
                }
                refresh.calL();
                if (settings.mode === 'slide') {
                    refresh.calSW();
                    refresh.sSW();
                    if (settings.loop === true) {
                        slideValue = $this.slideValue();
                        this.move($el, slideValue);
                    }
                    if (settings.vertical === false) {
                        this.setHeight($el, false);
                    }

                } else {
                    this.setHeight($el, true);
                    $el.addClass('lSFade');
                    if (!this.doCss()) {
                        $children.fadeOut(0);
                        $children.eq(scene).fadeIn(0);
                    }
                }
                if (settings.loop === true && settings.mode === 'slide') {
                    $children.eq(scene).addClass('active');
                } else {
                    $children.first().addClass('active');
                }
            },
            pager: function () {
                var $this = this;
                refresh.createPager = function () {
                    thumbWidth = (elSize - ((settings.thumbItem * (settings.thumbMargin)) - settings.thumbMargin)) / settings.thumbItem;
                    var $children = $slide.find('.lslide');
                    var length = $slide.find('.lslide').length;
                    var i = 0,
                        pagers = '',
                        v = 0;
                    for (i = 0; i < length; i++) {
                        if (settings.mode === 'slide') {
                            // calculate scene * slide value
                            if (!settings.autoWidth) {
                                v = i * ((slideWidth + settings.slideMargin) * settings.slideMove);
                            } else {
                                v += ((parseInt($children.eq(i).width()) + settings.slideMargin) * settings.slideMove);
                            }
                        }
                        var thumb = $children.eq(i * settings.slideMove).attr('data-thumb');
                        if (settings.gallery === true) {
                            pagers += '<li style="width:100%;' + property + ':' + thumbWidth + 'px;' + gutter + ':' + settings.thumbMargin + 'px"><a href="#"><img src="' + thumb + '" /></a></li>';
                        } else {
                            pagers += '<li><a href="#">' + (i + 1) + '</a></li>';
                        }
                        if (settings.mode === 'slide') {
                            if ((v) >= w - elSize - settings.slideMargin) {
                                i = i + 1;
                                var minPgr = 2;
                                if (settings.autoWidth) {
                                    pagers += '<li><a href="#">' + (i + 1) + '</a></li>';
                                    minPgr = 1;
                                }
                                if (i < minPgr) {
                                    pagers = null;
                                    $slide.parent().addClass('noPager');
                                } else {
                                    $slide.parent().removeClass('noPager');
                                }
                                break;
                            }
                        }
                    }
                    var $cSouter = $slide.parent();
                    $cSouter.find('.lSPager').html(pagers);
                    if (settings.gallery === true) {
                        if (settings.vertical === true) {
                            // set Gallery thumbnail width
                            $cSouter.find('.lSPager').css('width', settings.vThumbWidth + 'px');
                        }
                        pagerWidth = (i * (settings.thumbMargin + thumbWidth)) + 0.5;
                        $cSouter.find('.lSPager').css({
                            property: pagerWidth + 'px',
                            'transition-duration': settings.speed + 'ms'
                        });
                        if (settings.vertical === true) {
                            $slide.parent().css('padding-right', (settings.vThumbWidth + settings.galleryMargin) + 'px');
                        }
                        $cSouter.find('.lSPager').css(property, pagerWidth + 'px');
                    }
                    var $pager = $cSouter.find('.lSPager').find('li');
                    $pager.first().addClass('active');
                    $pager.on('click', function () {                       
                        if (settings.loop === true && settings.mode === 'slide') {
                            scene = scene + ($pager.index(this) - $cSouter.find('.lSPager').find('li.active').index());
                        } else {
                            scene = $pager.index(this);
                        }
                        $el.mode(false);
                        if (settings.gallery === true) {
                            $this.slideThumb();
                        }
                        return false;
                    });
                };
                if (settings.pager) {
                    var cl = 'lSpg';
                    if (settings.gallery) {
                        cl = 'lSGallery';
                    }
                    $slide.after('<ul class="lSPager ' + cl + '"></ul>');
                    var gMargin = (settings.vertical) ? 'margin-left' : 'margin-top';
                    $slide.parent().find('.lSPager').css(gMargin, settings.galleryMargin + 'px');
                    refresh.createPager();
                }

                setTimeout(function () {
                    refresh.init();
                }, 0);
            },
            setHeight: function (ob, fade) {
                var obj = null,
                    $this = this;
                if (settings.loop) {
                    obj = ob.children('.lslide ').first();
                } else {
                    obj = ob.children().first();
                }
                var setCss = function () {
                    var tH = obj.outerHeight(),
                        tP = 0,
                        tHT = tH;
                    if (fade) {
                        tH = 0;
                        tP = ((tHT) * 100) / elSize;
                    }
                    ob.css({
                        'height': 'auto',
                        'padding-bottom': tP + '%'
                    });
                };
                setCss();
                if (obj.find('img').length) {
                    if ( obj.find('img')[0].complete) {
                        setCss();
                        if (!interval) {
                            $this.auto();
                        }  
                    }else{
                        obj.find('img').on('load', function () {
                            setTimeout(function () {
                                setCss();
                                if (!interval) {
                                    $this.auto();
                                }
                            }, 100);
                        });
                    }
                }else{
                    if (!interval) {
                        $this.auto();
                    }
                }
            },
            active: function (ob, t) {
                if (this.doCss() && settings.mode === 'fade') {
                    $slide.addClass('on');
                }
                var sc = 0;
                if (scene * settings.slideMove < length) {
                    ob.removeClass('active');
                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.fadeOut(settings.speed);
                    }
                    if (t === true) {
                        sc = scene;
                    } else {
                        sc = scene * settings.slideMove;
                    }
                    //t === true ? sc = scene : sc = scene * settings.slideMove;
                    var l, nl;
                    if (t === true) {
                        l = ob.length;
                        nl = l - 1;
                        if (sc + 1 >= l) {
                            sc = nl;
                        }
                    }
                    if (settings.loop === true && settings.mode === 'slide') {
                        //t === true ? sc = scene - $el.find('.clone.left').length : sc = scene * settings.slideMove;
                        if (t === true) {
                            sc = scene - $el.find('.clone.left').length;
                        } else {
                            sc = scene * settings.slideMove;
                        }
                        if (t === true) {
                            l = ob.length;
                            nl = l - 1;
                            if (sc + 1 === l) {
                                sc = nl;
                            } else if (sc + 1 > l) {
                                sc = 0;
                            }
                        }
                    }

                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.eq(sc).fadeIn(settings.speed);
                    }
                    ob.eq(sc).addClass('active');
                } else {
                    ob.removeClass('active');
                    ob.eq(ob.length - 1).addClass('active');
                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.fadeOut(settings.speed);
                        ob.eq(sc).fadeIn(settings.speed);
                    }
                }
            },
            move: function (ob, v) {
                if (settings.rtl === true) {
                    v = -v;
                }
                if (this.doCss()) {
                    if (settings.vertical === true) {
                        ob.css({
                            'transform': 'translate3d(0px, ' + (-v) + 'px, 0px)',
                            '-webkit-transform': 'translate3d(0px, ' + (-v) + 'px, 0px)'
                        });
                    } else {
                        ob.css({
                            'transform': 'translate3d(' + (-v) + 'px, 0px, 0px)',
                            '-webkit-transform': 'translate3d(' + (-v) + 'px, 0px, 0px)',
                        });
                    }
                } else {
                    if (settings.vertical === true) {
                        ob.css('position', 'relative').animate({
                            top: -v + 'px'
                        }, settings.speed, settings.easing);
                    } else {
                        ob.css('position', 'relative').animate({
                            left: -v + 'px'
                        }, settings.speed, settings.easing);
                    }
                }
                var $thumb = $slide.parent().find('.lSPager').find('li');
                this.active($thumb, true);
            },
            fade: function () {
                this.active($children, false);
                var $thumb = $slide.parent().find('.lSPager').find('li');
                this.active($thumb, true);
            },
            slide: function () {
                var $this = this;
                refresh.calSlide = function () {
                    if (w > elSize) {
                        slideValue = $this.slideValue();
                        $this.active($children, false);
                        if ((slideValue) > w - elSize - settings.slideMargin) {
                            slideValue = w - elSize - settings.slideMargin;
                        } else if (slideValue < 0) {
                            slideValue = 0;
                        }
                        $this.move($el, slideValue);
                        if (settings.loop === true && settings.mode === 'slide') {
                            if (scene >= (length - ($el.find('.clone.left').length / settings.slideMove))) {
                                $this.resetSlide($el.find('.clone.left').length);
                            }
                            if (scene === 0) {
                                $this.resetSlide($slide.find('.lslide').length);
                            }
                        }
                    }
                };
                refresh.calSlide();
            },
            resetSlide: function (s) {
                var $this = this;
                $slide.find('.lSAction a').addClass('disabled');
                setTimeout(function () {
                    scene = s;
                    $slide.css('transition-duration', '0ms');
                    slideValue = $this.slideValue();
                    $this.active($children, false);
                    plugin.move($el, slideValue);
                    setTimeout(function () {
                        $slide.css('transition-duration', settings.speed + 'ms');
                        $slide.find('.lSAction a').removeClass('disabled');
                    }, 50);
                }, settings.speed + 100);
            },
            slideValue: function () {
                var _sV = 0;
                if (settings.autoWidth === false) {
                    _sV = scene * ((slideWidth + settings.slideMargin) * settings.slideMove);
                } else {
                    _sV = 0;
                    for (var i = 0; i < scene; i++) {
                        _sV += (parseInt($children.eq(i).width()) + settings.slideMargin);
                    }
                }
                return _sV;
            },
            slideThumb: function () {
                var position;
                switch (settings.currentPagerPosition) {
                case 'left':
                    position = 0;
                    break;
                case 'middle':
                    position = (elSize / 2) - (thumbWidth / 2);
                    break;
                case 'right':
                    position = elSize - thumbWidth;
                }
                var sc = scene - $el.find('.clone.left').length;
                var $pager = $slide.parent().find('.lSPager');
                if (settings.mode === 'slide' && settings.loop === true) {
                    if (sc >= $pager.children().length) {
                        sc = 0;
                    } else if (sc < 0) {
                        sc = $pager.children().length;
                    }
                }
                var thumbSlide = sc * ((thumbWidth + settings.thumbMargin)) - (position);
                if ((thumbSlide + elSize) > pagerWidth) {
                    thumbSlide = pagerWidth - elSize - settings.thumbMargin;
                }
                if (thumbSlide < 0) {
                    thumbSlide = 0;
                }
                this.move($pager, thumbSlide);
            },
            auto: function () {
                if (settings.auto) {
                    clearInterval(interval);
                    interval = setInterval(function () {
                        $el.goToNextSlide();
                    }, settings.pause);
                }
            },
            pauseOnHover: function(){
                var $this = this;
                if (settings.auto && settings.pauseOnHover) {
                    $slide.on('mouseenter', function(){
                        $(this).addClass('ls-hover');
                        $el.pause();
                        settings.auto = true;
                    });
                    $slide.on('mouseleave',function(){
                        $(this).removeClass('ls-hover');
                        if (!$slide.find('.lightSlider').hasClass('lsGrabbing')) {
                            $this.auto();
                        }
                    });
                }
            },
            touchMove: function (endCoords, startCoords) {
                $slide.css('transition-duration', '0ms');
                if (settings.mode === 'slide') {
                    var distance = endCoords - startCoords;
                    var swipeVal = slideValue - distance;
                    if ((swipeVal) >= w - elSize - settings.slideMargin) {
                        if (settings.freeMove === false) {
                            swipeVal = w - elSize - settings.slideMargin;
                        } else {
                            var swipeValT = w - elSize - settings.slideMargin;
                            swipeVal = swipeValT + ((swipeVal - swipeValT) / 5);

                        }
                    } else if (swipeVal < 0) {
                        if (settings.freeMove === false) {
                            swipeVal = 0;
                        } else {
                            swipeVal = swipeVal / 5;
                        }
                    }
                    this.move($el, swipeVal);
                }
            },

            touchEnd: function (distance) {
                $slide.css('transition-duration', settings.speed + 'ms');
                if (settings.mode === 'slide') {
                    var mxVal = false;
                    var _next = true;
                    slideValue = slideValue - distance;
                    if ((slideValue) > w - elSize - settings.slideMargin) {
                        slideValue = w - elSize - settings.slideMargin;
                        if (settings.autoWidth === false) {
                            mxVal = true;
                        }
                    } else if (slideValue < 0) {
                        slideValue = 0;
                    }
                    var gC = function (next) {
                        var ad = 0;
                        if (!mxVal) {
                            if (next) {
                                ad = 1;
                            }
                        }
                        if (!settings.autoWidth) {
                            var num = slideValue / ((slideWidth + settings.slideMargin) * settings.slideMove);
                            scene = parseInt(num) + ad;
                            if (slideValue >= (w - elSize - settings.slideMargin)) {
                                if (num % 1 !== 0) {
                                    scene++;
                                }
                            }
                        } else {
                            var tW = 0;
                            for (var i = 0; i < $children.length; i++) {
                                tW += (parseInt($children.eq(i).width()) + settings.slideMargin);
                                scene = i + ad;
                                if (tW >= slideValue) {
                                    break;
                                }
                            }
                        }
                    };
                    if (distance >= settings.swipeThreshold) {
                        gC(false);
                        _next = false;
                    } else if (distance <= -settings.swipeThreshold) {
                        gC(true);
                        _next = false;
                    }
                    $el.mode(_next);
                    this.slideThumb();
                } else {
                    if (distance >= settings.swipeThreshold) {
                        $el.goToPrevSlide();
                    } else if (distance <= -settings.swipeThreshold) {
                        $el.goToNextSlide();
                    }
                }
            },



            enableDrag: function () {
                var $this = this;
                if (!isTouch) {
                    var startCoords = 0,
                        endCoords = 0,
                        isDraging = false;
                    $slide.find('.lightSlider').addClass('lsGrab');
                    $slide.on('mousedown', function (e) {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        if ($(e.target).attr('class') !== ('lSPrev') && $(e.target).attr('class') !== ('lSNext')) {
                            startCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            isDraging = true;
                            if (e.preventDefault) {
                                e.preventDefault();
                            } else {
                                e.returnValue = false;
                            }
                            // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
                            $slide.scrollLeft += 1;
                            $slide.scrollLeft -= 1;
                            // *
                            $slide.find('.lightSlider').removeClass('lsGrab').addClass('lsGrabbing');
                            clearInterval(interval);
                        }
                    });
                    $(window).on('mousemove', function (e) {
                        if (isDraging) {
                            endCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            $this.touchMove(endCoords, startCoords);
                        }
                    });
                    $(window).on('mouseup', function (e) {
                        if (isDraging) {
                            $slide.find('.lightSlider').removeClass('lsGrabbing').addClass('lsGrab');
                            isDraging = false;
                            endCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            var distance = endCoords - startCoords;
                            if (Math.abs(distance) >= settings.swipeThreshold) {
                                $(window).on('click.ls', function (e) {
                                    if (e.preventDefault) {
                                        e.preventDefault();
                                    } else {
                                        e.returnValue = false;
                                    }
                                    e.stopImmediatePropagation();
                                    e.stopPropagation();
                                    $(window).off('click.ls');
                                });
                            }

                            $this.touchEnd(distance);

                        }
                    });
                }
            },




            enableTouch: function () {
                var $this = this;
                if (isTouch) {
                    var startCoords = {},
                        endCoords = {};
                    $slide.on('touchstart', function (e) {
                        endCoords = e.originalEvent.targetTouches[0];
                        startCoords.pageX = e.originalEvent.targetTouches[0].pageX;
                        startCoords.pageY = e.originalEvent.targetTouches[0].pageY;
                        clearInterval(interval);
                    });
                    $slide.on('touchmove', function (e) {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        var orig = e.originalEvent;
                        endCoords = orig.targetTouches[0];
                        var xMovement = Math.abs(endCoords.pageX - startCoords.pageX);
                        var yMovement = Math.abs(endCoords.pageY - startCoords.pageY);
                        if (settings.vertical === true) {
                            if ((yMovement * 3) > xMovement) {
                                e.preventDefault();
                            }
                            $this.touchMove(endCoords.pageY, startCoords.pageY);
                        } else {
                            if ((xMovement * 3) > yMovement) {
                                e.preventDefault();
                            }
                            $this.touchMove(endCoords.pageX, startCoords.pageX);
                        }

                    });
                    $slide.on('touchend', function () {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        var distance;
                        if (settings.vertical === true) {
                            distance = endCoords.pageY - startCoords.pageY;
                        } else {
                            distance = endCoords.pageX - startCoords.pageX;
                        }
                        $this.touchEnd(distance);
                    });
                }
            },
            build: function () {
                var $this = this;
                $this.initialStyle();
                if (this.doCss()) {

                    if (settings.enableTouch === true) {
                        $this.enableTouch();
                    }
                    if (settings.enableDrag === true) {
                        $this.enableDrag();
                    }
                }

                $(window).on('focus', function(){
                    $this.auto();
                });
               
                $(window).on('blur', function(){
                    clearInterval(interval);
                });

                $this.pager();
                $this.pauseOnHover();
                $this.controls();
                $this.keyPress();
            }
        };
        plugin.build();
        refresh.init = function () {
            refresh.chbreakpoint();
            if (settings.vertical === true) {
                if (settings.item > 1) {
                    elSize = settings.verticalHeight;
                } else {
                    elSize = $children.outerHeight();
                }
                $slide.css('height', elSize + 'px');
            } else {
                elSize = $slide.outerWidth();
            }
            if (settings.loop === true && settings.mode === 'slide') {
                refresh.clone();
            }
            refresh.calL();
            if (settings.mode === 'slide') {
                $el.removeClass('lSSlide');
            }
            if (settings.mode === 'slide') {
                refresh.calSW();
                refresh.sSW();
            }
            setTimeout(function () {
                if (settings.mode === 'slide') {
                    $el.addClass('lSSlide');
                }
            }, 1000);
            if (settings.pager) {
                refresh.createPager();
            }
            if (settings.adaptiveHeight === true && settings.vertical === false) {
                $el.css('height', $children.eq(scene).outerHeight(true));
            }
            if (settings.adaptiveHeight === false) {
                if (settings.mode === 'slide') {
                    if (settings.vertical === false) {
                        plugin.setHeight($el, false);
                    }else{
                        plugin.auto();
                    }
                } else {
                    plugin.setHeight($el, true);
                }
            }
            if (settings.gallery === true) {
                plugin.slideThumb();
            }
            if (settings.mode === 'slide') {
                plugin.slide();
            }
            if (settings.autoWidth === false) {
                if ($children.length <= settings.item) {
                    $slide.find('.lSAction').hide();
                } else {
                    $slide.find('.lSAction').show();
                }
            } else {
                if ((refresh.calWidth(false) < elSize) && (w !== 0)) {
                    $slide.find('.lSAction').hide();
                } else {
                    $slide.find('.lSAction').show();
                }
            }
        };
        $el.goToPrevSlide = function () {
            if (scene > 0) {
                settings.onBeforePrevSlide.call(this, $el, scene);
                scene--;
                $el.mode(false);
                if (settings.gallery === true) {
                    plugin.slideThumb();
                }
            } else {
                if (settings.loop === true) {
                    settings.onBeforePrevSlide.call(this, $el, scene);
                    if (settings.mode === 'fade') {
                        var l = (length - 1);
                        scene = parseInt(l / settings.slideMove);
                    }
                    $el.mode(false);
                    if (settings.gallery === true) {
                        plugin.slideThumb();
                    }
                } else if (settings.slideEndAnimation === true) {
                    $el.addClass('leftEnd');
                    setTimeout(function () {
                        $el.removeClass('leftEnd');
                    }, 400);
                }
            }
        };
        $el.goToNextSlide = function () {
            var nextI = true;
            if (settings.mode === 'slide') {
                var _slideValue = plugin.slideValue();
                nextI = _slideValue < w - elSize - settings.slideMargin;
            }
            if (((scene * settings.slideMove) < length - settings.slideMove) && nextI) {
                settings.onBeforeNextSlide.call(this, $el, scene);
                scene++;               
                $el.mode(false);
                if (settings.gallery === true) {
                    plugin.slideThumb();
                }
            } else {                
                //if (settings.loop === true || settings.loop === false) {
                    settings.onBeforeNextSlide.call(this, $el, scene);
                    scene = 0;
                    $el.mode(false);
                    if (settings.gallery === true) {
                        plugin.slideThumb();
                    }
            //} else
            if (settings.slideEndAnimation === true) {
                    $el.addClass('rightEnd');
                    setTimeout(function () {
                        $el.removeClass('rightEnd');
                    }, 400);
                }
            }
        };
        $el.mode = function (_touch) {
            if (settings.adaptiveHeight === true && settings.vertical === false) {
                $el.css('height', $children.eq(scene).outerHeight(true));
            }
            if (on === false) {
                if (settings.mode === 'slide') {
                    if (plugin.doCss()) {
                        $el.addClass('lSSlide');
                        if (settings.speed !== '') {
                            $slide.css('transition-duration', settings.speed + 'ms');
                        }
                        if (settings.cssEasing !== '') {
                            $slide.css('transition-timing-function', settings.cssEasing);
                        }
                    }
                } else {
                    if (plugin.doCss()) {
                        if (settings.speed !== '') {
                            $el.css('transition-duration', settings.speed + 'ms');
                        }
                        if (settings.cssEasing !== '') {
                            $el.css('transition-timing-function', settings.cssEasing);
                        }
                    }
                }
            }
            if (!_touch) {
                settings.onBeforeSlide.call(this, $el, scene);
            }
            if (settings.mode === 'slide') {
                plugin.slide();
            } else {
                plugin.fade();
            }
            if (!$slide.hasClass('ls-hover')) {
                plugin.auto();
            }
            setTimeout(function () {
                if (!_touch) {
                    settings.onAfterSlide.call(this, $el, scene);
                }
            }, settings.speed);
            on = true;
        };
        $el.play = function () {
            $el.goToNextSlide();
            settings.auto = true;
            plugin.auto();
        };
        $el.pause = function () {
            settings.auto = false;
            clearInterval(interval);
        };
        $el.refresh = function () {
            refresh.init();
        };
        $el.getCurrentSlideCount = function () {
            var sc = scene;
            if (settings.loop) {
                var ln = $slide.find('.lslide').length,
                    cl = $el.find('.clone.left').length;
                if (scene <= cl - 1) {
                    sc = ln + (scene - cl);
                } else if (scene >= (ln + cl)) {
                    sc = scene - ln - cl;
                } else {
                    sc = scene - cl;
                }
            }
            return sc + 1;
        };
        $el.getTotalSlideCount = function () {
            return $slide.find('.lslide').length;
        };
        $el.goToSlide = function (s) {
            if (settings.loop) {
                scene = (s + $el.find('.clone.left').length - 1);
            } else {
                scene = s;
            }
            $el.mode(false);
            if (settings.gallery === true) {
                plugin.slideThumb();
            }
        };
        $el.destroy = function () {
            if ($el.lightSlider) {
                $el.goToPrevSlide = function(){};
                $el.goToNextSlide = function(){};
                $el.mode = function(){};
                $el.play = function(){};
                $el.pause = function(){};
                $el.refresh = function(){};
                $el.getCurrentSlideCount = function(){};
                $el.getTotalSlideCount = function(){};
                $el.goToSlide = function(){};
                $el.lightSlider = null;
                refresh = {
                    init : function(){}
                };
                $el.parent().parent().find('.lSAction, .lSPager').remove();
                $el.removeClass('lightSlider lSFade lSSlide lsGrab lsGrabbing leftEnd right').removeAttr('style').unwrap().unwrap();
                $el.children().removeAttr('style');
                $children.removeClass('lslide active');
                $el.find('.clone').remove();
                $children = null;
                interval = null;
                on = false;
                scene = 0;
            }

        };
        setTimeout(function () {
            settings.onSliderLoad.call(this, $el);
        }, 10);
        $(window).on('resize orientationchange', function (e) {
            setTimeout(function () {
                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    e.returnValue = false;
                }
                refresh.init();
            }, 200);
        });
        return this;
    };
}(jQuery));




Lightslider.css
/*! lightslider - v1.1.6 - 2016-10-25
* https://github.com/sachinchoolur/lightslider
* Copyright (c) 2016 Sachin N; Licensed MIT */
/*! lightslider - v1.1.3 - 2015-04-14
* https://github.com/sachinchoolur/lightslider
* Copyright (c) 2015 Sachin N; Licensed MIT */

/** /!!! core css Should not edit !!!/**/
/*  updates for thumbnail rotator -
    added the below css for the purpose of thumbnail image and title alignment
    .image-fixed-width,
    #content-slider li img,
    #content-slider li,
    #content-slider li span */
.lSSlideOuter {
    overflow: hidden;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.lightSlider:before, .lightSlider:after {
    content: " ";
    display: table;
}

.lightSlider {
    overflow: hidden;
    margin: 0;
}

.lSSlideWrapper {
    max-width: 100%;
    overflow: hidden;
    position: relative;
}

.lSSlideWrapper > .lightSlider:after {
    clear: both;
}


.lSSlideWrapper .lSSlide {
    -webkit-transform: translate(0px, 0px);
    -ms-transform: translate(0px, 0px);
    transform: translate(0px, 0px);
    -webkit-transition: all 1s;
    -webkit-transition-property: -webkit-transform,height;
    -moz-transition-property: -moz-transform,height;
    transition-property: transform,height;
    -webkit-transition-duration: inherit !important;
    transition-duration: inherit !important;
    -webkit-transition-timing-function: inherit !important;
    transition-timing-function: inherit !important;
}

.lSSlideWrapper .lSFade {
    position: relative;
}

.lSSlideWrapper .lSFade > * {
    position: absolute !important;
    top: 0;
    left: 0;
    z-index: 9;
    margin-right: 0;
    width: 100%;
}

.lSSlideWrapper.usingCss .lSFade > * {
    opacity: 0;
    -webkit-transition-delay: 0s;
    transition-delay: 0s;
    -webkit-transition-duration: inherit !important
    transition-duration: inherit !important
    -webkit-transition-property: opacity;
    transition-property: opacity;
    -webkit-transition-timing-function: inherit !important;
    transition-timing-function: inherit !important;

.lSSlideWrapper .lSFade > *.active {
        z-index: 10;
}

.lSSlideWrapper.usingCss .lSFade > *.active {
        opacity: 1;
}
/** /!!! End of core css Should not edit !!!/**/

/* Pager */
.lSSlideOuter .lSPager.lSpg {
    margin: 10px 0 0;
    padding: 0;
    text-align: center;
}

.lSSlideOuter .lSPager.lSpg > li {
    cursor: pointer;
    display: inline-block;
    padding: 0 5px;
}

.lSSlideOuter .lSPager.lSpg > li a {
   /*light grey */
   background-color: #d8d8d8;
   border-radius: 30px;
   display: inline-block;
   height: 8px;
   overflow: hidden;
   text-indent: -999em;
   width: 8px;
   position: relative;
   z-index: 99;
   -webkit-transition: all 0.5s linear 0s;
   transition: all 0.5s linear 0s;
}

.lSSlideOuter .lSPager.lSpg > li:hover a, .lSSlideOuter .lSPager.lSpg > li.active a {
   /* dark maroon*/
   background-color: #a54d5b;
}

.lSSlideOuter .media {
    opacity: 0.8;
}

    .lSSlideOuter .media.active {
        opacity: 1;
    }
/* End of pager */


/* Right and left control */
.lSSlideOuter.lSrtl {
    direction: rtl;
}

.lSSlideOuter .lightSlider, .lSSlideOuter .lSPager {
    padding-left: 0;
    list-style: none outside none;
}

.lSSlideOuter.lSrtl .lightSlider, .lSSlideOuter.lSrtl .lSPager {
    padding-right: 0;
}

.lSSlideOuter .lightSlider > *, .lSSlideOuter .lSGallery li {
    float: left;
}

.lSSlideOuter.lSrtl .lightSlider > *, .lSSlideOuter.lSrtl .lSGallery li {
    float: right !important;
}


.lSSlideOuter .rightEnd {
    -webkit-animation: rightEnd 0.3s;
    animation: rightEnd 0.3s;
    position: relative;
}

.lSSlideOuter .leftEnd {
    -webkit-animation: leftEnd 0.3s;
    animation: leftEnd 0.3s;
    position: relative;
}

.lSSlideOuter.vertical .rightEnd {
    -webkit-animation: topEnd 0.3s;
    animation: topEnd 0.3s;
    position: relative;
}

.lSSlideOuter.vertical .leftEnd {
    -webkit-animation: bottomEnd 0.3s;
    animation: bottomEnd 0.3s;
    position: relative;
}

.lSSlideOuter.lSrtl .rightEnd {
    -webkit-animation: leftEnd 0.3s;
    animation: leftEnd 0.3s;
    position: relative;
}

.lSSlideOuter.lSrtl .leftEnd {
    -webkit-animation: rightEnd 0.3s;
    animation: rightEnd 0.3s;
    position: relative;
}


/*Thumbnail image style*/
.image-fixed-width {
    float: left;
    min-width: 110px;
    max-width: 110px;
    max-height: 90px;
    min-height: 90px;
    margin: 0px;
    padding: 0px;
}

/*adds border to the thumbnail image*/
#content-slider li img {
    text-align: center;
    border: 2px solid #fcf9f9;
}

/*style for thumbnail image + span containg the title*/
#content-slider li {
    text-align: center;
    background-color: transparent;
    width: 110px;
    height: auto;
    display: block;
    float: left;
}

/* thumbnail image title styling*/
#content-slider li span {
    float: left;
    width: 100%;
    overflow: hidden;
    text-align: left;
    color: #036d9b;
}

That's it we completed it in around 3 weeks.

Please post in your comments or feedbacks.