Showing posts with label pagination. Show all posts
Showing posts with label pagination. Show all posts

Friday, March 17, 2017

How to Paginate Data With PHP

Its sometime we found that we need a pagination but its difficult to make it as easy as we think. Below is a code snippet to make an standard pagination system using PHP code. Its nothing but you have to pass some arguments to make a better pagination system.

$paginator = new stdClass();
$paginator->total = 444;
$paginator->limit = 10;
$paginator->page = 1;
$paginator->links = 5;
$paginator->list_class = "pagination";
$paginator->link = "/users/list?q=value;
 
$html = makePaginationHtml($paginator); 
 
function makePaginationHtml($paginator)
{
    $last = ceil($paginator->total / $paginator->limit);
    $start = (($paginator->page - $paginator->links) > 0) ? $paginator->page - $paginator->links : 1;
    $end = (($paginator->page + $paginator->links) < $last) ? $paginator->page + $paginator->links : $last;
    $html = '<ul class="' . $paginator->list_class . '">';
    $link = $paginator->link;

    if ($paginator->page > 1) {
        $html .= '<li class=""><a href="' . $link . '&limit=' . $paginator->limit;
        $html .= '&page=' . ($paginator->page - 1) . '">&laquo;</a></li>';
    }
    if ($start > 1) {
        $html .= '<li><a href="' . $link . '&limit=' . $paginator->limit . '&page=1">1</a></li>';
        $html .= '<li class="disabled"><span>...</span></li>';
    }
    for ($i = $start; $i <= $end; $i++) {
        $class = ($paginator->page == $i) ? "active" : "";
        $html .= '<li class="' . $class . '"><a href="' . $link . '&limit=';
        $html .= $paginator->limit . '&page=' . $i . '">' . $i . '</a></li>';
    }
    if ($end < $last) {
        $html .= '<li class="disabled"><span>...</span></li>';
        $html .= '<li><a href="' . $link . '&limit=' . $paginator->limit . '&page=';
        $html .= $last . '">' . $last . '</a></li>';
    }
    if ($paginator->page != $last) {
        $html .= '<li class=""><a href="' . $link . '&limit=' . $paginator->limit;
        $html .= '&page=' . ($paginator->page + 1) . '">&raquo;</a></li>';
    }
    $html .= '</ul>';
    return $html;
}

Wednesday, July 3, 2013

Cloudant search by indexes and set limit pagination


$cloudantLimit = 2;
$posts = array(
    "q" => "customerID:cid_100",
    "include_docs" => "true",
    "sort" => json_encode("-createdStamp"),
    "limit" => $cloudantLimit
);
$totalResult = array();
$bookmark = null;
$skip = 0;
while(true) {
    if($bookmark != null) {
        $posts["bookmark"] = $bookmark;
    }
    $loadMore = false;
    $result = getTransactionHistory($this->userName, $this->password, $posts);
    if($result != null && isset($result["code"]) && $result["code"] == 200 && isset($result["response"]) && strlen(trim($result["response"])) > 0) {
        $result200 = json_decode($result["response"]);
        if(isset($result200->total_rows)
            && isset($result200->bookmark)
            && isset($result200->rows) && is_array($result200->rows) && count($result200->rows) > 0) {
            $bookmark = $result200->bookmark;
            array_push($totalResult, $result["response"]);
            $skip = $skip + $cloudantLimit;
            if($result200->total_rows > $skip) {
                $loadMore = true;
            }
        }
    }
    if(!$loadMore) {
        break;
    }
}

function getTransactionHistory($userName, $password, $posts = null) {
    $headers[0] = "Authorization: Basic " . base64_encode("$userName:$password");
    $headers[1] = "Content-Type: application/json";

    return makeCurlCall(
        "https://$userName.cloudant.com/transactions/_design/views103/_search/animals",
        "GET",
        $headers,
        $posts
    );
}

function makeCurlCall($url, $method = "GET", $headers = null, $gets = null, $posts = null) {
    $ch = curl_init();
    if($gets != null)
    {
        $url.="?".(http_build_query($gets));
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    if($posts != null)
    {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $posts);
    }
    if($method == "POST") {
        curl_setopt($ch, CURLOPT_POST, true);
    } else if($method == "PUT") {
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
    } else if($method == "HEAD") {
        curl_setopt($ch, CURLOPT_NOBODY, true);
    }
    if($headers != null && is_array($headers))
    {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    $response = curl_exec($ch);
    $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);

    curl_close($ch);
    return array(
        "code" => $code,
        "response" => $response
    );
}

Saturday, June 1, 2013

jQuery custom pagination class

Html data load as follows:

<input type="hidden" class="contact_admin_total_row_count" value="5"/>
<input type="hidden" class="contact_admin_pagination_limit" value="2"/>
<input type="hidden" class="contact_admin_total_row_found" value="1"/>

<table class="table_design_1">
/* data row here */ 
</table> 

Start pagination as follows:


var options = {
    currentPage: 1,
    loadUrl: BASE_URL + "contact/admin",
    autoLoad: true,
    total: parseInt(jQuery(".contact_admin_total_row_count").attr("value")),
    limit: parseInt(jQuery(".contact_admin_pagination_limit").attr("value")),
    totalFinderId: ".contact_admin_total_row_count",
    resultCountElm: ".contact_admin_total_row_found",
    counter: 100
};
jQuery(".table_design_1").startPagination(options, 
function(paginationCounterId,options,elm,afterCall,targetUrl,currentPage) {
    /* after some work done, refresh pagination */
    elm.refreshPagination(paginationCounterId,options,elm,afterCall,targetUrl,currentPage); 
});

And the pagination class

var paginationCounter = 1;
jQuery.fn.startPagination = function(opts, afterCall) {
    var elm = jQuery(this);
    jQuery.fn.startPagination.defaults = {
        loadUrl: "", /* Define data load url, suppose: http://pritom.com/blog_list */
        total: 5, /* Define total number of items, such 200 */
        limit: 20, /* Define pagination limit such 20 items per page */
        currentPage: 1, /* Current selected page, if 2 then items from 20-39 would load */
        place: "both", /* Pagination link for both upper and lower portion, options: ['top', 'bottom', 'both'] */
        directHtml: false, /* Would replace direct html to element or search in body */
        counter: 0, /* If one page contains more than one pagination list use integer number to defferentiate them */
        offset: 0, /* Start loading index */
        configs: {},
        sortClass: 0, /* make a header class 'sortable' to make data table sortable and define property 'sort-data'
         * to set sort data. */
        sortType: "",
        formParams: {}, /* If any params value need to submit as POST */
        showPagination: true,
        changeBrowserHistory: false, /* Change browser url if you refresh the page */
        browserHistoryURL: null, /* Then define browser history url: http://pritom.com/blog_list */
        autoLoad: false, /* Load first time if needed */
        totalFinderId: null, /* jQuery element to find total items found for re-organize pagination */
        resultCountElm: null, /* jQuery element to find current items loaded for re-load pagination if zero result found */
        parentDiv: null, /* Define if possible a parent div */
        limitFinderElm: null  /* jQuery element to find limit to paginate */
    };
    var options = $.extend(jQuery.fn.startPagination.defaults, opts);
    var paginationCounterId = null;
    if(options.counter == null || isNaN(options.counter) || options.counter == 0) {
        options.counter = paginationCounter++;
    }

    options.offset = parseInt(options.offset);
    if(isNaN(options.offset)) {
        return;
    }
    options.limit = parseInt(options.limit);
    if(isNaN(options.limit)) {
        return;
    }

    if(options.counter != 0) {
        paginationCounterId = "paginationCounter"+options.counter;
    }
    jQuery("."+paginationCounterId).remove();

    var total = parseInt(options.total);
    if(isNaN(total)) {
        return;
    }
    var limit = parseInt(options.limit);
    if(isNaN(limit)) {
        return;
    }
    var start = options.currentPage * limit;
    var pageCount = Math.ceil(total / limit);
    if(options.offset != 0) {
        start = options.offset;
        options.currentPage = Math.ceil(start/ limit) + 1;
    }
    if(isNaN(options.currentPage)) {
        options.currentPage = 1;
    }
    var propertyElm = "<input type='hidden' class='url' value='"+options.loadUrl+"'/>";
    propertyElm += "<input type='hidden' class='limit' value='"+limit+"'/>";
    var pages = [];
    var hasPrevious = 1;
    var hasNext = pageCount;
    if(options.currentPage == 1) {
        pages.push(1);
        if(pageCount >= 2) {
            pages.push(2);
        }
        if(pageCount > 2) {
            pages.push(3);
        }
    } else if(options.currentPage == pageCount) {
        if(pageCount - 2 > 0) {
            pages.push(pageCount - 2);
        }
        if(pageCount - 1 > 0) {
            pages.push(pageCount - 1);
        }
        pages.push(pageCount);
    } else {
        if(pageCount - 1 > 0) {
            pages.push(options.currentPage - 1);
        }
        pages.push(options.currentPage);
        if(options.currentPage + 1 <= pageCount) {
            pages.push(options.currentPage + 1);
        }
    }
    var classElm = "<style type=\"text/css\">" +
        ".pagination-disable {" +
        "    pointer-events: none;" +
        "}" +
        "";
    var hasPreviousClass = " pagination-disable ";
    var hasNextClass = " pagination-disable ";
    if(options.currentPage > 1) {
        hasPrevious = options.currentPage - 1;
        hasPreviousClass = "";
    }
    if(options.currentPage < pageCount) {
        hasNext = options.currentPage + 1;
        hasNextClass = "";
    }
    classElm += "</style>";
    var firstPage = "<a href='javascript:void(0)' pc='1' class='pagination-link pagination-first "+hasPreviousClass+"'><span>First&nbsp;</span></a>";
    var lastPage = "<a href='javascript:void(0)' pc='"+pageCount+"' class='pagination-link pagination-last "+hasNextClass+"'><span>&nbsp;Last</span></a>";
    var prevPage = "<a href='javascript:void(0)' pc='"+hasPrevious+"' class='pagination-link pagination-prev "+hasPreviousClass+"'><span>Prev</span></a>";
    var nextPage = "<a href='javascript:void(0)' pc='"+hasNext+"' class='pagination-link pagination-next "+hasNextClass+"'><span>Next</span></a>";
    var middlePage = "";
    jQuery.each(pages, function() {
        var _n = this;
        if(_n == options.currentPage) {
            middlePage += "<a href='javascript:void(0)' pc='"+_n+"' class='pagination-link pagination-next pagination-disable pagination-active'><span>&nbsp;"+_n+"&nbsp;</span></a>";
        } else {
            middlePage += "<a href='javascript:void(0)' pc='"+_n+"' class='pagination-link pagination-next'><span>&nbsp;"+_n+"&nbsp;</span></a>";
        }
    });
    var showingPage = "<span class='showing'>Showing "+((options.currentPage*options.limit)-options.limit+1)
        +" - "+((options.currentPage*options.limit)>options.total ? options.total : (options.currentPage*options.limit))+" of "+options.total+"</span>";
    var paginationElm = "<div class='PAGINATION_POSITION pagination "+paginationCounterId+"'>"+propertyElm;
    paginationElm += "<div class='sub-pagination'>";
    paginationElm += showingPage+firstPage+prevPage+middlePage+nextPage+lastPage;
    paginationElm += classElm+"</div></div>";
    if(options.showPagination == true && total > 0 && pageCount > 1) {
        if(options.place == "both") {
            elm.after(paginationElm.replace("PAGINATION_POSITION", "pagination_bottom "+paginationCounterId+"_bottom"));
            elm.before(paginationElm.replace("PAGINATION_POSITION", "pagination_top "+paginationCounterId+"_top"));
        } else if(options.place == "top") {
            elm.before(paginationElm.replace("PAGINATION_POSITION", "pagination_top "+paginationCounterId+"_top"));
        } else {
            elm.after(paginationElm.replace("PAGINATION_POSITION", "pagination_bottom "+paginationCounterId+"_bottom"));
        }
    }
    /**
     * START SORTING AND SEARCHING PROCESS
     */
    startSorting(paginationCounterId,options,elm,afterCall);
    startSearching(paginationCounterId,options,elm,afterCall);

    jQuery("body").find("."+paginationCounterId).delegate(".pagination-link", "click", function() {
        var elmTargetClick = jQuery(this);
        paginationLinkClickEvent(options, paginationCounterId, elm, afterCall, elmTargetClick);
    });
    if(options.autoLoad == true) {
        options.autoLoad = false;
        paginationLinkClickEvent(options, paginationCounterId, elm, afterCall, jQuery("body").find("."+paginationCounterId).find(".pagination-active"));
    }
};
function paginationLinkClickEvent(options, paginationCounterId, elm, afterCall, elmTargetClick) {
    var linkElm = elmTargetClick;
    var pc = parseInt(jQuery.trim(linkElm.attr("pc")));
    if(isNaN(pc)){
        pc = 1;
    }
    options.currentPage = pc;
    var limit = options.limit;
    var offset = (parseInt(pc) * parseInt(limit)) - parseInt(limit);
    setBrowserHistoryIfNeed(options, offset, limit);
    elm.refreshPagination(paginationCounterId,options,elm,afterCall);
}
function setBrowserHistoryIfNeed(options, offset, limit) {
    if(options.changeBrowserHistory == true) {
        if(options.browserHistoryURL != null) {
            var theURL = options.browserHistoryURL;
            if(theURL.indexOf("?") >= 0) {
                theURL = theURL + "&offset="+offset+"&limit="+limit;
            } else {
                theURL = theURL + "?offset="+offset+"&limit="+limit;
            }
            jQuery.setBrowserHistoryToCurrentState(theURL);
        }
    }
}
function startSorting(paginationCounterId,options,elm,afterCall) {
    paginationCounterId += "Sortable";
    var clickImage = "<span sortType='asc' class='img img-asc'><img style='cursor: pointer;' border='0' src='"+BASE_URL+"images/sort.png'/></span>";
    var clickImageReverse = "<span sortType='desc' class='img img-desc'><img style='cursor: pointer;' border='0' src='"+BASE_URL+"images/sort_r.png'/></span>";
    var clickMe = "<span class='sort-click "+paginationCounterId+"'><span class='sort-text'>"+clickImage+clickImageReverse+"</span></span>";
    var sortNumber = 0;
    elm.find(".sortable").each(function() {
        sortNumber++;
        var mainElm = jQuery(this);

        var sortBy = mainElm.attr("sort-data");
        if(sortBy === undefined) {
            console.log("sort by undefined");
            return;
        }
        mainElm.append(clickMe);
        mainElm.find(".sort-click").attr("sort-number", sortNumber);
        if(sortNumber == options.sortClass) {
            mainElm.find(".sort-click").addClass("active-"+options.sortType);
            mainElm.find(".sort-click").find(".img-"+options.sortType).remove();
        }
        mainElm.find(".img").bind("click", function() {
            var sortElm = jQuery(this);
            elm.find(".img").removeClass("active");
            sortElm.addClass("active");
            var sortType = jQuery(this).attr("sortType");
            if(sortType === undefined) {
                sortType = "asc";
            }
            if(sortType != "asc" && sortType != "desc") {
                sortType = "asc";
            }
            sortElm.closest(".sort-click").removeClass("asc").removeClass("desc");
            sortElm.closest(".sort-click").addClass(sortType);
            options.sortClass = sortElm.closest(".sort-click").attr("sort-number");
            options.sortType = sortType;
            options.configs['sortBy'] = sortBy;
            options.configs['sortType'] = sortType;
            elm.refreshPagination(paginationCounterId,options,elm,afterCall);
            return false;
        });
        mainElm.bind("click", function() {
            var sortElm = null;
            if(jQuery(this).find("span.sort-click").find("span.img-asc").length) {
                sortElm = jQuery(this).find("span.sort-click").find("span.img-asc");
            } else if(jQuery(this).find("span.sort-click").find("span.img-desc").length) {
                sortElm = jQuery(this).find("span.sort-click").find("span.img-desc");
            } else {
                return false;
            }
            sortElm.trigger("click");
            return false;
        });
    });
}
function startSearching(paginationCounterId,options,elm,afterCall) {
    paginationCounterId += "Searchable";
    var sortNumber = 0;
    console.log(".searchable class to header make it searchabge by rendering a text box");
    elm.find(".searchable").each(function() {
        sortNumber++;
        var mainElm = jQuery(this);
        var search_name = mainElm.attr("search_name");
        if(search_name === undefined) {
            console.log("need attribute 'search_name'");
            return;
        }
        var clickMe = "<div style='clear: both;'></div>" +
            "<input type='text' class='search_txt' placeholder='Enter search value' name='"+search_name+"' />";
        mainElm.append(clickMe);
        mainElm.find(".search_txt").change(function() {
            var searchValue = jQuery.trim(jQuery(this).attr("value"));
            options.formParams["__s[" + search_name + "]"] = searchValue;
            loadPaginationData(paginationCounterId,options,elm,afterCall);
        });
        mainElm.find(".search_txt").keypress(function(event) {
            if(event.which == 13) {
                jQuery(this).trigger("change");
            }
        });
    });
}
jQuery.fn.refreshPagination = function(paginationCounterId,options,elm,afterCall) {
    var elm = jQuery(this);
    var appendTo = jQuery("body");
    var pageHeight = parseInt(appendTo.css("height").replace(/px/g, "")) + jQuery("body").scrollTop();
    var pageWidth = appendTo.css("width");
    if(options.parentDiv != null && jQuery(options.parentDiv).length) {
        appendTo = jQuery(options.parentDiv);
        jQuery(options.parentDiv).css({
            position: "relative"
        });
        pageHeight = parseInt(jQuery(options.parentDiv).css("height").replace(/px/g, "")) + 50;
        pageWidth = appendTo.css("width");
    }
    var newDiv = jQuery('<div class="body-over" style="filter:alpha(opacity=0.3); -moz-opacity:0.3; opacity:0.3;">').appendTo(appendTo);
    newDiv.css({
        width: pageWidth,
        height: pageHeight + "px",
        position: "absolute",
        top: "0px",
        left: "0px",
        backgroundColor: "black",
        zIndex: 1000000000
    });

    var moreConfigLink = "";
    jQuery.each(options.configs, function(key, value) {
        if(moreConfigLink != "") {
            moreConfigLink += "&";
        }
        moreConfigLink += key + "=" + value;
    });

    var targetUrl = "";
    var _a = options.limit;
    var _b = (_a * options.currentPage) - _a;
    if(options.loadUrl.indexOf("?") >= 0) {
        targetUrl = options.loadUrl + "&offset="+_b+"&limit="+_a;
    } else {
        targetUrl = options.loadUrl + "?offset="+_b+"&limit="+_a;
    }
    if(targetUrl.indexOf("?") >= 0) {
        targetUrl += "&" + moreConfigLink;
    } else {
        targetUrl += "?" + moreConfigLink;
    }
    jQuery.ajax({
        type: "POST",
        dataType: "HTML",
        data: options.formParams,
        url: targetUrl,
        success: function(htmlData) {
            if(options.directHtml == true) {
                elm.html(htmlData);
            } else {
                var newElm = $("<div>"+htmlData+"</div>");
                if(newElm.find("#"+elm.attr("id")).length) {
                    elm.html(newElm.find("#"+elm.attr("id")).html());
                } else if(newElm.find("."+elm.attr("class")).length) {
                    elm.html(newElm.find("."+elm.attr("class")).html());
                }
            }
            var newElement = jQuery("<div>"+htmlData+"</div>");
            if(options.totalFinderId != null) {
                if(newElement.find(options.totalFinderId).length) {
                    var tempTotal = newElement.find(options.totalFinderId).attr("value");
                    if( tempTotal !== undefined ) {
                        tempTotal = parseInt(tempTotal);
                        if( !isNaN(tempTotal) ) {
                            options.total = tempTotal;
                        }
                    }
                }
            }
            var resultCount = null;
            if(options.resultCountElm != null) {
                if(newElement.find(options.resultCountElm).length) {
                    var tempTotal = newElement.find(options.resultCountElm).attr("value");
                    if( tempTotal !== undefined ) {
                        tempTotal = parseInt(tempTotal);
                        if( !isNaN(tempTotal) ) {
                            resultCount = tempTotal;
                        }
                    }
                }
            }
            if(options.limitFinderElm != null) {
                if(newElement.find(options.limitFinderElm).length) {
                    var tempTotal = newElement.find(options.limitFinderElm).attr("value");
                    if( tempTotal !== undefined ) {
                        tempTotal = parseInt(tempTotal);
                        if( !isNaN(tempTotal) ) {
                            options.limit = tempTotal;
                        }
                    }
                }
            }
            if(resultCount != null && resultCount == 0 && options.currentPage > 1) {
                options.currentPage--;
                while(true) {
                    var _a = options.limit;
                    var _b = (_a * options.currentPage) - _a;
                    if(_b > options.total && options.currentPage > 1) {
                        options.currentPage--;
                    } else {
                        break;
                    }
                }
                elm.refreshPagination(paginationCounterId,options,elm,afterCall);
                return false;
            }
            jQuery("."+paginationCounterId).remove();
            elm.startPagination(options, afterCall);

            if(afterCall) {
                afterCall(paginationCounterId,options,elm,afterCall);
            }
            jQuery(".body-over").remove();
        }
    });
};