Laravel 4 custom pagination: go to first/last page and show a fixed number of links - laravel-4

I'm using the default Bootstrap slider navigation in Laravel 4 and it works very nice: but now I'd like improve it with two customizations, and I have no clue how:
1: Add a "go to first page" at the beginning, disabled if we are in the first page; and an analogous "go to last page" at the end, disabled if we are in the last page (please see how the arrows are changed compared to default Laravel stuff! I'd like to use "double arrows" (« and ») for "go to first/last", and a single arrow (‹ and ›) for "go to prev/next:
<ul class="pagination">
<li class="disabled"><span>«</span></li>
<li class="disabled"><span>‹</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>›</li>
<li>»</li>
</ul>
2: Show a custom number of links at a time (i.e. 5) instead of the default long list:
<ul class="pagination">
<li class="disabled"><span>«</span></li>
<li class="disabled"><span>‹</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>›</li>
<li>»</li>
</ul>
or
<ul class="pagination">
<li>«</li>
<li>‹</li>
<li>2</li>
<li>3</li>
<li class="active"><span>4</span></li>
<li>5</li>
<li>6</li>
<li>›</li>
<li>»</li>
</ul>
Want to see a picture? This is how it should be for various pages (it's an old procedural PHP built on Bootstrap 2.3.2... I have the original code but don't know how to "translate" into Laravel OOP)
So far I made a custom.php view and changed line 'pagination' => 'pagination::slider-3' in laravel/app/config/view.php to 'pagination' => 'pagination::custom'
Then, in custom.php view, I am stuck on:
<?php
$presenter = new Illuminate\Pagination\BootstrapPresenter($paginator);
?>
<?php if ($paginator->getLastPage() > 1): ?>
<ul class="pagination">
</ul>
<?php endif; ?>
Please, any help?
Thanks in advance!

Here you go.
<?php
class MyPresenter extends Illuminate\Pagination\BootstrapPresenter {
public function render()
{
if ($this->currentPage == 1) {
$content = $this->getPageRange(1, $this->currentPage + 2);
}
else if ($this->currentPage >= $this->lastPage) {
$content = $this->getPageRange($this->currentPage - 2, $this->lastPage);
}
else {
$content = $this->getPageRange($this->currentPage - 1, $this->currentPage + 1);
}
return $this->getFirst().$this->getPrevious('‹').$content.$this->getNext('›').$this->getLast();
}
public function getFirst($text = '«')
{
if ($this->currentPage <= 1)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl(1);
return $this->getPageLinkWrapper($url, $text);
}
}
public function getLast($text = '»')
{
if ($this->currentPage >= $this->lastPage)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl($this->lastPage);
return $this->getPageLinkWrapper($url, $text);
}
}
}
Feel free to change MyPresenter class name, and in your custom view:
<ul class="pagination">
<?php echo with(new MyPresenter($paginator))->render(); ?>
</ul>
Of course this is not quite perfect (you'll probably run into problem if total pages is less than 3), but this will set you on the right track.

Related

I have problem with my code "UNDEFINED INDEX"

There is link to my previous problem where is code,maybe it helps you
Parse error: syntax error, unexpected '__construct' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)
this is problem i get
Undefined index: item (View: C:\xampp\htdocs\laravel\resources\views\shoppingCart.blade.php)
this error is there <strong><?php echo e($product['item']['name']); ?></strong>
this is my route
Route::get('shoppingCart', 'WebController#shoppingCart')->name('get.shoppingCart');
this is in my webcontroller
public function shoppingCart(){
if(!Session::has('cart')){
return view('shoppingCart');
}
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
return view('shoppingCart',['products'=>$cart->items]);
}
this is link for cart
<li>CART <span class="badge">{{Session::has('cart') ? '!' : ''}}</span></li>
And this is my code for shoppingCart
#extends('layouts.main')
#section('content')
#if(Session::has('cart'))
<div>
<div>
<ul class="list-group">
#foreach($products as $product)
<li class="list-group-item"></li>
<strong>{{$product['item']['name']}}</strong>
<li>Odstrániť</li>
#endforeach
</ul>
</div>
</div>
#else
<div>
<h2>V košíku nemáš žiadne položky!!!</h2>
</div>
#endif
#endsection
Firstly you can check if you have data or not on $cart->items while writing dd($cart->items); on the your function . Follow my comments .
public function shoppingCart(){
if(!Session::has('cart')){
return view('shoppingCart');
}
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
//dd($cart->items) /*uncomment this and check if you have data or not if you have no then problem is */
return view('shoppingCart',['products'=>$cart->items]); /* on the other if you have data dont forget those line and look at my comment on blade.php */
}
Your blade.php
#extends('layouts.main')
#section('content')
#if(Session::has('cart'))
<div>
<div>
<ul class="list-group">
#foreach($products as $product)
<li class="list-group-item"></li>
<strong>{{$product['item']['name']}}</strong>
<!--Look at here you remembe you were add products writing `['products'=>$cart->items]` then you be care calling your datas first you be relay on your codes you are working array (it seems you are working with objects then you need to call it $products->item->name Secondly you remember on the function you were add your data `['products'=>$cart->items]` like this if there is no child items object on $cart->items then you need to call it like
foreach($products as $product))
{
echo $product->name; //if it is array then echo $product['name'];
}
-->
<li>Odstrániť</li>
#endforeach
</ul>
</div>
</div>
#else
<div>
<h2>V košíku nemáš žiadne položky!!!</h2>
</div>
#endif
#endsection

Laravel Blade Changing Active Class Bootstrap

How will I change the active class in twitter bootstrap when i visit another page with Laravel Blade Templating ?
here is an example this might can help
You could define a variable in your blade template
<?php $nav_profile = 'active'; ?>
#extends ('layouts.app')
#section ('content')
..
..
#endsection
And then in the layouts file;
<ul class="nav nav-tabs">
<li role="presentation" class="{{ $nav_home or '' }}">Home</li>
<li role="presentation" class="{{ $nav_profile or '' }}">Profile</li>
<li role="presentation" class="{{ $nav_messages or '' }}">Messages</li>
</ul>
So, if the page includes a variable called nav_profile then insert 'active' into the class. The 'or 'part inserts an empty string if the variable is not present.
I have found a simple solution for this problem. This solution has very simple trick.
And it will work for all links throughout the page.
<script>
function addActiveClass(){
var objs = document.getElementsByTagName('a'); // take all 'a' tags
for(var i = 0; i < objs.length; i++){
if(objs[i].href == window.location.href){ // check if the user is on this link
objs[i].className = objs[i].className + " active"; // add additional 'active' class
}
}
}
addActiveClass();
</script>
Adding this code to the end of your page will do the magic.

Recursive display of data with blade, laravel

My Controller:
class Comments extends Controller {
public function GenerateComments($id){
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
return view('comments', ['Themes'=>$theme, 'Comments'=>$Comments]);
}
My Table(NewTheme_Comment):
id
parent_id
id_theme
user
text
upVotes
downVotes
My view(contains the recursive display of the tree of comments like the same in reddit), ......(data) contains the bootstrap media object, and the </div>'s things are used to round up (visually) the tree of comments as it should be:
<?php
tree($Comments, 0, 0);
$var = -1;
function tree($Comments, $parent_id = 0, $level=0, $c=0) {
global $var;
foreach($Comments as $Comment) {
if($Comment['parent_id'] == $parent_id) {
If ($level > $var) $var++; else {
for ($i = $var-$level+1; $i>0; $i--) { if ($c < 0) echo '</div> </div>'; else $c--; };
$var=$level;
};
echo '........(data)';
tree($Comments, $Comment['id'], $level+1,$c);
};
};
};
?>
The problem is that .........(data) should contain this stuff:
<div class="media">
<div class="media-left">
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/upVote.svg") }}" >
<div>{{$Comment->upVotes-$Comment->downVotes}}</div>
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/downVote.svg") }}" >
</div>
<div class="media-body">
<p class="media-heading">{{ $Comment->text }}</p>
<p class="media-heading">{{ $Comment->user }} / {{ $Comment->created_at }} </p>
And I am using the blade above this line | , which I can't integrate into that echo in view, replacing the ..........(data).
I have the intuition that the function I should integrate into the controller but I am broken(I spent to much time on recursive method of displaying comments) and I don't know how to take the data and print out it as whole unit recursively.
Any help is GREATLY appreciated to find a way out of this mess, thank you very much
Edit 1:
This is an example if i am filling with bootstrap media object in ........(data):
<div class="media">
<a class="media-left" href="#">
<img class="media-object" src="..." alt="...">
</a>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
Without 2 x </div>
You are approaching the views in a wrong way, as blade templates are not meant to use functions, it's better to follow the below recommendations.
The best way for that is to place the function code inside a blade file, for example recursive.blade.php:
recursive.blade.php
#foreach($comments as $comment)
//place your code here
#endforeach
Then in your main blade you can call it several times:
main.blade.php
<div>
#include('recursive', ['comments' => $comments])
</div>
The below example works for me and is the most widely used approach. remember the default value for parent_id is -1.
Model
public function children(){
return $this->hasMany(self::class,'parent_id','id')->with('children');
}
Controller
$comments = Comments::where('parent_id','=',-1)->get();
return view('comments',['comments'=> $comments]);
Blade (comments.blade.php)
<div class="tree">
#include('comment-list-widget',['comments' => $comment])
</div>
Blade (comment-list-widget.blade.php)
<ul>
#foreach($comments as $comment)
<li>
<a>{{$comment->text}}</a>
#if(!empty($comment->children) && $comment->children->count())
#include('comment-list-widget',['comments' => $comment->children])
#endif
</li>
#endforeach
</ul>

Load an HMVC module view within an Iframe in Codeigniter

I'm new at this and some help will be apprciated.
I'm building a sidebar in a CI-Boilerplate-Project which contains modules (widgets) that i got run with HMVC https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc.
In the sidebar i have a widget that display a friendslist with status online/offline.
The user has the ability to switch the widgets on/off in the managementsection.
In the Profileview:
<aside class="sidebox right">
<?php foreach ($boxes as $boxName => $boxSetting)
{
echo Modules::run($boxName, $boxSetting['box_visible']);
}
?>
</aside>
if box_visible == 1 the widget will be displayed.
Controller:
class Myfriends extends SM_Controller
{
function __construct()
{
parent::__construct();
}
public function index($visible = false)
{
$user = $this->session->userdata('user');
$myf = $this->widget_model->get_friends($user['user_id'], 5);
$data['friends'] = $myf;
if ($visible) $this->load->view('myfriends', $data);
}
}
View:
<html>
<head>
<meta http-equiv="refresh" content="5">
</head>
<body>
<div class="box friendsbox">
<div id="header"><h3><?=$boxTitle?></h3></div>
<div id="boxcontent">
<ul>
<?php foreach ($friends as $friend): ?>
<li>
<div id="thb_img">
<img src="<?=img_thumb($friend['file_path'], 50, 50) ?>" />
</div>
<div id="short_desc">
<a href="<?= site_url('widget_functions/show_user/' . $friend['uu_id']) ?>">
<?= ucfirst($friend['user_name']) . ' ' . ucfirst($friend['user_lastname']) . ' ' ?>
</a>
<?php if ($friend['is_online']): ?>
<span style="color: green">online</span>
<?php endif; ?>
</div>
</li>
<?php endforeach; ?>
</ul>
</div>
<div id="footer">» mehr</div>
</div>
</body>
</html>
Now, i need to update the friendslist every 1-2 min so i tryed to load the moduleview within an iframe:
<aside class="sidebox right">
<?php foreach ($boxes as $boxName => $boxSetting): ?>
<?php if ($boxName == 'myfriends' && $boxSetting['box_visible'] == 1) { ?>
<iframe src="<?php echo site_url('myfriends/index'); ?>" ></iframe>
<?php
}
else
{
echo Modules::run($boxName, $boxSetting['box_visible']);
}
?>
<?php endforeach; ?>
</aside>
BUT this dose not work! The place of the widget is emtpy.
Do you have any idea how to get that to work?
appreciate your help
I believe the main issue is with the way you initialize the index method. the index method is kinda tricky with parameters in Codeigniter. In my projects, the only way to get the vlues of arguments passed to the index parameters is by using the URI library method $this->uri->segment(n). In other words, I believe that the value of $visible is not properly passing to the index() body
Anyway, I think you should create another method in your MyFriends Class called render() for example, and call it instead of relaying on the index() method. now render() can play nicely with the $visible=false initialization trick.
Hope this helps

how to fix Dynamic Multiple Drop Down Menu problem in codeigniter?

i have a menu generated dynamically by taking title from database. i have set same table for sub pages by adding a column p_id. and my code looks like this.
private $Section = array();
function _menu($root){
$this->db->select('id,title,p_id');
$this->db->Where('p_id',$root);
$this->db->Where('status','active');
$this->db->Where('type','page');
$this->db->order_by('sort');
$query = $this->db->get('pages');
foreach ($query->result() as $row)
{
$this->Section[] = '<ul>';
$this->Section[] = '<li>';
$this->Section[] = anchor('site/page/'.$row->id.'#cont_main',$row->title);
$this->_menu($row->id);
$this->Section[] = '</li>';
$this->Section[] = '</ul>';
}
$query->free_result();
return $this->Section;
}
//get menu tree
function MenuTree(){
return $this->_menu(0);
}
in above _menu() if a nav have two or more child then it doesn't displays because the source populated by it gives extra </ul> and <ul>. the source looks like this
<ul>
<li>menu 1
<ul>
<li><a>menu 1 sub1</a></li>
</ul>
<ul>
<li><a>menu 1 sub2</a></li>
</ul>
</li>
while i am assuming to get:
<ul>
<li>menu 1
<ul>
<li><a>menu 1 sub1</a></li>
<li><a>menu 1 sub2</a></li>
</ul>
</li>
edited
i have to add menu according to child element. image comes in all menus which doesn't have child too due to extra <ul></ul> if i use ul before loop. the source looks like this.
<ul>
<li>menu 1
<ul>
<li><a>menu 1 sub1</a>
<ul></ul>
</li>
<li><a>menu 1 sub2</a></li>
</ul>
</li>
any idea would be appreciable.
You need to add your ul outside the foreach loop AND make sure that you already have results!
if ($query->num_rows() > 0) { // we actually have results, open a UL and loop to add the LIs
$this->Section[] = '<ul>';
foreach ($query->result() as $row) {
You are using
foreach ($query->result() as $row) {
$this->Section[] = '<ul>';
which of course always displays an ul since it does it FOR EACH element. You need to place
$this->Section[] = '<ul>';
and it's closing block outside the loop. If you want it only triggered if there are more than one parent, an IF statement that check's this and reacts accordingly should by everything you need.
The problem that remains seems to be the placing of the ul. You could do
function MenuTree() {
return "<ul>" . $this->_menu(0) . "</ul>";
}
and remove the mentioned ul from above completely to just get the inner loops.

Resources