How to use Ajax and JSON for making dropdown menu?

ajax, javascript, jquery, json, php

Solution

You could store the result of the post request in a javascript array, so you could reuse it, see following please:

var cachedObj = [];

$(document).ready(function(){                
  $('#mnav a').on('click', function() {
    var cat = $(this).attr('id');
    _url = '&category_id=' + cat;
    getData(cat, _url); //<-- Get data from ajax or cache
  });
});

//This function replaces the $.post call (just for example) 
function dummyPost(id, url){
  //url should be used to make the post call
  var data = "<span class='sub'>Test " + id + "</span>";
  return data;
}

function getData(id, url){
  //Try to get data from cache
  var data;
  if(cachedObj[url]) {
    data = cachedObj[url];
    console.log("Data retrived from cache");
  }
  else {
    data = dummyPost(id, url);
    cachedObj[url] = data;
    console.log("Data retrived from post");
  }
  
  $('#mnav .sub').remove();
  //$(data).insertAfter($('#mnav #' + id));
  $('#mnav #' + id).append($(data));
}
.sub{
  color: red;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mnav" class="list-group">
  <a id="1" class="list-group-item active">One</a>
  <a id="2" class="list-group-item active">Two</a>
  <a id="3" class="list-group-item active">Three</a>
</div>

I've maked the `dummyPost` function that should be modified in order to do the post request.

You could see in my example's log, that the first time you click on a link it retrieves his submenu with a "post", the next times instead, it get data from the cached array `cachedObj`.

I hope it helps you. Bye.

Update: Applied to your code should be like:

<script type="text/javascript">

  var cachedObj = []; //<-- Add an array to cache submenus

  //Add a function to retrieves data from cache or REST
  function getData(url){
    //Try to get data from cache
    if(cachedObj[url]) {
      console.log("Data retrived from cache");
    }
    else {
      $.ajax({
         type: 'GET',
         url: 'index.php?route=test%2Fcategory%2Fchild' + url,
         success: function(data) {
               cachedObj[url] = data;
               console.log("Data retrived from post");
            }),
         async:false
      });
    }
    return cachedObj[url];
 }

 $(document).ready(function(){                
    $('#mnav a').on('click', function() {
        var cat = $(this).attr('id');
        var url = '&category_id=' + cat;

        var data = getData(url); //<-- Call the new function to get data
        if(data.length>10){
           $('#mnav #sub').remove();
           $(data).insertAfter($('#mnav #' + cat));
        }
    });
 });
</script>

I can't test it, so it could be contains some errors.

Problem

Here is the code I used to show a category menu in OpenCart with different levels. It works, but after each click it produces more and more `XHR finished loading: POST` and `XHR finished loading: GET`s which stops the page by clicking sometimes: ``` <script type="text/javascript"> _url = ''; $(document).ready(function(){ $('#mnav a').on('click', function() { var cat = $(this).attr('id'); _url = '&category_id=' + cat; $.post('index.php?route=test/category/child' + _url, function(data) { if(data.length>10){ $('#mnav #sub').remove(); $(data).insertAfter($('#mnav #' + cat)); } }); }); }); $.ajaxPrefilter(function( options, original_Options, jqXHR ) { options.async = true; }); </script> ``` HTML Codes: ``` <div id="mnav" class="list-group"> <?php foreach ($categories as $category) { ?> <a id="<?php echo $category['category_id']; ?>" class="list-group-item active"><?php echo $category['name']; ?></a> <?php } ?> </div> ``` Controller codes: ``` <?php class ControllerTestCategory extends Controller { public function index() { if (isset($this->request->get['path'])) { $parts = explode('_', (string)$this->request->get['path']); } else { $parts = array(); } $data['category_id'] = 0; if (isset($parts[0])) { $data['category_id'] = $parts[0]; } else { $data['category_id'] = 0; } if (isset($parts[1])) { $data['child_id'] = $parts[1]; } else { $data['child_id'] = 0; } $this->load->model('catalog/cat'); $data['categories'] = array(); $categories = $this->model_catalog_cat->getCategories(0); foreach ($categories as $category) { $children_data = array(); $filter_data = array( 'filter_category_id' => $category['category_id'], 'filter_sub_category' => true ); $data['categories'][] = array( 'category_id' => $category['category_id'], 'name' => $category['name'], 'children' => $category['children'], 'products' => $category['products'], 'href' => $this->url->link('product/category', 'path=' . $category['category_id']) ); } $this->response->setOutput($this->load->view('test/category', $data)); } public function child() { if (isset($this->request->get['category_id'])) { $this->load->model('catalog/cat'); $data['categories'] = array(); $categories = $this->model_catalog_cat->getCategories($this->request->get['category_id']); $data['x'] = '<div id="sub">'; foreach ($categories as $category) { $data['x'] .= '<li>' . $category['name'] . '</li>'; } $data['x'] .= '</div>'; } else { $data['x'] = 'NA'; } $this->response->setOutput($this->load->view('test/category', $data)); } } ``` SQL codes: ``` public function getCategories($parent_id = 0) { $sql = "SELECT c.category_id, c.parent_id, cd.name, (SELECT COUNT(DISTINCT ch.category_id) from category ch where ch.parent_id = c.category_id and cd.language_id = '" . (int)$this->config->get('config_language_id') . "') as children"; $sql .= " , (SELECT COUNT(DISTINCT p.product_id) FROM product p LEFT JOIN product_description pd ON (p.product_id = pd.product_id) LEFT JOIN product_to_category p2c ON (p2c.product_id = p.product_id) LEFT JOIN category_path cp ON (cp.category_id = p2c.category_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW()) AS items"; $sql .= " FROM category c LEFT JOIN category_description cd ON (c.category_id = cd.category_id) WHERE c.parent_id = '" . (int)$parent_id . "' AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND c.status = '1' ORDER BY c.sort_order, LCASE(cd.name)"; $query = $this->db->query($sql); return $query->rows; } ``` I'd highly appreciate if you kindly help me by providing all necessary JavaScript, jQuery and JSON codes because I know these subjects with little :-(

Original source