Thursday, June 25, 2015

Kendo UI ListView Infinite Scroll for Non-Mobile ListView

The Kendo UI non-mobile ListView does not come with infinite scrolling. However, I've managed to invent a hack which makes it work for cases where the ListView items are read-only. This solution uses a ListView to fetch new pages of data while a div above it holds all previous pages of data.

The Kendo UI non-mobile ListView does not come with infinite scrolling.  However, I've managed to invent a hack which makes it work for cases where the ListView items are read-only.

This solution uses a ListView to fetch new pages of data while a div above it holds all previous pages of data.

    <div id="noResults"></div>
    <div id="listPrev"></div>  <!-- Archive of previous pages -->
    <div id="list"></div>  <!-- ListView to fetch new pages of data -->
    <div id="loading">

    <script id="myTemplate" type="text/x-kendo-tmpl">
        <!-- Kendo template goes here -->
    </script>

    <script>

    var viewModel = kendo.observable({
        MyObjects: [],
        PreviousScrollPosition: 0,
        FetchMore: true
    });

    $(document).ready(function () {
        $("#list").kendoListView({
            template: kendo.template($("#myTemplate").html()),
            autoBind: true,
            dataSource: getDataSource(),

            dataBound: function() {
                viewModel.FetchMore = true;
            }
        });
        kendo.bind(document.body, viewModel);
    });

    function getDataSource()
    {
        return new kendo.data.DataSource({
            data: viewModel.Interactions,
            pageSize: viewModel.MyObjects,
            schema: {}
            }
        });
    }

    // Handle scroll Event
    $(window).scroll(function() {
        var scrolled = Math.max(Math.max(document.body.scrollTop, (window.pageYOffset - 1)), 0);
        // Anytime user scrolls to the bottom
        if (isScrolledToBottom(viewModel.ScrollBottomPadding) === true) {
            // Get data for infinite scroll
            infiniteScrollDown();
        }
        viewModel.PreviousScrollPosition = scrolled;
    });

    function isScrolledToBottom(buffer) {
            var pageHeight = document.body.scrollHeight;
            // NOTE:  IE and the other browsers handle scrollTop and pageYOffset differently
            var pagePosition = document.body.offsetHeight + Math.max(document.body.scrollTop, (window.pageYOffset - 1));
            buffer = buffer || 0;
            return pagePosition >= (pageHeight - buffer);
    }

    function infiniteScrollDown() {
        console.log("infiniteScrollDown()");
        viewModel.FetchMore = false;
        // For endless scrolling:  Append contents of ListView to div above the ListView.
        $("#listPrev").append($("#list").html());
        // Add new page of data to the bottom of the Infinite scroll.
        var lv = $("#list").data("kendoListView").dataSource;
        lv.page(lv.page() +1);
    }

    </script>

Wednesday, June 24, 2015

Pure CSS Cross-Browser Multi-Line Text with Ellipsis

There are two common ways to do Multi-Line text with ellipsis.  The first is to use CSS that only works on webkit browsers.  The second is to use a javascript plugin.  Below is a third solution that uses pure CSS and works for all browsers.

Lorem ipsum dolor sit amet, consectetur eu in adipiscing elit. Aliquam consectetur venenatis blandit. Praesent vehicula, libero non pretium vulputate, lacus arcu facilisis lectus, sed feugiat tellus nulla eu dolor. Nulla porta bibendum lectus quis euismod. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat.
...


[div class="container"]
    [div class="text"]
        [[Text]]
    [/div]
    [div class="ellipsis"]...[/div]
[/div]


[style]
    body {
       margin: 20px;
    }
    .container{
        position: relative;
        background-color: #bbb;
        padding: 20px;
    }
    .text {
       overflow: hidden;
       /*text-overflow: ellipsis; Not needed */
       line-height: 16px;
       max-height: 48px; /* Multiples of line-height */
    }
    .ellipsis {
        position: absolute;
        bottom: 20px;
        right: 20px;
        height: 16px;
        width: 30px;
        background-color: inherit;
        padding-left: 8px;
    }

[/style]

The pure css solution works when the text overflows the available space. However, short text strings do not overflow the space and should not be given an ellipsis.

To solve the short text problem, Implement the javascript solution, below, as well:

[script]
    function getTextWidth(text, font) {
        var canvas = getTextWidth.canvas ||
            (getTextWidth.canvas = document.createElement("canvas"));
        var context = canvas.getContext("2d");
        context.font = font;
        var metrics = context.measureText(text);
        return metrics.width;
    };

    $(".container").each(function() {
        if (getTextWidth(
            $(this).find(".text").text(),
            $(this).find(".text").css("font")
            ) < ($(this).find(".text").width() * 3)) {  // Multiplier is number of lines to show
                $(this).find(".ellipsis").remove();
            }
    });

[/script]