5
\$\begingroup\$

This is a simple load more plugin, built for teaching purposes. For this reason, it's not pretty in terms of output.

I'd like to know if this can be improved, or if anyone can spot any major problems with this. The one thing I'm concerned about is the 'templating', whereby it gets the template from the initial markup and duplicates it.

loadmore.js

/*jslint unparam: true, white: true */

(function($) {
    "use strict";

    $.fn.loadmore = function(options) {

        var self = this,

        settings = $.extend({
            source: '',
            step: 2
        }, options),

        stepped = 1,
        item = self.find('.item'),

        finished = function() {
            self.find('.items-load').remove();
        },

        append = function(value) {
            var name,
                part;

            item.remove();

            for(name in value) {
                if(value.hasOwnProperty(name)) {
                    part = item.find('*[data-field="' + name + '"]');

                    if(part.length) {
                        part.text(value[name]);
                    }
                }
            }

            item.clone().appendTo(self.find('.items'));
        },

        load = function(start, count) {
            $.ajax({
                url: settings.source,
                type: 'get',
                dataType: 'json',
                data: {start: start, count: count},
                success: function(data) {

                    var items = data.items;

                    if(items.length) {
                        $(items).each(function(index, value) {
                            append(value);
                        });

                        stepped = stepped + count;
                    }

                    if(data.last === true) {
                        finished();
                    }
                }
            });
        };

        if(settings.source.length) {

            // Event handler for load more button
            self.find('.items-load').on('click', function() {
                load(stepped, settings.step);

                return false;
            });


            load(1, settings.step);
        } else {
            console.log('Source required for loadmore.');
        }

    };
}(jQuery));

Example usage

<!DOCTYPE html>
<html>
    <head>
        <title>Load more</title>
        <meta charset="UTF-8">
    </head>
    <body>

        <h4>Articles</h4>
        <div class="articles">
            <div class="items">
                <div class="item">
                    <h3><span data-field="title"></span> (<span data-field="id"></span>)</h3>
                    <p data-field="description"></p>
                </div>
            </div>
            <a href="#" class="items-load">Load more</a>
        </div>

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <script src="js/loadmore.js"></script>

        <script>
            $('.articles').loadmore({
                source: 'articles.php',
                step: 2
            });
        </script>
    </body>
</html>

Example JSON generated with PHP

<?php
header('Content-Type: application/json');

$pdo = new PDO("mysql:host=127.0.0.1;dbname=loadmore", "root", "");

$articles = [];

$start = isset($_GET['start']) ? (int)$_GET['start'] - 1 : 0;
$count = isset($_GET['count']) ? (int)$_GET['count'] : 1;

$article = $pdo->query("SELECT SQL_CALC_FOUND_ROWS * FROM articles LIMIT {$start}, {$count}");
$articlesTotal = $pdo->query("SELECT FOUND_ROWS() as count")->fetch(PDO::FETCH_ASSOC)['count'];

if($articlesCount = $article->rowCount()) {
    $articles = $article->fetchAll(PDO::FETCH_OBJ);
}

echo json_encode(array(
    'items' => $articles,
    'last' => ($start + $count) >= $articlesTotal ? true : false,
    'start' => $start,
    'count' => $count
));
\$\endgroup\$
3
\$\begingroup\$

From some staring at your code

  • There are no comments, at all
  • You $.ajax({ call should handle failure by implementing error
  • The items treatment in success seems little clumsy, first I would not put the function inside the ajax call, secondly I would probably go with something like this:

    success: function(data) {
    
        $(data.items).each(function(index, value) {
            append(value);
        });
        if(data.last === true) {
            finished();
        }
    }
    
  • I do not understand the value of stepped, what does it bring to your plugin ? It would have been far better to keep the stepping logic out of the plugin, and let the caller pass a data object that will be passed to the ajax call.
  • '.items-load' is a magic, repeated constant, you should use a properly named variable
  • item.find('*[data-field="' + name + '"]'); <- I don't like this, why would you not simply search by id, it performs better, and it is more standard.
  • "use strict"; on the top level, good stuff
  • Passes perfectly on JsHint.com
  • if(value.hasOwnProperty(name)) { <- good defensive coding
  • jQuery handles empty/undefined gracefully, so that you can write nicer code, this:

    part = item.find('*[data-field="' + name + '"]');
    
    if(part.length) {
        part.text(value[name]);
    }
    

    could be this:

    item.find('#'+name).text(value[name]);
    
  • The CSS names you use are very generic, you might want to consider adding a small prefix to avoid name clashes

  • loadmore -> loadMore because lowerCamelCase
  • console.log in production is a no-no
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.