1

I'm trying to make an XML based menu with JavaScript, XML and jQuery. I've been successful at getting the categories of the menu, but haven't been able to generate the items in the categories.

My script is as follows, and later in this thread, I've asked for suggestions for this code:

var animalsXMLurl = 'http://dl.dropboxusercontent.com/u/27854284/Stuff/Online/XML_animals.xml';
$(function() {
    $.ajax({
        url: animalsXMLurl, // name of file you want to parse
        dataType: "xml",
        success: function parse(xmlResponse) {

            var data = $("item", xmlResponse).map(function() {
                return {
                    id: $("animal_id", this).text(),
                    title: $("animal_title", this).text(),
                    url: $("animal_url", this).text(),
                    category: $("animal_category", this).text().split('/'),
                };
            }).get();
            var first_item = category_gen(data, 0);
            $('ul.w-nav-list.level_2').append(first_item);
            var categnumber = new Array();
            for (i = 1; i <= data.length; i++) //for splitting id, and getting 0 for category_number (1 or 2 or 3...and so on)
            {
                categnumber[i] = data[i].id.split('_');
                console.log(categnumber[i][0]);
                for (j = 1; j <= data.length; j++) //appending via a function.
                {
                    var data_text = category_or_animal(data, categnumber, j);
                    console.log(data_text);
                    $('ul.w-nav-list.level_2').append(data_text);
                }
            }

            function category_or_animal(d, catg, k) {
                var catg1 = new Array();
                var catg2 = new Array();
                var catg1 = d[k].id.split('_');
                if (d[k - 1]) {
                    var catg2 = d[k - 1].id.split('_');
                    //if(d[k-1].id)
                    if (catg1[0] != catg2[0])
                        return category_gen(d, k);
                } else
                    return '</ul>' + animal_gen(d, k);
            }
            function category_gen(d, z) {
                var category_var = '<li class="w-nav-item level_2 has_sublevel"><a class="w-nav-anchor level_2" href="javascript:void(0);"><span class="w-nav-title">' + d[z].category + '</span><span class="w-nav-arrow"></span></a><ul class="w-nav-list level_3">';
                return category_var;
            }

            function animal_gen(d, z) {
                var animal_var = '<li class="w-nav-item level_3"><a class="w-nav-anchor level_3" href="animals/' + d[z].url + '"><span class="w-nav-title">' + d[z].title + '</span><span class="w-nav-arrow"></span></a></li>';
                return animal_var;
            }

        }, error: function() {
            console.log('Error: Animals info xml could not be loaded.');
        }
    });
});

Here's the JSFiddle link for the above code: http://jsfiddle.net/mohitk117/d7XmQ/4/

In the above code I need some alterations, with which I think the code might work, so I'm asking for suggestions:

Here's the function that's calling separate functions with arguments to generate the menu in above code:

function category_or_animal(d, catg, k) {
    var catg1 = new Array();
    var catg2 = new Array();
    var catg1 = d[k].id.split('_');
    if (d[k - 1]) {
        var catg2 = d[k - 1].id.split('_');
        //if(d[k-1].id)
        if (catg1[0] != catg2[0])
            return category_gen(d, k);
    } else
        return animal_gen(d, k) + '</ul>';
}

At the if(catg1[0] != catg2[0]) it checks if the split string 1_2 or 1_3 is equal to 1_1 or 1_2 respectively. By split, I mean the first element: 1 .... if you have a look at the xml: [ :: Animals XML :: ], you'll see that the animal_id is in the format of %category_number% _ %item_number% ... So I need to create the menu with CATEGORY > ITEM (item=animal name)

Now if I could return category_gen() + animal() with animal(){ in a for loop for all the matching category id numbers} then maybe this could be complete! But I don't of a count script for conditioning the for loop (i=0;i<=count();i++)...

Would anyone know of how to get this script functioning?

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
mk117
  • 753
  • 2
  • 13
  • 26
  • Possible duplication is here http://stackoverflow.com/questions/19395257/how-to-count-duplicate-value-in-an-array-in-javascript – Pavlo Mar 21 '14 at 12:25
  • I had already read that page, the count code on that page is for an array which is being sorted and then being counted... How can I use that count function to return `category_gen() + animals_gen()` ?? Could you have a look at the xml and the jsfiddle? Thanks! – mk117 Mar 21 '14 at 12:36

2 Answers2

0

Hard to tell what the provided JSFiddle is trying to do.

This is my best stab at it. I used JQuery to parse the XML out into categories and generate lists of items.

http://jsfiddle.net/d7XmQ/8/

"use strict";

var animalsXMLurl = 'http://dl.dropboxusercontent.com/u/27854284/Stuff/Online/XML_animals.xml';

$(function () {

    var $menu = $('#menu');

    $.ajax({
        url: animalsXMLurl, // name of file you want to parse
        dataType: "xml",
        success: handleResponse,
        error: function () {
            console.log('Error: Animals info xml could not be loaded.');
        }
    });

    function handleResponse(xmlResponse) {
        var $data = parseResponse(xmlResponse);
        createMenu($data);
    }

    function parseResponse(xmlResponse) {
        return $("item", xmlResponse).map(function () {
            var $this = $(this);
            return {
                id: $this.find("animal_id").text(),
                title: $this.find("animal_title").text(),
                url: $this.find("animal_url").text(),
                category: $this.find("animal_category").text()
            };
        });
    }

    function createMenu($data) {
        var categories = {};
        $data.each(function (i, dataItem) {
            if (typeof categories[dataItem.category] === 'undefined') {
                categories[dataItem.category] = [];
            }
            categories[dataItem.category].push(dataItem);
        });
        $.each(categories, function (category, categoryItems) {
            var categoryItems = categories[category];
            $menu.append($('<h2>').text(category));
            $menu.append(createList(categoryItems));
        });
    }

    function createList(categoryItems) {
        var $list = $('<ul>');
        $.each(categoryItems, function (i, dataItem) {
            $list.append(createItem(dataItem));
        });
        return $list;
    }

    function createItem(dataItem) {
        return $('<li>').text(dataItem.title);
    }
});
dannyfritz
  • 396
  • 5
  • 12
  • Hi! I edited your code, and it worked perfectly well!! Here's the thread with jsfiddle of my version of your code: http://stackoverflow.com/questions/22527661/how-to-create-an-xml-based-menu#answer-22579614 – mk117 Mar 22 '14 at 16:31
0

You can solve this without using any for/while loop or forEach.

function myCounter(inputWords) {        
    return inputWords.reduce( (countWords, word) => {
        countWords[word] = ++countWords[word] || 1;
        return countWords;
    }, {});
}

Hope it helps you!

Pablo Souza
  • 61
  • 1
  • 3