0

I am trying to use the JQCloud jquery plugin to generate a tag cloud from some Elasticsearch data. The main issue I am facing is that the data I get back is formated using the terms 'key' for tag and 'doc_count' for the number of times the tag shows up in the data. I've tried a few different ways of getting the data to parse correctly but the tag cloud never shows up on the page, nor am I getting any great information from the Chrome Dev tools console.

First call

$(document).ready(function(){
  $.ajax({
    url: "/tags",
    type: "get",
    async: false,
    success: function(data){
            $("#wordCloud").jQCloud([{text: data[0].key, weight: data[0].doc_count}, {text: data[1].key, weight: data[1].doc_count}]);
    }
  });
}); 

Second call

$(document).ready(function(){
  $.ajax({
    url: "/tags",
    type: "get",
    async: false,
    success: function(data) {
      var json = JSON.parse(data);
      $("#tagcloud").jQCloud([json]);
    }
  });
});

Both of these suggestions were taken from Import a JS array using ajax to pass though to a function/plugin in JQuery.

Community
  • 1
  • 1
greyhoundforty
  • 239
  • 2
  • 9
  • 1
    First of all your url seems incomplete. And second, do you have any errors in console? – Ionut Necula Dec 12 '16 at 15:35
  • 2
    And secondly, synchronous requests are deprecated and never been useful, don't use it. And btw, we have no idea what data looks like. Error in console? – A. Wolff Dec 12 '16 at 15:36
  • @lonut The URL is a local call (currently for testing). If I go to localhost:8080/tags I get back the expected JSON data. Also if I manually do some parsing I get a list back of tags but I wanted to automate the building of the cloud. My manual process is ugly – greyhoundforty Dec 12 '16 at 15:47
  • @A.Wolff No error in console which is the confusing part. I have removed the async option. The data comes in like this `[{"key": "ibm_created", "doc_count": 85}, {"key": "ibm_dedicated_public", "doc_count": 74}, {"key": "ibm_third_party", "doc_count": 40}, {"key": "p", "doc_count": 31}, {"key": "service", "doc_count": 30}, {"key": "bluemix", "doc_count": 29}, {"key": "development", "doc_count": 29}, {"key": "cloud", "doc_count": 28}]` – greyhoundforty Dec 12 '16 at 15:49

2 Answers2

1
  1. You never use synchronous Ajax. There is no justification to ever set async: false in an Ajax call.

  2. jQuery parses JSON for you. Unless something is wrong with the server's response you don't need to call JSON.parse() yourself.

  3. You should use the promise-based interface jQuery provides on Ajax calls, as it results higher versatility than the traditional success callback.

  4. If your Ajax call is as simple as "GET this URL and then do something", using $.get() instead of $.ajax() will reduce the necessary lines of code.

  5. Apparently jQCloud expects an array of objects like this: {text: ..., weight: ...}, but your API endpoint does not give you exactly that format. $.map() is there to help you transform the elements of an array.

So with all that in mind, your Ajax call could be rewritten as:

$.get("/tags").done(function (data) {
    var tagCloud = $.map(data, function (item) {
        return {text: item.key, weight: item.doc_count};
    });
    $("#wordCloud").jQCloud(tagCloud);
});

Runnable code sample below:

$.mockjax({
    url: "/tags",
    responseText: [
      {"key": "ibm_created", "doc_count": 85},
      {"key": "ibm_dedicated_public", "doc_count": 74},
      {"key": "ibm_third_party", "doc_count": 40},
      {"key": "p", "doc_count": 31},
      {"key": "service", "doc_count": 30},
      {"key": "bluemix", "doc_count": 29},
      {"key": "development", "doc_count": 29},
      {"key": "cloud", "doc_count": 28}
    ]
});

$.get("/tags").done(function (data) {
    var tagCloud = $.map(data, function (item) {
      return {text: item.key, weight: item.doc_count};
    });
    $("#wordCloud").jQCloud(tagCloud);
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqcloud/1.0.4/jqcloud.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.6.2/jquery.mockjax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqcloud/1.0.4/jqcloud-1.0.4.min.js"></script>

<div id="wordCloud" style="width: 600px; height: 200px;"></div>
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Thanks for the very detailed reply. My JS chops are not very good at the moment. The code is now producing `jquery.min.js:3 Uncaught TypeError: Cannot use 'in' operator to search for '1880'` so it looks like it might not be correctly parsing the JSON data. – greyhoundforty Dec 12 '16 at 16:07
  • For me it's impossible to say why this happens. It's not because of my code, I've added a live code sample as a proof-of-concept. Run it for yourself to see. – Tomalak Dec 12 '16 at 16:43
  • No worries, your help is greatly appreciated. I am digging in to it now. Thanks again. – greyhoundforty Dec 12 '16 at 16:44
  • No idea why (as I am still learning JS and JQuery), but I had to add `data=JSON.parse(data);` before calling the map function. – greyhoundforty Dec 12 '16 at 17:15
  • That's because your server did not send the right content type. Set the `Content-Type: application/json` response header to inform the client of the data format. When jQuery sees that it will parse the JSON for you. That's what I meant by *"Unless something is wrong with the server's response"* in point #2 above. – Tomalak Dec 12 '16 at 17:33
0

on the second one, it is not necessary add [] to json var, json var is already an array

$(document).ready(function(){
  $.ajax({
    url: "/tags",
    type: "get",
    async: false,
    success: function(data) {
      var json = JSON.parse(data);
      $("#tagcloud").jQCloud(json);
    }
  });
});
Emiliano
  • 698
  • 9
  • 30