Browse Source

Add jquery plugin jscroll for scroll ajax pagination - refs BT#5637

Daniel Barreto 10 years ago
parent
commit
54aa741e8c

+ 32 - 0
main/inc/ajax/social.ajax.php

@@ -185,6 +185,38 @@ switch ($action) {
                 break;
         }
         break;
+    case 'listWallMessage':
+        $start = isset($_REQUEST['start']) ? intval($_REQUEST['start']) - 1 : 0;
+        $length = isset($_REQUEST['length']) ? intval($_REQUEST['length']) : 10;
+        $userId = api_get_user_id();
+        $array = SocialManager::getWallMessagesPostHTML($userId, $friendId, null, $length, $start);
+        if (!empty($array)) {
+            ksort($array);
+            $html = '';
+
+            for($i = 0; $i < count($array); $i++) {
+                $post = $array[$i]['html'];
+                $comment = SocialManager::getWallMessagesHTML($userId, $friendId, $array[$i]['id'], null, $length, $start);
+
+                $html .= SocialManager::social_wrapper_div($post . $comment, 5);
+            }
+            $html .= Display::div(
+                Display::url(
+                    get_lang('Next'),
+                    api_get_self() . '?a=listWallMessage&start=' .
+                    ($start + $length + 1) . '&length=' . $length,
+                    array(
+                        'class' => 'nextPage',
+                        'style' => 'display: none;',
+                    )
+                ),
+                array(
+                    'class' => 'next'
+                )
+            );
+            echo $html;
+        }
+        break;
     default:
         echo '';
 }

+ 3 - 0
main/inc/lib/javascript/jscroll/.gitignore

@@ -0,0 +1,3 @@
+
+.settings/
+.project

+ 54 - 0
main/inc/lib/javascript/jscroll/README.md

@@ -0,0 +1,54 @@
+# jScroll jQuery Plugin for Infinite Scrolling / Auto-Paging
+
+Official site at [jscroll.com](http://jscroll.com/).
+
+* Copyright (C) 2011-2013, [Philip Klauzinski](http://klauzinski.com/)
+* Current Version: 2.2.4
+* Dual licensed under the MIT and GPL Version 2 licenses.
+* http://jscroll.com/#license
+* http://www.opensource.org/licenses/mit-license.php
+* http://www.gnu.org/licenses/gpl-2.0.html
+
+Requires jQuery v1.4.3+
+
+## Facebook Page
+
+Follow us on Facebook for commit updates: http://www.facebook.com/jScroll.Infinite.Scrolling
+
+## Usage
+
+The `jscroll` method is called on the selector for which you want your scrollable content contained within. For example:
+
+```javascript
+$('.jscroll').jscroll();
+```
+
+The `jscroll` method takes an optional object literal as a parameter for overriding the default options. An example of how this can be done is shown below.
+
+```javascript
+$('.jscroll').jscroll({
+    loadingHtml: '<img src="loading.gif" alt="Loading" /> Loading...',
+    padding: 20,
+    nextSelector: 'a.jscroll-next:last',
+    contentSelector: 'li'
+});
+```
+
+## Options
+
+* debug            (false)  When set to true, outputs useful information to the console display if the `console` object exists.
+* autoTrigger      (true)  When set to true, triggers the loading of the next set of content automatically when the user scrolls to the bottom of the containing element. When set to false, the required next link will trigger the loading of the next set of content when clicked.
+* autoTriggerUntil (false)  Set to an integer great than 0 to turn off `autoTrigger` of paging after the specified number of pages. Requires `autoTrigger` to be `true`.
+* loadingHtml      (`'<small>Loading...</small>'`)  The HTML to show at the bottom of the content while loading the next set.
+* padding          (0)  The distance from the bottom of the scrollable content at which to trigger the loading of the next set of content. This only applies when autoTrigger is set to true.
+* nextSelector     ('a:last')  The selector to use for finding the link which contains the href pointing to the next set of content. If this selector is not found, or if it does not contain a href attribute, jScroll will self-destroy and unbind from the element upon which it was called.
+* contentSelector  ('')  A convenience selector for loading only part of the content in the response for the next set of content. This selector will be ignored if left blank and will apply the entire response to the DOM.
+* pagingSelector   ('')  Optionally define a selector for your paging controls so that they will be hidden, instead of just hiding the next page link.
+* callback         ()  Optionally define a callback function to be called after a set of content has been loaded.
+
+For more information on the *contentSelector* option and how it loads a response fragment, see the [jQuery documentation for the .load() method](http://api.jquery.com/load/).
+
+## LICENSES:
+
+* MIT: http://www.opensource.org/licenses/mit-license.php
+* GPL-2.0: http://www.gnu.org/licenses/gpl-2.0.html

+ 209 - 0
main/inc/lib/javascript/jscroll/jquery.jscroll.js

@@ -0,0 +1,209 @@
+/*!
+ * jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging - v2.2.4
+ * http://jscroll.com/
+ *
+ * Copyright 2011-2013, Philip Klauzinski
+ * http://klauzinski.com/
+ * Dual licensed under the MIT and GPL Version 2 licenses.
+ * http://jscroll.com/#license
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * @author Philip Klauzinski
+ * @requires jQuery v1.4.3+
+ */
+(function($) {
+
+    // Define the jscroll namespace and default settings
+    $.jscroll = {
+        defaults: {
+            debug: false,
+            autoTrigger: true,
+            autoTriggerUntil: false,
+            loadingHtml: '<small>Loading...</small>',
+            padding: 0,
+            nextSelector: 'a:last',
+            contentSelector: '',
+            pagingSelector: '',
+            callback: false
+        }
+    };
+
+    // Constructor
+    var jScroll = function($e, options) {
+
+        // Private vars
+        var _data = $e.data('jscroll'),
+            _userOptions = (typeof options === 'function') ? { callback: options } : options,
+            _options = $.extend({}, $.jscroll.defaults, _userOptions, _data || {}),
+            _isWindow = ($e.css('overflow-y') === 'visible'),
+            _$next = $e.find(_options.nextSelector).first(),
+            _$window = $(window),
+            _$body = $('body'),
+            _$scroll = _isWindow ? _$window : $e,
+            _nextHref = $.trim(_$next.attr('href') + ' ' + _options.contentSelector);
+
+        // Initialization
+        $e.data('jscroll', $.extend({}, _data, {initialized: true, waiting: false, nextHref: _nextHref}));
+        _wrapInnerContent();
+        _preloadImage();
+        _setBindings();
+
+        // Private methods
+
+        // Check if a loading image is defined and preload
+        function _preloadImage() {
+            var src = $(_options.loadingHtml).filter('img').attr('src');
+            if (src) {
+                var image = new Image();
+                image.src = src;
+            }
+        }
+
+        // Wrapper inner content, if it isn't already
+        function _wrapInnerContent() {
+            if (!$e.find('.jscroll-inner').length) {
+                $e.contents().wrapAll('<div class="jscroll-inner" />');
+            }
+        }
+
+        // Find the next link's parent, or add one, and hide it
+        function _nextWrap($next) {
+            if (_options.pagingSelector) {
+                var $parent = $next.closest(_options.pagingSelector).hide();
+            } else {
+                var $parent = $next.parent().not('.jscroll-inner,.jscroll-added').addClass('jscroll-next-parent').hide();
+                if (!$parent.length) {
+                    $next.wrap('<div class="jscroll-next-parent" />').parent().hide();
+                }
+            }
+        }
+
+        // Remove the jscroll behavior and data from an element
+        function _destroy() {
+            return _$scroll.unbind('.jscroll')
+                .removeData('jscroll')
+                .find('.jscroll-inner').children().unwrap()
+                .filter('.jscroll-added').children().unwrap();
+        }
+
+        // Observe the scroll event for when to trigger the next load
+        function _observe() {
+            _wrapInnerContent();
+            var $inner = $e.find('div.jscroll-inner').first(),
+                data = $e.data('jscroll'),
+                borderTopWidth = parseInt($e.css('borderTopWidth')),
+                borderTopWidthInt = isNaN(borderTopWidth) ? 0 : borderTopWidth,
+                iContainerTop = parseInt($e.css('paddingTop')) + borderTopWidthInt,
+                iTopHeight = _isWindow ? _$scroll.scrollTop() : $e.offset().top,
+                innerTop = $inner.length ? $inner.offset().top : 0,
+                iTotalHeight = Math.ceil(iTopHeight - innerTop + _$scroll.height() + iContainerTop);
+
+            if (!data.waiting && iTotalHeight + _options.padding >= $inner.outerHeight()) {
+                //data.nextHref = $.trim(data.nextHref + ' ' + _options.contentSelector);
+                _debug('info', 'jScroll:', $inner.outerHeight() - iTotalHeight, 'from bottom. Loading next request...');
+                return _load();
+            }
+        }
+
+        // Check if the href for the next set of content has been set
+        function _checkNextHref(data) {
+            data = data || $e.data('jscroll');
+            if (!data || !data.nextHref) {
+                _debug('warn', 'jScroll: nextSelector not found - destroying');
+                _destroy();
+                return false;
+            } else {
+                _setBindings();
+                return true;
+            }
+        }
+
+        function _setBindings() {
+            var $next = $e.find(_options.nextSelector).first();
+            if (_options.autoTrigger && (_options.autoTriggerUntil === false || _options.autoTriggerUntil > 0)) {
+                _nextWrap($next);
+                if (_$body.height() <= _$window.height()) {
+                    _observe();
+                }
+                _$scroll.unbind('.jscroll').bind('scroll.jscroll', function() {
+                    return _observe();
+                });
+                if (_options.autoTriggerUntil > 0) {
+                    _options.autoTriggerUntil--;
+                }
+            } else {
+                _$scroll.unbind('.jscroll');
+                $next.bind('click.jscroll', function() {
+                    _nextWrap($next);
+                    _load();
+                    return false;
+                });
+            }
+        }
+
+        // Load the next set of content, if available
+        function _load() {
+            var $inner = $e.find('div.jscroll-inner').first(),
+                data = $e.data('jscroll');
+
+            data.waiting = true;
+            $inner.append('<div class="jscroll-added" />')
+                .children('.jscroll-added').last()
+                .html('<div class="jscroll-loading">' + _options.loadingHtml + '</div>');
+
+            return $e.animate({scrollTop: $inner.outerHeight()}, 0, function() {
+                $inner.find('div.jscroll-added').last().load(data.nextHref, function(r, status, xhr) {
+                    if (status === 'error') {
+                        return _destroy();
+                    }
+                    var $next = $(this).find(_options.nextSelector).first();
+                    data.waiting = false;
+                    data.nextHref = $next.attr('href') ? $.trim($next.attr('href') + ' ' + _options.contentSelector) : false;
+                    $('.jscroll-next-parent', $e).remove(); // Remove the previous next link now that we have a new one
+                    _checkNextHref();
+                    if (_options.callback) {
+                        _options.callback.call(this);
+                    }
+                    _debug('dir', data);
+                });
+            });
+        }
+
+        // Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript
+        function _debug(m) {
+            if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) {
+                if (typeof m === 'object') {
+                    var args = [];
+                    for (var sMethod in m) {
+                        if (typeof console[sMethod] === 'function') {
+                            args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]];
+                            console[sMethod].apply(console, args);
+                        } else {
+                            console.log.apply(console, args);
+                        }
+                    }
+                } else {
+                    console[m].apply(console, Array.prototype.slice.call(arguments, 1));
+                }
+            }
+        }
+
+        // Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method()
+        $.extend($e.jscroll, {
+            destroy: _destroy
+        });
+        return $e;
+    };
+
+    // Define the jscroll plugin method and loop
+    $.fn.jscroll = function(m) {
+        return this.each(function() {
+            var $this = $(this),
+                data = $this.data('jscroll');
+            // Instantiate jScroll on this element if it hasn't been already
+            if (data && data.initialized) return;
+            var jscroll = new jScroll($this, m);
+        });
+    };
+})(jQuery);

File diff suppressed because it is too large
+ 14 - 0
main/inc/lib/javascript/jscroll/jquery.jscroll.min.js


+ 41 - 0
main/inc/lib/javascript/jscroll/jscroll.jquery.json

@@ -0,0 +1,41 @@
+{
+    "name": "jscroll",
+    "version": "2.2.4",
+    "title": "jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging",
+    "author": {
+        "name": "Philip KLauzinski",
+        "url": "http://klauzinski.com"
+    },
+    "licenses": [
+        {
+            "type": "MIT",
+            "url": "http://opensource.org/licenses/MIT"
+        },
+        {
+            "type": "GPL-2.0",
+            "url": "http://opensource.org/licenses/GPL-2.0"
+        }
+    ],
+    "dependencies": {
+        "jquery": ">=1.4.3"
+    },
+    "description": "jScroll is a jQuery plugin allowing you to effortlessly implement infinite scrolling, lazy loading, or whatever catchy phrase you may know it as, within a web page or web/HTML5 application. jScroll allows you to initiate an auto-paged AJAX fetch triggered by scrolling within a fixed-height div, or from scrolling the window object. A real-world example of this behavior is your Facebook News Feed, which automatically loads content as you scroll down and reach the end of the page.",
+    "keywords": [
+        "infinite-scrolling",
+        "lazy-loading",
+        "auto-paging",
+        "infinite",
+        "scroll",
+        "scrolling",
+        "lazy",
+        "auto",
+        "loading",
+        "paging",
+        "ajax",
+        "html5"
+    ],
+    "homepage": "http://jscroll.com",
+    "demo": "http://jscroll.com/#examples",
+    "docs": "http://jscroll.com",
+    "bugs": "https://github.com/pklauzinski/jscroll/issues"
+}

+ 14 - 12
main/inc/lib/social.lib.php

@@ -1239,13 +1239,14 @@ class SocialManager extends UserManager
      * Gets all messages from someone's wall (within specific limits)
      * @param int $userId id of wall shown
      * @param string $messageStatus status wall message
-     * @param int $parentId id message (Post main)
-     * @param string Date from which we want to show the messages, in UTC time
-     * @param int   Limit for the number of parent messages we want to show
+     * @param int|string $parentId id message (Post main)
+     * @param date $start Date from which we want to show the messages, in UTC time
+     * @param int $limit Limit for the number of parent messages we want to show
+     * @param int $offset Wall message query offset
      * @return boolean
      * @author Yannick Warnier
      */
-    public static function getWallMessages($userId, $messageStatus, $parentId = '', $start = null, $limit = 10)
+    public static function getWallMessages($userId, $messageStatus, $parentId = '', $start = null, $limit = 10, $offset = 0)
     {
         if (empty($start)) {
             $start = '0000-00-00';
@@ -1267,8 +1268,7 @@ class SocialManager extends UserManager
                 AND send_date > '$start' ";
         $sql .= (empty($messageStatus) || is_null($messageStatus)) ? '' : " AND msg_status = '$messageStatus' ";
         $sql .= (empty($parentId) || is_null($parentId)) ? '' : " AND parent_id = '$parentId' ";
-        $sql .= " ORDER BY send_date DESC
-                LIMIT $limit ";
+        $sql .= " ORDER BY send_date DESC LIMIT $offset, $limit ";
         $res = Database::query($sql);
         if (Database::num_rows($res) > 0) {
             while ($row = Database::fetch_array($res)) {
@@ -1285,17 +1285,18 @@ class SocialManager extends UserManager
      * @param int $friendId id person
      * @param int $idMessage id message
      * @param string  Start date (from when we want the messages until today)
-     * @param int Limit to the number of messages we want
+     * @param int $limit Limit to the number of messages we want
+     * @param int $offset
      * @return string  HTML formatted string to show messages
      */
-    public static function getWallMessagesHTML($userId, $friendId, $idMessage, $start = null, $limit = 10)
+    public static function getWallMessagesHTML($userId, $friendId, $idMessage, $start = null, $limit = 10, $offset = 0)
     {
         if (empty($start)) {
             $start = '0000-00-00';
         }
 
         $visibility = (api_get_user_id() == $userId  && $userId == $friendId);
-        $messages = self::getWallMessages($userId, MESSAGE_STATUS_WALL, $idMessage, $start, $limit);
+        $messages = self::getWallMessages($userId, MESSAGE_STATUS_WALL, $idMessage, $start, $limit, $offset);
         $formattedList = '<div class="mediaPost" style="width:calc(100%-14px);
         display:block;padding-left:14px">';
         $users = array();
@@ -1364,17 +1365,18 @@ class SocialManager extends UserManager
     /**
      * @param int $userId id
      * @param int $friendId id
-     * @param null $start
+     * @param date $start
      * @param int $limit
+     * @param int $offset
      * @return array $data return array associative
      */
-    public static function getWallMessagesPostHTML($userId, $friendId = 0, $start = null, $limit = 10)
+    public static function getWallMessagesPostHTML($userId, $friendId = 0, $start = null, $limit = 10, $offset= 0)
     {
         if (empty($start)) {
             $start = '0000-00-00';
         }
         $visibility = (api_get_user_id() == $userId  && $userId == $friendId);
-        $messages = self::getWallMessages($userId, MESSAGE_STATUS_WALL_POST , null, $start, $limit);
+        $messages = self::getWallMessages($userId, MESSAGE_STATUS_WALL_POST , null, $start, $limit, $offset);
         $users = array();
         $data = array();
         foreach ($messages as $key => $message) {

+ 25 - 1
main/social/profile.php

@@ -112,8 +112,11 @@ require_once api_get_path(SYS_CODE_PATH).'announcements/announcements.inc.php';
 
 require_once $libpath.'magpierss/rss_fetch.inc';
 $ajax_url = api_get_path(WEB_AJAX_PATH).'message.ajax.php';
+$socialAjaxUrl = api_get_path(WEB_AJAX_PATH).'social.ajax.php';
 api_block_anonymous_users();
 
+$htmlHeadXtra[] = api_get_js('jscroll/jquery.jscroll.js');
+
 $htmlHeadXtra[] = '<script>
 
 function checkLength( o, n, min, max ) {
@@ -256,6 +259,15 @@ $(document).ready(function (){
         height    : 300
        });
 
+    var container = $("#wallMessages");
+    container.jscroll({
+        loadingHtml: "<div class=\"span5\"> <div class=\"well_border\">' . get_lang('Loading') . ' </div></div>",
+        padding: -880,
+        nextSelector: "a.nextPage:last",
+        contentSelector: "",
+        debug: true
+    });
+
 });
 
 function display_hide () {
@@ -402,11 +414,23 @@ if ($show_full_profile) {
 }
 
 $wallSocialAddPost .= wallSocialAddPost();
+$social_right_content .= Display::div(
+    wallSocialPost($my_user_id, $friendId) . Display::url(
+        get_lang('Next'),
+        $socialAjaxUrl . '?a=listWallMessage&start=10&length=5',
+        array(
+            'class' => 'nextPage next',
+            'style' => 'display: none;'
+        )
+    ),
+    array(
+        'id' => 'wallMessages'
+    )
+);
 $social_right_content .= SocialManager::social_wrapper_div($wallSocialAddPost, 5);
 
 $social_right_content .=  SocialManager::social_wrapper_div($personal_info, 4);
 
-$social_right_content .= wallSocialPost($my_user_id, $friendId);
 //$social_right_content .= SocialManager::social_wrapper_div($wallSocial, 5);
 
 

Some files were not shown because too many files changed in this diff