How to handle hundreds of pagination in AngularJS + Laravel4? - php

I have a case where I have to pull data from the server and make pagination in the results. There are thousands of the data, and I'm planning to show 20 items per page.
My plan is to call this Laravel function each time new page is clicked:
public static function GetPagingListing($limLow=null, $limTop=null) {
$data = array();
$results = DB::table('news')->orderBy('date','desc')->limit($limLow, $limTop)->get(array('id','title','category','edituser','date'));
if($results != null) {
$i = 0;
foreach($results as $k=>$v) {
$data[$i][] = $v;
$i++;
}
}
$count = DB::table('news')->count(); //this gives total count of the data, for pagination later
return Response::json(['data'=>$data, 'count'=> ($count/20)]);
}
Then my current way of displaying the pagination is this (.html in Angular):
<ul>
<li ng-class="{disabled: currentPage == 0}">
<a href ng-click="prevPage()"><i class="fa fa-angle-double-left"></i> Before</a>
</li>
<li ng-repeat="n in range(itemCount)" ng-class="{active: n == currentPage}" ng-click="setPage()">
<a href ng-bind="n + 1">1</a>
</li>
<li ng-class="{disabled: currentPage == newsList.length - 1}">
<a href ng-click="nextPage()">After <i class="fa fa-angle-double-right"></i></a>
</li>
</ul>
This all works fine, but the total of my data count is 1000+, that's like 50+ pagination that user can click. How to make the pagination like [<prev][1][2][3][...][21][22][23][...][50][51][52][next>] (or at least a logic)?
EDIT
Solved my problem using Angular UI Bootstrap:
<pagination total-items="itemCount" page="currentPage" on-select-page="setPage(page)" boundary-links="true" rotate="false" max-size="5"></pagination>
with its cdn:
<script src="//cdn.jsdelivr.net/angular.bootstrap/0.7.0/ui-bootstrap-tpls.min.js"></script>

I've just think about this recently, and my conclusion is that the logic of the pagination is surprisingly involved. One place you can look for inspiration is Wordpress's paginate_links function http://core.trac.wordpress.org/browser/tags/3.7.1/src/wp-includes/general-template.php#L1988.
You need to know the total number of pages total, the current page current, number of first/last pages to be displayed end_size (3 in your example) and the number of pages around the current page mid_size (1 in your example); then:
if total < 2, no pagination needed
if current > 1, shows prev
for n from 1 to total:
if n <= end_size (the first part) or n > total - end_size (the last part) or (n >= current - mid_size and n <= current + mid_size) (the middle part), display link to page n
else display dots if not displayed
if current < total, shows next

Related

Using PHP to check if a CSS stylesheet is active for if/else statement

This is a strange one and it might not even be possible, but what I'm trying to do is check whether a particular stylesheet is loaded, if it is run one code, else run another. For example:
// Create loop counter
$counter = 0;
while ( have_posts() ) {
// MaxIT - Shows 2 listings per loop instead of 2
for ($x = 0; $x < 2; $x++) {
// Increase loop counter
$counter++;
the_post();
// Include listing loop template
get_template_part( 'loop', 'listing' );
} // endwhile have_posts()
echo '<hr style="width:100%; padding-left: 40px; margin: 60px 0px;" />';
}
The point of this code is to display properties on a real estate website. The original code did not have the FOR loop, I added that in so it would display 2 properties at a time before displaying in a horizontal rule. This was purely for aesthetics and looks great when viewing the properties in "grid" view, which shows two properties per row, like:
PROPERTY | PROPERTY
HORIZONTAL RULE
However, the client requested having a list view also, which shows 1 property per row, with image on the left and details on the right. I accomplished this with a second stylesheet which is loaded on click of a drop-down selector. However, because the above PHP loads 2 properties before the HR, it shows like:
PROPERTY
PROPERTY
HORIZONTAL RULE
So what I want to accomplish is having the PHP say "if the grid_view.css is loaded, show 2 properties before the HR, else if the list_view.css is loaded, show 1 property before the HR".
Is this possible with PHP? I'm not familiar with any other programming languages, so if it can be done in Javascript / JQuery that would be fine but I might need the "dummy" explanation if possible.
Thanks heaps in advance!
---- UPDATE / EDIT
Ok, I'm having trouble working out how to do what Justin suggested with "setting a flag" (don't quite understand that terminology tbh) in the PHP, so here's more insight on my current code (and yes it's built on Wordpress, sorry I should have said so earlier).
In my header.php I have...
Argh, having trouble..
So in my header.php I have this...
<link rel="stylesheet" type="text/css" href="/wp-content/themes/wpcasa/slick/slick.css"/>
<link href="/wp-content/themes/wpcasa/lib/assets/css/layout.min.css" rel="stylesheet" type="text/css" title="layoutgrid">
<link href="/wp-content/themes/wpcasa/lib/assets/css/layout_list.css" rel="stylesheet" type="text/css" title="layoutlist">
<script type="text/javascript" src="/wp-content/themes/wpcasa/lib/assets/js/styleswitcher.js"></script>
Only one of those stylesheets is active at a time, whiche one is handled by the styleswitcher.js file...
function setActiveStyleSheet(title) {
var i, a, main;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
a.disabled = true;
if(a.getAttribute("title") == title) a.disabled = false;
}
}
}
function getActiveStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) return a.getAttribute("title");
}
return null;
}
function getPreferredStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("rel").indexOf("alt") == -1
&& a.getAttribute("title")
) return a.getAttribute("title");
}
return null;
}
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
window.onload = function(e) {
var cookie = readCookie("style");
var title = cookie ? cookie : getPreferredStyleSheet();
setActiveStyleSheet(title);
}
window.onunload = function(e) {
var title = getActiveStyleSheet();
createCookie("style", title, 365);
}
var cookie = readCookie("style");
var title = cookie ? cookie : getPreferredStyleSheet();
setActiveStyleSheet(title);
That is not my code and as mentioned earlier I barely know anything about Javascript.
Then in my search-listings.php file I have this markup to create the selector...
<div class="btn-group">
<button class="btn btn-mini dropdown-toggle" data-toggle="dropdown">View <span class="caret"></span></button>
<ul class="dropdown-menu pull-right">
<li>Grid view</li>
<li>List view</li>
</ul>
</div>
The main issue is that I need the loop counter from the PHP code at the top to run one way or another. The link provided by #aug seemed to make sense, but as far as I know I can't wrap that Javascript around the PHP to achieve what I need to do.
So to recap...
There's a PHP while loop which displays the property listings.
There's a PHP for loop which I wrote inside the while loop to display 2 listings each time the while loop cycles, instead of 1.
The above worked fine until the introduction of the "list" view came about, which due to my lacking PHP knowledge had to be implemented by using a Javascript file to switch the active stylesheet.
I now need a way to still be able to switch to the list view stylesheet, but to either change the $x < 2 to $x < 1 when the list view stylesheet is loaded, OR to be able to have an if / elseif statement that give you either $x < 2 or $x < 1 depending on which stylesheet is loaded.
I hope that makes sense, thanks for all the help so far!
PHP will get processed before any HTML, Javascript or CSS does, so it has no way of telling if the CSS class exists, because it does not exist at that point in time.
In your particular situation I would dump the properties into a JSON object and handle it with Javascript.
EDIT: PHP Specific Solution
Well, I'm making an assumption from your code you are using wordpress, which it may be worth while looking into get_posts() http://codex.wordpress.org/Function_Reference/get_posts
With the limited info and code available, the easiest way is for you that I can see is to set a flag that designates whether or not this is a list view.
lets assume that variable is $listview which is set to true or false.
in your page's template file you can do...
if(!$listview) {
//echo your extra css here...
}
then with your loop you created...
$counter = 0;
if(!$listview) { $hr_counter = 1; } else { $hr_counter = 2; }
while ( have_posts() ) {
// MaxIT - Shows 2 listings per loop instead of 2
for ($x = 0; $x < $hr_counter; $x++) {
// Increase loop counter
$counter++;
the_post();
// Include listing loop template
get_template_part( 'loop', 'listing' );
} // endwhile have_posts()
echo '<hr style="width:100%; padding-left: 40px; margin: 60px 0px;" />';
}
this way you will either do 2 posts then the rule, or 1 post then the rule.
Without seeing more of the code there isn't much else I can assist with in your specific situation.
Hope that helps or gets you headed in the right direction.

array_slice load remaining items

I am returning a large array (of products), and am using array_slice to grab only the first 8 items.
I will implement a "See More" button, which will load the remaining items on the frontend for the user.
<?php
$split_output = array_slice($_associatedProducts, 0, 8); // returns set number of products in array (8), for more button
?>
My question is, how do I then return the remaining items in the array, following the 8 displayed? These items will then be displayed when the user clicks "See More".
Thanks in advance!
Instead of using array_slice, output all values of the array to the page but hide the values from the ninth value onwards (easily achievable with a foreach loop and a counter variable). Apply Javascript to unhide these values on the click of a button:
<?php
$_associatedProducts = array(); // then add values to the array
$num = 0;
foreach($_associatedProducts as $prod){
if(++$num <= 8){
print("<div>$prod</div>");
}
else{
print("<div class=\"more\" style=\"display:none;\">$prod</div>");
}
}
?>
<button type="button" id="myButton">See More</button>
<script type="text/javascript">
document.getElementById("myButton").onclick = function(){
var divs = document.getElementsByClassName("more");
var len = divs.length;
for(var i = 0; i < len; i++){
divs[i].style.display = "block";
}
this.style.display = "none";
}
</script>
Use this go get the remaining items:
$more_output = array_slice($_associatedProducts, 8);
Then place them inside a hidden div:
<div class="moreProducts">
Place your hidden Products here
</div>
Style:
.moreProducts {
display: none;
}
HTML Link:
More Products
jQuery:
$('a.showMore').bind('click', function() {
$('.moreProducts').show();
});
The above code is just an example. You have to change it to your needs.
You can slice the rest with the starting point of where you left. The ninth item (which is offset 8). If you don't supply the length to array_slice it will simply return all remaining items.
$remaining_items = array_slice($_associatedProducts, 8);
If you wan't to do this after the user clicks a link, there are many routes to take on this problem.
Getting the data Asynchronous with JS
Multiple pages, first page has LIMIT 0,8 in the query, the see more page does not.
Simply sending all data to the page, and make the remaining products initially hidden and show them with a button.
Many more...
Below an example of Simply sending all data to the page, and make the remaining products initially hidden and show them with a button.
Which can also be done in many ways, it's just an example.
Then when clicking see more... you can show the remaining items with javascript.
This way you don't even have to slice.
Example:
css:
.hide{
display:none;
}
php / html
<ul id="productlist">
<?php
$i=1;
foreach($_associatedProducts as $product){
$hide = ($i++>8)?' class="hide"':'';
echo "<li$hide>$product</li>";
}
?>
</ul>
<button id="seemore">See more..</button>
Will generate:
<ul id="productlist">
<li>product 1</li>
<li>product 2</li>
<li>product 3</li>
<li>product 4</li>
<li>product 5</li>
<li>product 6</li>
<li>product 7</li>
<li>product 8</li>
<li class="hide">product 9</li>
<li class="hide">product 10</li>
</ul>
<button>See more..</button>
Now add jquery:
$('#seemore').on('click', function(){
$('#productlist>li.hide').removeClass('hide');
});

How to make PHP loop refresh when clicking class tag

Okay so I have this portfolio page where I display a couple of thumbnails, and you can order it by tags, so for example like this:
year 1
And this works fine. However, my thumbnails display at three on a row, so only the first two should have a right margin, the third one no margin.
I used PHP to do this which works fine.
if ($result=$link->query($query)) {
for ($i=1; $i <= $result->num_rows; $i++) {
$row= $result->fetch_assoc();
$id = $row['number'];
$title = $row['title'];
$bgthumbnail = $row['thumbnail'];
if($i%3 == 0){
echo "
<div class=\"thumbnail\">
<a href=\"portfoliodetail.php?id=$id\">
<div class=\"thumbnailOverview noMargin\" style=\"background: url('images/portfolio/thumbnails/$bgthumbnail'); background-position: center center;\">
<div class=\"latestWorkTitle\">$title</div>
</div>
</a>
</div>
";
} else {
echo "
<div class=\"thumbnail\">
<a href=\"portfoliodetail.php?id=$id\">
<div class=\"thumbnailOverview\" style=\"background: url('images/portfolio/thumbnails/$bgthumbnail'); background-position: center center;\">
<div class=\"latestWorkTitle\">$title</div>
</div>
</a>
</div>
";
}
}
$result->close();
}
However, when I click a tag, the margin doesn't update. So when a thumbnail was given no margin in the overview because it was the third one in row, when it displays first because of a chosen tag, it also receives no margin.
Of course this is because nothing "refreshes" or something, but I was wondering if there is an "easy" way to fix this problem? To make the PHP loop run again or something?
You must to set/remove noMargin class name via javascript:
$('.year-clicker').click(function (event) {
event.preventDefault();
var year = $(event.currentTarget).data('year');
$('.thumb').hide().removeClass('noMargin').filter('.year' + year).show();
$('.thumb:visible').each(function (i, e) {
if ((i + 1) % 3 == 0) {
$(e).addClass('noMargin');
}
});
return false;
});
Try out this jsfiddle http://jsfiddle.net/xgE3K/1/
unless your "tags" are recalling the page - so that the php is re-executed - you probably want to look at javascript (or possibly ajax) to do the reformatting of the layout.
Depending on the quantity of thumbnails and the variety of tags, you might use the php to create a div (with a relevant id and a style="" attribute) for each of the different filter tags - containing the layout of the thumbnails for that tag (so you can ensure your layout is fine for each view).
i.e. repeat your code above enclosed by a unique div tag for each view.
Make the default view div visible (style="display: block") and the others hidden (style="dsplay: none").
Then have a javascript function that is executed on any tag click. This will make the relevant div visible and the rest hidden, by changing their style value as above.
Uses a bit more memory, but your switching between views will be quicker than doing a reload.
Despite all this, I think it's cleaner and more scalable to recall the page with the relative filter (depending on the tag) then you will have more control over the layout.

Jquery cycle menu with container

I am trying to link an anchor to cycle to a specific div. This is what I have:
The menu
<div id="mainmenu">
<ul class="sidenav" id="menu">
<li>
<a href="#page2">Serviciile noastre
</a>
</li>
<li>
<a href="#page8">Credite Nevoi personale fara ipoteca
</a>
</li>
<li>
<a href="">Credite Nevoi personale cu ipoteca
</a>
</li>
<li>
<a href="">Credite ipotecare
</a>
</li>
<li>
<a href="">Carduri de credit
</a>
</li>
<li>
<a href="">Credite "Prima Casa"
</a>
</li>
<li>
<a href="">Refinantari credite/carduri
</a>
</li>
<li>
<a href="">Acte necesare
</a>
</li>
<li>
<a href="">Economisire creditare
</a>
</li>
</ul>
</div>
And the JavaScript
var $jts = jQuery.noConflict();
$jts(function() {
// maincontent cycle
$jts('#maincontent').cycle({
fx: 'blindY', // You can choose effect do you like, for reference : http://www.malsup.com/jquery/cycle/browser.html
speed: 'slow',
timeout: 0,
cleartype: true, // true if clearType corrections should be applied (for IE)
cleartypeNoBg: true,
pager: '#menu',
startingSlide : 0,
after:onAfter,
pagerAnchorBuilder: function(idx, slide) {
// return sel string for existing anchor
return '#menu li:eq(' + (idx) + ') a';
}
});
function onAfter(curr, next, opts, fwd){
//get the height of the current slide
var $ht = $jts(this).height();
I am using jquery.cycle.all.min.js.
So if I understand correctly, you wish to have an <a href=... click event to take it to the corresponding slide.
Simplest way to do this for your example slide id of 7:
The link you want to click to view a specific slide:
<!-- support for those strange users
without Javascript - we will fix this later -->
Sample text
Your JS to control the behaviour
//if the user has JS enabled, we will stop the
//link from taking us away from the page
//and only do the sweet animation
$(".go-to").click(function(gt){
gt.preventDefault();
var slide = $(this).attr("rel");
$("#maincontent").cycle(slide);
});
Main things to note:
Use of the rel attribute. Use it, it's great.
Use of the empty selector class go-to - used only to define that particular link to interact with cycle. This can be any name you like (so long as it follows the conventions outlined below), for example foo, bar, coco-the-clown etc.
Finally, the next is a little off-topic, but a useful piece of information none-the-less;
If you want your pages to validate to W3C standards, ID's must be unique, and start with a letter. Direct from the horse's mouth:
ID tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
http://www.w3.org/TR/html4/types.html#type-name
in response to your comment
So the basic premise of what we want to do:
Assign an identifier to each link that corresponds with the slide number - which means this will have to be a number.
Find out the slide order.
Using your link you posted in the comment you should change it to reflect which ever slide number you want to see when clicked, like so:
<a href="credite.php" class="go-to" rel="1" >Credite Nevoi personale fara ipoteca</a>
Also, remove the rel="opt" and class="go-to" from your div element.
If you go and try this now (assuming you have more than 1 slide...) and it is what you wanted, you probably won't need to come back and read the rest.
So when you click the link mentioned above, this should take you to slide number 2 - provided you are not on slide number 2. "What?!" I hear you cry. Read on.
So, if you were to look at the rendered source code in your browser, you will see that inside of your cycle element, maincontent, each of the div elements that are direct descendants of maincontent will be the slides. These are in order (for a computer); 0 is the starting slide and 1 is the second slide, 2 is the third slide ad infinitum.
So - if you are using PHP & MySQL to show your content, it will be super-easy to assign "IDs" to your anchor's rel attributes. Alternatively, you can hard-code these.
Let me know how you did!

Label each row of an HTML table numerically (PHP + MYSQL)

All I want is for the first column of each row in my table to display the number of the current row. For example, please see the following table.
Column Header 1 Column Header 2
1 some data
2 more data
3 some more data
4 even more data
I am familiar with JavaScript (I will most likely understand any JS script posted), CSS, and HTML. I am curious as to whether or not I will have to write a JS function to do this, or if I can somehow just create a variable and increase its index by ' 1 ' each time.
I look forward to your responses!
If you're using PHP, try to get an array of strings for data you want to output:
$data = array('here', 'is', 'some', 'data');
// Avoid printing table if there is no data
if (count($data) > 0) {
echo '<table><tr><td>Column Header 1</td><td>Column Header 2</td></tr>';
for ($i = 0; $i < count($data); $i++) {
echo '<tr><td>', $i + 1, '</td><td>', $data[$i], '</td></tr>';
}
echo '</table>';
}
Try CSS autonumbering
http://www.w3.org/TR/CSS2/generate.html#counters
This is the client side solution. Use it if you can not do it on server side.
Does it have to be a table, or could you use an ol?
<ol>
<li>some data</li>
<li>more data</li>
<li>some more data</li>
<li>even more data</li>
</ol>
Based on kisp's approach of CSS numbering, I created a prototype which appears to do almost what you are looking for. The numbering isn't in a separate collumn, it's in the "before" pseudo-element.

Categories