Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel pjax - set up

I am using pjax with laravel for faster page loads for the first time, so I don't have much knowledge about it. I am using this package. I have set it up and it seems to be working, only for some pages where I have some some javascript for the content, I have some issues.

This is my main.js file:

$(document).ready(function() {

    if ($.support.pjax) {
        $.pjax.defaults.timeout = 5000;
    }
    $(document).pjax('.link', "#pjax");

    //add class active to tab based on url
    var loc = window.location.pathname;
    switch (window.location.pathname) {
      case '/admin/statistics':
        $('#statistics').addClass('is-active bulletpoint');
        break;
      case '/admin/articles':
        $('#articles').addClass('is-active bulletpoint');
        $('.tabs').append('<li class="tabs-title search"><i class="ion-ios-search"></i><input id="search-table" type="text" class="search-input" placeholder="Søk"></li>');
        break;
      case '/admin/users':
        $('#users').addClass('is-active bulletpoint');
        $('.tabs').append('<li class="tabs-title search"><i class="ion-ios-search"></i><input type="text" class="search-input" id="search-table" placeholder="Søk"></li>');
        break;
      case '/admin/articles/create':
        $('#create').addClass('is-active bulletpoint');
        break;
      }

      var table = $('#table').DataTable({
        "paging": false,
        "ordering": false,
        "info": false,
        "dom": 'lrtip',
        "language": {
          "zeroRecords": "Ingen treff funnet"
        }
      });

      $('#search-table').keyup(function(){
        table.search($(this).val()).draw();
      });

    //add input field for external media, and remove if empty
    $(document.body).on("input", ".external-media-input:last", function () {
      var inputID = (parseInt($(this).attr('id')) + 1);
      $(".input_fields_wrap").append('<div><input class="external-media-input" id="' + inputID + '" name="external_media[]" type="text"/></div>');
    }).on('blur', ".external-media-input:not(:last)", function () {
        if(!$(this).val()) $(this).remove();
    });

    //autocomplete for challenge question
    $("#challenge_question").autocomplete({
        source: "http://myApp.app/admin/challenges/autocomplete",
        minLength: 2,
        select: function( event, ui ) {
            $('#challenge_question').val(ui.item.id);
        }
    });

    //slider
    var orbit = new Foundation.Orbit($('#slider'));

    //donut charts
    for(var key in myApp.categoryViewsPercentage) {
      $('[id="' + key + '"]').highcharts({
        chart: {
            plotBackgroundColor: null,
            plotBorderWidth: 0,
            plotShadow: false,
            backgroundColor: '#2A2E34'
        },
        credits: {
          enabled: false
        },
        exporting: {
              enabled: false
          },
        title: {
            text: '<style="font-size:14px; color:#FFFFFF">'+ myApp.categoryViewsPercentage[key] + '%</style>' +'<br><style="font-size:8px; color:#FFFFFF"">'+ key +'</style>',
            align: 'center',
            verticalAlign: 'middle',
            y: 0
        },
        plotOptions: {
            pie: {
                borderWidth: 0,
                dataLabels: {
                    enabled: false
                },
                size: 95,
                startAngle: 0,
                endAngle: 360,
            }
        },
        series: [{
            type: 'pie',
            innerSize: '70%',
            data: [
                [key , myApp.categoryViewsPercentage[key]],
                {
                    y: 100 - myApp.categoryViewsPercentage[key],
                    dataLabels: {
                        enabled: false
                    }
                },
            ]
        }]
     });
   }
});

I have links for the content that are above "pjax" container, so they are not part of pjax reloading, set up like this:

<ul class="tabs" data-tabs>
  <li class="tabs-title" id="create"><a href="{{ url('/admin/articles/create') }}" class="link">Nytt inlegg</a></li>
  <li class="tabs-title" id="articles"><a href="{{ url('/admin/articles') }}" class="link">Mine innlegg</a></li>
  <li class="tabs-title" id="statistics"><a href="{{ url('/admin/statistics') }}" class="link">Statistikk</a></li>
  <li class="tabs-title" id="users"><a href="{{ url('/admin/users') }}" class="link">Brukere</a></li>
</ul>

Master blade:

<!DOCTYPE html>
<html lang="en">
<head>
  @section('head')
    @include('layouts.partials.head')
  @show
</head>
<body id="app-layout">
    @section('topBar')
      @include('layouts.partials.top-bar')
    @show
    <div class="expanded row">
        <div class="large-12 columns">
        <div class="large-3 columns">
          @mirror()
        </div>
        <div class="large-9 columns">
          <div>
            @if (count($errors) > 0)
              <div class="alert alert-danger">
                  <ul>
                      @foreach ($errors->all() as $error)
                          <li>{{ $error }}</li>
                      @endforeach
                  </ul>
              </div>
            @endif
          <div class="row expanded columns header">
              @section('headerLinks')
                @include('layouts.partials.headerLinks')
              @show
          </div>
          <div class="content" id="pjax">
            @yield('content')
          </div>
        </div>
      </div>
    </div>
    @include('layouts.partials.foot')
</body>
</html>

I am calling scripts like this:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js" integrity="sha384-I6F5OKECLVtK/BL+8iSLDEHowSAfUo76ZL9+kGAgTRdiByINKJaqTPH/QVNS1VDb" crossorigin="anonymous"></script>
  <script type="text/javascript" src="{{ asset('js/zurb/zurb.js') }}"></script>
  <script type="text/javascript" src="{{ asset('js/jquery-ui/jquery-ui.min.js') }}"></script>
  <script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
  <script type="text/javascript" src="{{ asset('js/jquery-filer/jquery-filer.js') }}"></script>
  <script type="text/javascript" src="{{ asset('js/editor/editor.js') }}"></script>
  <script type="text/javascript" src="{{ asset('js/datepicker/datepicker.js') }}"></script>
  <script src="https://code.highcharts.com/highcharts.js"></script>
  <script src="https://code.highcharts.com/modules/exporting.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
  <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.pjax/1.9.6/jquery.pjax.js"></script>
  <script src="{{ asset('js/charts.js') }}"></script>
  <script src="{{ asset('js/main.js') }}"></script>

One of my issues is that it is not giving the class is-active and bulletpoint to links on page change, and appending input field based on page, because pages are not reloaded so it is not getting new values for window.location.pathname. What would be the best way to set up something like this, so that moving from one to another tab and changing classes behaves smooth.

This part is the setup I have now, in my main.js file:

//add class active to tab based on url
    var loc = window.location.pathname;
    switch (window.location.pathname) {
      case '/admin/statistics':
        $('#statistics').addClass('is-active bulletpoint');
        break;
      case '/admin/articles':
        $('#articles').addClass('is-active bulletpoint');
        $('.tabs').append('<li class="tabs-title search"><i class="ion-ios-search"></i><input id="search-table" type="text" class="search-input" placeholder="Søk"></li>');
        break;
      case '/admin/users':
        $('#users').addClass('is-active bulletpoint');
        $('.tabs').append('<li class="tabs-title search"><i class="ion-ios-search"></i><input type="text" class="search-input" id="search-table" placeholder="Søk"></li>');
        break;
      case '/admin/articles/create':
        $('#create').addClass('is-active bulletpoint');
        break;
      }

Also on my articles/create page I am using jFiler multiple upload, that is not loading with pjax. And on my admin/statistic, I am loading 3 types of charts with data from the server, and it renders two of them, but not the last one.

like image 770
Ludwig Avatar asked May 25 '16 12:05

Ludwig


1 Answers

pjax stands for pushState + AJAX, meaning it uses the History Web API.

This in turn means that with jQuery you can listen to the popstate event that pjax triggers like so:

$(window).on('popstate', function(ev){ 
    console.log('popstate!', ev);
});

And then update the css classes accordingly.

like image 180
Elwin Arens Avatar answered Sep 21 '22 15:09

Elwin Arens