2

I have looked a lot through this StackExchange but I guess I am not too advanced in using AJAX/Json.

My aim is to have page transitions using Ajax. This was rather easy to accomplish following this article: https://designbycosmic.com/journal/craft-cms-ajax-page-transitions-with-history-pushstate

Now what this article is missing out is the updating of the page title and meta tags. I have done a lot of searches and from what I understand I need to build json files for each page/entry.

So I installed ElementAPI and tried to get the basics working

    <?php
namespace Craft;

return [
    'endpoints' => [
        'news.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'news'],
            'transformer' => function(EntryModel $entry) {
                return [
                    'title' => $entry->title,
                    'url' => $entry->url,
                    'jsonUrl' => UrlHelper::getUrl("news/{$entry->id}.json")
                ];
            },
        ]
    ]
];

But I am getting stuck at this point. I know that I can get the jquery through

  $.ajax({
      type: 'get',
      url: 'news.json',
      data: {
        format: 'json'
      },
      success: function(result){
        $main.html(result);
      },
      error: function(){
        console.log("error.");
        location.reload();
      }
    });

But if I do that I am getting an empty body that loads nothing.

I kind of am stuck here as my knowledge ends.

I would be very grateful for any information on how to progress. I am really looking to understand how this works but without having at least a working model it's hard for me to analyze and reverse-engineer the code.

1 Answer 1

3

You almost certainly don't have to update the meta tags when you use AJAX to load pages like this.

Meta tags are not exposed to the end user; they're there for search engine crawlers and social media embedding (e.g. Facebook) etc. Crawlers will read the meta tag values from the original HTML at the URL being crawled or shared, not whatever values you update to using JavaScript in an AJAX callback.

On the other hand, updating the page/document title can be a good idea, as users will see this value in their browser.

You can update the document title simply by setting

document.title = "Who let the dogs out?"

somewhere in your JavaScript. A good place to do this in regards to the tutorial script you're using would be inside the ajaxLoad() method, i.e.

ajaxLoad = function(html) {
    init();

    /* ----- Here you could maybe add logic to set the HTML title to the new page title ----- */
    document.title = "Who let the dogs out?";

    ...
},

Of course, you'll want to set the document title to something relevant – preferably the "real" page title for that URL. You certainly could use the ElementAPI plugin to pull your entry's title, but that would mean a ton of work and an additional AJAX request. A much simpler way to do it is to set a data-attribute somewhere in the markup returned by the original AJAX call, e.g.:

<div class="js-ajax-wrapper" data-title="{{ siteName }}: {{ entry.title }}">
    {{ entry.body }}
    ...
</div>

And then do something like this in your ajaxLoad() method:

ajaxLoad = function(html) {
    ...
    document.title = $('<div />').append(html).children('.js-ajax-wrapper').data('title');
    ...
},

Note that the designbycosmic.com script has a small bug – in order for the above to work you'll have to change the call to ajaxLoad() inside the success callback for the loadPage() method to ajaxLoad(result); – alternatively, you can ignore the ajaxLoad() method and just change the document title inside the success callback:

success: function(result){
    ...
    document.title = $('.js-main .js-ajax-wrapper').data('title');
    /* ----- Bring In New Content ----- */
    ...    
},

Finally, as an aside your issue with the ElementAPI plugin is that you're returning a JSON payload (containing only the title, url and jsonUrl for the entry), yet you're attempting to inject that data into the DOM as HTML (i.e. $main.html(result);.

3
  • Hey there. Sorry for the late reply I am working on this project at night (I don't have any other time slot left open). Thanks for the detailed comment. I tried it the way you suggested and indeed it does work. I went for the first way and changing the ajaxLoad() to ajaxLoad(results) - it works great. Oddly when I tried it in the complete function it threw out "undefined" but I am happy as it is now. One more thing for the meta tags. As I said I have read a lot and I have found people using ga( 'send', 'pageview', ga_page ); is this necessary?
    – kadir
    Commented Aug 10, 2016 at 23:55
  • Happy I was able to help out, @kadir. And yes, using AJAX and pushState would require manual ga.send() calls to track page views w/ Analytics. The ajaxLoad() method is a good spot for that stuff, too. Commented Aug 11, 2016 at 0:31
  • Thanks a lot for your help mats - Hope I will be able to show off some craftcms greatness later this year then :)
    – kadir
    Commented Aug 11, 2016 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.