This extension uses the infinite scroll jQuery plugin, from http://www.infinite-scroll.com/ to create an infinite scrolling pagination, like in twitter. This kind of pagination is also called Endless Scroll.
It uses javascript to load and parse the new pages, but gracefully degrade in cases where javascript is disabled and the users will still be able to access all the pages.
Requirements ¶
Yii 1.1.4
Usage ¶
The YiinfiniteScroller class extends the CBasePager class, so you will use it the same way as CLinkPager and CListPager.
On your controller you need to create the CPagination class which controls the pages handling:
class PostController extends Controller
{
public function actionIndex()
{
$criteria = new CDbCriteria;
$total = Post::model()->count();
$pages = new CPagination($total);
$pages->pageSize = 20;
$pages->applyLimit($criteria);
$posts = Post::model()->findAll($criteria);
$this->render('index', array(
'posts' => $posts,
'pages' => $pages,
));
}
}
Now on your view you will use it as a widget, like in the following sample:
$this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array(
'itemSelector' => 'div.post',
'pages' => $pages,
));
Note that this will only output the necessary code to the pager. It will not render the page items. Since YiinfiniteScroller extends CBasePager, everything works exactly the same way as if you were using the CListPager or CLinkPager. So, you're need to manually render the items.
In this example, the items are stored in the $posts variable. In our view, we can render the posts by using a simple foreach loop, like in the example bellow:
<?php foreach($posts as $post): ?>
<div class="post">
<p>Autor: <?php echo $post->author; ?></p>
<p><?php echo $post->text; ?></p>
</div>
<?php endforeach; ?>
This is how the complete view file will look like:
<div id="posts">
<?php foreach($posts as $post): ?>
<div class="post">
<p>Autor: <?php echo $post->author; ?></p>
<p><?php echo $post->text; ?></p>
</div>
<?php endforeach; ?>
</div>
<?php $this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array(
'contentSelector' => '#posts',
'itemSelector' => 'div.post',
'loadingText' => 'Loading...',
'donetext' => 'This is the end... my only friend, the end',
'pages' => $pages,
)); ?>
There are a few properties that can be set for YiinfiniteScroller:
- contentSelector: The jQuery selector of the container element where the loaded items (from itemSelector) will be appended
- loadingText: The text to be displayed while a new page is being loaded
- loadingImg: The URL of the image displayed while a new page is being loaded
- donetext: The text to be displayed when all the pages had been loaded
- pages: The CPagination object
- errorCallback: Javascript function that is called when there are ajax errors or 404s.
- contentLoadedCallback: A Javascript function that is called when new itens are loaded. In its scope, this will be the DOM Element just loaded.
- navigationLinkText: The text to be displayed in the navigation link (Usually visible only when javascript is disabled). The default value is "next".
Changelog ¶
Release 1.3 (09/02/2014)
- Added the contentLoadedCallback
- Added tests!
- Fixed bug that loaded the last page twice
- Removed the navigation link in the last page. That link was pointing to a non existent page.
Release 1.2 (11/11/2013)
- Added the navigationLinkText property
- Fixed problems when there were 0 or 1 pages to be paged
How do I set each of my elements?
I still dont get it...
How do I set how to render each item?
This widget doesn't handle the rendering.
You render the items on the page yourself, use a loop or a CListView for example. This will make a call back to the page with the next page in the query string. Take the contents of the items on that page and insert it into the current page.
I still don't get it...too.
How did I render the items in view with this widget?
Can anyone post a sample code?
Thanks!
More usage samples
Description updated with more detailed examples of how to render the items. :)
gonna try this for sure!
keep up the good work pal!
Excellent addition to Yii
Looks like a great addition, just what I'm needing right now. Cheers!
thx!!
that's exactly what i was looking for. works fine, thanks for the examples! i just had to change the "$(..." in your YiinfiniteScroller class to "jQuery(.." that's the more popular way.
thumbs up.
jule
is there any way I can use this with CListView
can someone please help me how can I use it with CListView widget
Using with CListView
$this->widget('zii.widgets.CListView', array( // Default CListView configuration 'dataProvider'=>$dataProvider, 'itemView'=>'infinitelist_item', // Custom Infinite Scroller pagination 'id'=>'list-identifier', 'pager'=>array( 'class'=>'ext.yiinfinite-scroll.YiinfiniteScroller', 'contentSelector' => '#list-identifier div.items', 'itemSelector' => 'div.view', ) ));
Nice one! Please add htmlOptions to hidden navigationlink
Hi,
very nice extension! Just a tipp: I needed html options for the infinite_navigation links to hide these links from Google.
Just add in the class header
public $linkHtmlOptions = array();
and in the function that creates the navigation
private function renderNavigation() { $next_link = CHtml::link('next',$this->createPageUrl($this->getCurrentPage(false)+1), $this->linkHtmlOptions); (..)
Thanks alot
Jule from Hamburg
@yokesh28
I didn't understand the problem you're facing. Can you give me more details and show me the code on how you're using the extension?
How do you extend it so it works with callback function?
Hi, I want to add function callback with jQuery masonry like the codes below:
}, function ( newElements ) { setTimeout(function() { $container.masonry({ appendedContent: $(newElements) }); }, 50); } );
How can you do that?
Thanks in advance.
Well done
Thanks, it works perfectly.
wonderfull.. and thank you....
Wow,
poor me... I already read this extension several times, but i really dont what the purpose of this extension, and finally when see the demo, i surprise, "this is the extension that I looking for month...."
Thank you davi_alexandre, thank you community.. I really need this extension to show the tree of all of Chart of Account (Accounting apps) in partial way to cut loading times...
great extension
hi,
thank you for this extension, it's works great.
I have a pro lem with integrating with http://masonry.desandro.com/demos/infinite-scroll.html
The Masonry has great way to arrange the boxes... do you have a solution?
thank you
resolved
it's very simple with mansory. i just tell use pagination and insert in view:
And he does the rest of the job.
thank you
Is there any way we can stop this after n number of pages
Thanks for this great plugin . Could you please let me know for example if we have 20 pages , display the scrolling up to 10 pages and then showing show more button. For example if you look at facebook wall or alubums , facebook only scrolls you for 10 times and then shows load more button .. I couldn't find that option or am I missing any option ..
Thanks for your help again
Regards
Yii Fan
:/
I have a CStarRating in each item, which breaks on the items who are loaded by scrolling,but not those loaded from the start.
Okejl
afterAjaxUpdate in a cListView doesnt work if you exchange the default pagination for infinitive scrolling. I need to run a js function after each time new content has been loaded, how can I do this with this extension?
Not able to use ajaxlink in your demo
Hi, i have used your extension and facing one issue. Here's my code
In protected/view folder, my index.php file
<div id="posts" class="span5"> <?php foreach($posts as $post): ?> <div class="post"> <div class="row "> <?php $this->beginWidget('CMarkdown', array('purifyOutput'=>true)); echo $post->content; $this->endWidget(); ?> </div> <div class="row"> <?php echo CHtml::link('<i class="icon-comment"></i> Comments ('.$post->commentCount.')',$post->url.'#comments'); ?> <?php echo "id".$post->id;?> <?php echo CHtml::htmlButton('<i class="icon-cog icon-white"></i> Subscribe', array('data-loading-text'=>'Subscribed', 'class'=>'btn btn-success', 'ajax' => array( 'type'=>'POST', 'url'=>CController::createUrl('headlines/Create/id/'.$post->id), 'update'=>'#userIdAvailability', 'beforeSend' => 'function(){ $("#userIdLoading").show();}', 'complete' => 'function(){ }' //$("#userIdLoading").hide(); ), 'type'=>'button')); ?> <div id="userIdAvailability"> <span style="" id="userIdLoading">Loading...</span></div> </div> </div> <?php endforeach; ?> </div> <?php $this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array( 'contentSelector' => '#posts', 'itemSelector' => 'div.post', 'loadingText' => 'Loading...', 'donetext' => 'This is the end... my only friend, the end', 'pages' => $pages, )); ?>
My controller file postcontroller.php
public function actionIndex() { $model=new Post; if(isset($_POST['Post'])) { $model->attributes=$_POST['Post']; if($model->save()) $this->redirect(array('view','id'=>$model->id)); } $criteria = new CDbCriteria; $total = Post::model()->count(); $pages = new CPagination($total); $pages->pageSize = 5; $pages->applyLimit($criteria); $posts = Post::model()->findAll($criteria); if(isset($_GET['tag'])) $criteria->addSearchCondition('tags',$_GET['tag']); $this->render('index', array( 'posts' => $posts, 'pages' => $pages, 'model' => $model )); }
Noticed Issue:
Note:
Please help me to resolve this issue
Load and replace by packets of rows
Hi all, is there a way with this extension to, instead of to add below X rows (which is making a huge page), to replace the precedent ones by the X next ?
Little improvement
Hey, thanks for this excellent extension!
I've made a simple improvement (i think), once I haven't found a way to manually trigger the loading of next page. So lets code:
Declare two new properties:
public $nextButtonId = 'scrollNext'; public $manualScroll = false;
Add the Id to the rendered "next button"
private function renderNavigation() { $next_link = CHtml::link(Yii::t('app','Next'),$this->createPageUrl($this->getCurrentPage(false)+1), array('id'=>$this->nextButtonId) ); echo '<div class="infinite_navigation">'.$next_link.'</div>'; }
Add the code to unbind the auto-scroll and bind the scroll-next to the button
private function createInfiniteScrollScript() { Yii::app()->clientScript->registerScript( uniqid(), "$('{$this->contentSelector}').infinitescroll(".$this->buildInifiniteScrollOptions().");" ); if($this->manualScroll): Yii::app()->clientScript->registerScript( uniqid().'_manual', " //kill scroll binding $(window).unbind('.infscr'); //hook up the manual click guy. $('a#{$this->nextButtonId}').click(function(){ $(document).trigger('retrieve.infscr'); return false; }); // remove the paginator when we're done. $(document).ajaxError(function(e,xhr,opt){ if(xhr.status == 404) $('a#{$this->nextButtonId}').remove(); }); ", CClientScript::POS_LOAD ); endif; }
In your view, just set the manuScroll property to true
<?php $this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array( 'manualScroll' => true, 'contentSelector' => '#publications', 'itemSelector' => 'div.publication', //another options... )); ?>
Hope this helps!
:)
Regards!
After Ajaxupdate scroll does`t work properly
Normally it work fine... after ajaxrender the infinite scroll not working properly....
can anyone solve this problem...
Manual Scroll
How to manual scroll? The Next button is unusable since next page is always automatically loaded...
I've tried the js given in the plugin's website, however, after the first manual loading, the Next button goes away.
Thanks
Manual scroll working
I've made two little changes to get manual scrolling:
First, in the function I had suggested, add the code to display the button after triggering the infscr:
private function createInfiniteScrollScript() { Yii::app()->clientScript->registerScript( uniqid(), "$('{$this->contentSelector}').infinitescroll(".$this->buildInifiniteScrollOptions().");" ); if($this->manualScroll): Yii::app()->clientScript->registerScript( uniqid().'_manuala', " //kill scroll binding $(window).unbind('.infscr'); //hook up the manual click guy. $('a#{$this->nextButtonId}').live('click', function(){ $(document).trigger('retrieve.infscr'); //============ NOTE I HAVE ADDED THIS LINE, ADJUST THE DISPLAY CSS PROPERTY OF YOUR NEXT BUTTON=================== $('a#{$this->nextButtonId}').css('display','inline-block' ); return false; }); // remove the paginator when we're done. $(document).ajaxError(function(e,xhr,opt){ if(xhr.status == 404) $('a#{$this->nextButtonId}').remove(); }); ", CClientScript::POS_LOAD ); endif; }
Also, change navSelector to be equals to nextSelector:
private $_default_options = array( 'navSelector' => 'div.infinite_navigation a:first', 'nextSelector' => 'div.infinite_navigation a:first', 'bufferPx' => '300', );
Working smoothly fine now!
Thanks and regards!
=))
Awesome work! One additional parameter
There is one more possible parameter loadingImg not mentioned in usage section:
<?php $this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array( 'itemSelector' => 'div.post', 'loadingImg' => 'http://www.infinite-scroll.com/loading.gif', 'pages' => $pages, )); ?>
multiple infinite scrolls in the same view
I have 2 infinite-scrolls in the same view (like facebook does on the wall and in the notifications) but it just doesnt work. They only work when they are separate, but if I put both in the same page they stop working.
By the way, im using different contentSelector and itemSelector for both infinite-scrolls.
Do you know any workaround to this?
Add callback functionality
I recognized that the current version of this great extension is missing a callback option which I needed to get masonry working correctly with infinite scroll.
I post it here, if somebody else is interested:
I just modified the YiinfiniteScroller Class from the Yiinfinite Scroll Yii Extension and added the callback part for Infinite Scroll which was missing:
private function createInfiniteScrollScript() { Yii::app()->clientScript->registerScript( uniqid(), "$('{$this->contentSelector}').infinitescroll(".$this->buildInifiniteScrollOptions().", ".$this->callback.");" ); }
At the beginning of the class I added the line
public $callback;
to use it later in the method.
Then you can call the Widget with an additional option callback, for example like this:
'callback' => 'function( newElements ) { // hide new items while they are loading var $newElems = $( newElements ).css({ opacity: 0 }); // ensure that images load before adding to masonry layout $newElems.imagesLoaded(function(){ // show elems now theyre ready $newElems.animate({ opacity: 1 }); $(".items").masonry( "appended", $newElems, true ); }); }',
Works like charm. Hope it may help somebody else.
Bootstrap Theme Conflict on ie8
Using Twitter Bootstrap Theme
public function actionIndex() { Yii::app()->setTheme('bootstrap'); //http://www.cniska.net/yii-bootstrap/ }
The script run correctly on Chrome.
But on ie8 tell this message:
"This is the end... my only friend, the end"
practically does not show the following pages
Can you help me?
this is not working.
i tried this with this same example but wht i found is just a an anchor tag named "next" at the end and when i click on it will do a non-ajax loading to next page and so on. nothing else. disappointed. :(
@sirin k it works
@sirin k
check js errors in console. if you see Next button, then something gone wrong in yii-infinitescroll js
im gettin a js error
Uncaught TypeError: Object [object Object] has no method 'infinitescroll'
@sirin k check assets registration
this probably means that jquery.infinitescroll.min.js is not registered (is there "jquery.infinitescroll.min.js" in generated html source code?) - check why it's not registered. maybe problem with your assets folder chmod, or bug in custom client script class, or or or
im gettin a js error
Uncaught TypeError: Object [object Object] has no method 'infinitescroll'
script is registered
<script type="text/javascript" src="/qponsr/frontend/www/assets/d6f41ffd/jquery.infinitescroll.min.js"></script> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($) { $('#posts').infinitescroll({'loadingText':'Loading...','donetext':'This is the end... my only friend, the end','itemSelector':'div.post','navSelector':'div.infinite_navigation','nextSelector':'div.infinite_navigation a:first','bufferPx':'300'}); }); /*]]>*/ </script>
@sirin k
I can take a look and help if you publish it somewhere online.
It started working..
It started working when i manually linked that js like below:
<script src="/qponsr/frontend/extensions/yiinfinite-scroll/assets/jquery.infinitescroll.min.js"></script>
@sirin k
so - problem in assets publishing ;)
check step-by-step how your client script publishes - that's where the shoe pinches
How to make The Next post triggerred by scroll bar in a div? not with browser scroll bar?
How to make The Next post triggerred by scroll bar in a div? not with browser scroll bar?
Thanks,
footer is no longer visible
How to make the footer visible
thanks
its nice extension its working fine for me.
LocalMode
If you want to work in localMode (just over a div) you need to add this to add a private option in YiinfiniteScroller.php:
private $_options = array( 'loadingImg' => null, 'loadingText' => null, 'donetext' => null, 'itemSelector' => null, 'errorCallback' => null, ** 'localMode' => null,** );
After that you can use
'localMode' => true,
in your widget options.
Thanks for this extension mates!
Plugin not working in AJAX
Hi, Thanks for this amazing plugin. Plugin works fine in normal scenario but in ajax it is not working properly. I am scrolling the content manually. The problem is of URL.
After ajax update , the "More" button has a url for another ajax call to load more content. When i click on the "More" button, this request is sent to the URL which is in the address bar not the URL which is for ajax request.
Can some body solve this issue.?
Use with data provider
Hi guys,
How can i use this with a data provider?
Thank you,
jim
Re: Use with data provider
How can i use this with a data provider?
Did you intend to use it with CListView? If yes, please see here:
http://www.yiiframework.com/forum/index.php/topic/33029-yiinfinite-scroll-and-afterajaxupdate/
Although there is problem with that, it could display data properly as far as I could see.
The autoload is not working in after Category sort using ajax
Hi All,
I have implemented the infinite scroller on my products page and is working fine. But after I sort my products by category which loads the results in AJAX. The infinite scroller is not working. Can any one help me on this. I have spent hours to sort out this problem. Is this a script conflict or the script is not loading. Im using renderPartial to load the sorted products and I have also set third and fourth parameter of the renderPartial as false,true.
Logic error in currentPageDoesntExists()
I use this script very close to the actual example and it works pretty well, however I had the issue that the last page was repeated once. So if there should've been only 3 pages, I would get content of: 1, 2, 3, 3 (end). Checking the code, there seems to be a problem here:
private function currentPageDoesntExists() { if($this->pageCount > 1) { return $this->currentPage > $this->pageCount; } else { return $this->currentPage > 0; } }
If pageCount is 3 and we are on page 3 already, this will return 3 > 3, which is false. However the code for sending a 404 which means there is no next page, checks the end like this:
if($this->currentPageDoesntExists()) { throw new CHttpException(404); }
So we will have to return true in this function, to have it correctly throw the 404. So the corrected code should look like this:
private function currentPageDoesntExists() { if($this->pageCount > 1) { return $this->currentPage >= $this->pageCount; } else { return $this->currentPage > 0; } }
Regards,
Sebastian
Javascript not loading
I am really thankful for the plugin. It works great. But I got a problem,
The Javascript is loading is first page. but not loading on the rest.
Here is the code i am working with.
<?php $this->widget('ext.yiinfinite-scroll.YiinfiniteScroller', array( 'contentSelector' => '#infinityScroller', 'itemSelector' => 'div.itemDiv', 'loadingText' => 'Loading...', 'donetext' => 'This is the end... ', 'pages' => $pages, )); ?>
I had tried using renderPartial. but still the problem remains the same.
if(Yii::app()->request->isAjaxRequest): $this->renderPartial('object_list', $content, false, true); else: $this->render('object_list',$content); endif;
Everything else works fine.
Script is not working properly
Its repeating my last page twice. Rest its working good. Also can anyone tell how do i replace loading gif with mine?
Multiple Pagination on a single page, causing error
Hi I am working on a profile page, where I need to show the list of comments and list of posts. I am showing them in different tabs on a single page. Now when I call pagination, both the paginations are working at once, is there a method where i can tell the process the difference between these tabs.
Or anything else to run both the paginations simultaneously without interrupting each other.
@ihemant
I think I experienced your latest issue ...I solved by changing the content selector & item selector div id to something different on the second tab.
Re: Script is not working properly
Hi @ihemant. The new release fixes the problem where the last page is loaded twice. Also, the README was updated with information about the loadingImg property that can be used to change the loading gif
Resolved
Thanks for resolve,that is exactly looking for this
Regards,
Ankit Modi
Not working with filters with ajax call on product listing page
Hi,
I am using yii infinite scroll extension in a product list page for infinite pagination. Here, there are several filters to filter the products. I am using ajax call to filter out products based on certain filters. My problem is infinite scroll is not working fine with filter data.
Like, there are 135 total products and i am showing 30 products on a page.
First case -
If i apply Filter like price is less than 500 then the result is 23 products. So it shows 23 products but when i scroll down the page, it will shows the page 2 product of the default listing and continues. The ideal result is it will show only 23 products.
Second case -
Like if i apply filter price is greater than 500 then the result is 45 products. So on first page it shows 30 products of the filtered result but when i scroll down the page then it will show the next 30 page of default listing and again n again.
So my question is how i can use this extension with filters on a product listing page???
Success callback function
Hi, is there any solution to callback any function when next page is loaded successful?
Thanks
Need more examples
I can't figure out how to make this work with CListView. It does nothing when I add it as a pager. No javascript errors, literally nothing happens when I scroll.
Any examples?
my code:
Controller:
public function actionIndex() { $dataProvider=new CActiveDataProvider('Student'); $dataProvider->pagination->pageSize = 20; $this->render('index',array( 'dataProvider'=>$dataProvider, )); }
View:
$this->widget('zii.widgets.CListView', array( 'id'=>'studentlist', 'dataProvider'=>$dataProvider, 'itemView'=>'_view', 'pager'=> array( 'class'=>'ext.yiinfinite-scroll.YiinfiniteScroller', ), ));
Smart Anchor Support
Would you consider adding some type of intelligent anchor support for elements that have not yet been loaded? (because the user has not scrolled down)
It would be nice to call xyz.com/somepage#autoscrollhere and have the extension scroll to the appropriate anchor. In this case, #autoscrollhere
Just curious,
Thanks for a great ext.
Uncaught TypeError: Cannot read property 'msie' of undefined
Hi, I try to use this component for pagination, on local and dev server it works fine, but on live I get the following error:
Uncaught TypeError: Cannot read property 'msie' of undefined
Can anyone help me with solving it?
Thank you!
RE: Uncaught TypeError: Cannot read property 'msie' of undefined
@kasinau having a quick look on the net it may be related to the jQuery version you're using, otherwise I recommend posting your issue with more details on StackOverflow or some other q/a site, as commenting on the extension here is not the right place to try and solve issues you may have, especially if not directly related to the extension (otherwise everybody would report it)...
Uncaught TypeError: Cannot read property 'msie' of undefined
@benomatis, yes, you are right, it is related to the jQuery version I use(1.10.*), but in this extension's documentation it isn't specified the compatible jQuery version, so I find this related to this extension too, please update the doc an specify that it's compatible with jQuery < 1.9.
I fixed the problem by upgrading the jquery.infinitescrool.min.js from assets.
Best.
RE: Uncaught TypeError: Cannot read property 'msie' of undefined
@kasinau Fair point, though it's possible that the extension has been developed before the newer releases of jQuery have become available, and hasn't been updated since. Either way, I'm not the doc owner and have no permission to edit it.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.