Using the Mobify API to manipulate AJAX responses

M. L. Giannotta Aug 13, 2014 09:48AM PDT

I have a website I am Mobifying which is a complete mess (thanks .NET!). There is a certain set of pages which heavily rely on AJAX to basically repaint the entire application at every step of a form change. Because the code is so horribly coupled, I don't have much leeway; however, my idea is to intercept the AJAX response and basically run the Mobification over that (basically using Dust templates and all that).

It is a loose requirement for my company that we use Mobify 1.1 API (might be able to convince a change if need be), so I have been playing around with extractHTML. Where would I go from there to interact with the extracted HTML, getting the nodes and passing template files to be filled up?

My idea is currently to use UnderscoreJS style templates, but since what I want to do is basically exactly what Mobify does, I don't want to add an extra overhead.

Any pointers are greatly appreciated.

Up 0 rated Down
Michael Aug 13, 2014 05:47PM PDT Mobify Agent

Hi there,

You’ve asked quite a doozy! This is a straightforward task if we split it up into steps, but prepare for a relatively lengthy reply. For the purposes of this question, imagine we have an eCommerce shopping cart page, which updates via AJAX for things like quantity and subtotal. The technique explained below waits for desktop to update content via AJAX, and then replaces that content using a template. (rather than intercepting the data entirely, we let desktop do its thing and then perform our transforms)


Step 1 – The Konf
We set up our template context within Mobify.konf as we normally would. Anything we can find in the page source is fair game here, and any elements which aren’t updated asynchronously can be transformed as usual. To deal with the elements we know are updated via AJAX and to avoid code duplication, attach your transformations to Mobify.$ (or window; but it’s nice not to pollute that namespace) so you can re-use them in the template. Here’s an example snippet from our imaginary Konf:

// The start of our 'cart' template definition
// elements which remain unchanged
‘templateName’: ‘cart’,
‘!match’: function() {
     return $(‘#cart’);
},
‘title’: function() {
      return $(‘#title’);
},
// Elements which are updated via AJAX
‘cart’: function () {
     Mobify.$._transformCart = function($) {
          var $items = $('#desktopCartItems .item').remove();
          ...
          return {
               ‘items’: $items
          };
     };
     return Mobify.$._transformCart($); // if we don't call our function here, we won't transform the content upon first page load!
},

Step 2 – Templating
With the context defined for our cart page, set up your page template per usual - customizing markup and inserting keys from the Konf. Here’s a snippet from an imaginary cart.tmpl file:

<div id=“cartPage”>
     <div class=“title”>{title}</div>
     <div class=“itemsContainer”>
          {>_cartItems/}  <!— This is a template partial, which I'll explain below —>
     </div>
</div>

However, for the content that is updated via AJAX, we’ll use a template partial (which you saw earlier). This will allow us to re-render a portion of HTML without having to re-render the entire template. The syntax for including a template partial is:
{>_cartItems/}
This refers to a template file named _cartItems.tmpl. The underscore prefix is just internal preference for denoting partials vs page templates.

Let’s take a look at that template partial (_cartItems.tmpl) more closely. It’s no different from a normal template; we define our custom markup and include references to keys as usual:

<div id=“desktopCartItems">
     {#cart}
          <li class="m-item">
               {items}
          </li>
     {/cart}
</div>

Note that our template re-uses the id from desktop - we want to make sure that the AJAX requests don’t fail. We’ll also look for this id afterwards so we can replace it.


Step 3 – AJAX
Now for the AJAX. In this example, after desktop writes the new content to the document, we use the function ‘updatedCart’ defined below to re-render our template partial with that new content. Note that this occurs within the page template as a {%script} block:

var updateCart = function() {
     var products = Mobify.$._transformCart(Mobify.$); // the transform we attached to Mobify.$ object in the konf
     dust.render(“_cartItems”, { cart: products }, function(err, output) {
          $(‘#desktopCartItems’).replaceWith($(output));
     };
};
// We listen for the ajax request, and then update our markup.
$(‘body’).ajaxComplete(function(data, xhr, settings) {
     updateCart();
}

Dust’s .render() function is what we’ll use to pass the new content through our template, and it has the form:
dust.render(name, context, callback(error, output))

  • ‘name’ is our template name
  • ‘context’ is a set of keys that the template requires (i.e. we need ‘cart’)
  • ‘callback’ is, well, a callback function that returns the templated html via the ‘output’ argument

Note that our callback function locates the container that was updated by desktop’s AJAX request, and replaces it with ‘output.’ (i.e. the re-rendered _cartItems template). This is what completes our task of updating a template with new asynchronous content.

To reiterate one last time: we aren’t intercepting the data from the AJAX request. We wait for it to be written out to the document, and then replace it using our transforms defined in the Konf passed through a template. This happens so quickly in practice it’s not really noticeable to the user.


Hopefully that made some sense to you and helps you with your task. Let me know if you have any questions or if I need to clarify anything I’ve said.

Best,
Michael

Post Your Public Answer

Your name (required)
Your email address (required)
Answer (required)
support@mobify.me
https://cdn.desk.com/
mobify
Loading
seconds ago
a minute ago
minutes ago
an hour ago
hours ago
a day ago
days ago
about
Invalid characters found
/customer/en/portal/articles/autocomplete