Group javascript xml output by letters or other attributes - javascript

I have an xml document that looks something like this
<?xml version="1.0" encoding="UTF-8"?>
<mapPoints>
<annotation cat="A" title="123" type="pointer"/>
<annotation cat="A" title="333" type="pointer"/>
<annotation cat="B" title="555" type="pointer"/>
</mapPoints>
I am parsing the XML into my javascript document.
Now, I want to group the output of my xml file in different divs base on the cat in the xml so that the markup would look something like this
<div class="A">
<ul>
<li>123 cat A</li>
<li>333 cat A</li>
</ul>
</div>
<div class="B">
<ul>
<li>555 cat B</li>
</ul>
</div>
My parsing is working properly but I don't know how I would group the entries and then output them into different divs. The solution needs to be dynamic since it could be a lot of categories.

Using jQuery and assuming you have your xml in a variable xml, try this:
$(xml).find('mapPoints annotation').each(function() {
var class = $(this).attr('cat');
if ($('div.' + class).length == 0) {
$('#annotations').append('<div class="' + class + '"><ul></ul></div>');
}
$('div.' + class + ' ul').append(getLiFromXml(this));
});
getLiFromXml is a function that returns <li>123 cat A</li> for <annotation cat="A" title="123" type="pointer"/> - hopefully, you can easily write it.
UPDATE
Updated the code to add a div first. I assumed that you store all your divs in a container (div, td, whatever...) with id="annotations"

Related

Create a function that shows text of a selected attribute and value based on function parameters in jQuery

This is the problem I am working on:
An HTML div element contains lists of endangered species grouped by continent and the species population status.
<div>
<ul data-continent="North America">
<li data-species="California condor">Critically Endangered</li>
<li data-species="American bison">Near Threatened</li>
</ul>
<ul data-continent="Europe">
<li data-species="Cave bear">Extinct</li>
</ul>
</div>
Write a function that returns how endangered a species is on a particular continent. For example endangeredSpecies('North America', 'American bison') would return 'Near Threatened'.
Now, I did the following;
return $('ul[data-continent="+continent+"]').find('li[data-species="+species+"]').html()
Why does this not work? I thought .find would traverse the selected element (in this case traverse the child elements of ul elements with data-continent = continent) and then apply .html() to it?
Your string interpolation should look like this
return $('ul[data-continent="' + continent + '"]').find('li[data-species="' + species + '"]').html()
Take advantage of jquery's tag find feature.
The best code:
function endangeredSpecies(continent, species) {
return $("ul[data-continent='"+continent+"']>li[data-species='"+species+"']").text();
}

Serialize from ul li with child using jqueryui sortable

I would like to know how to create a JSON or serialize (both is fine) from a ul including
<ul class="menu send ui-sortable">
<li id="pageid_1" class="ui-sortable-handle">Inscription
<ul class="menu send ui-sortable">
<li id="pageid_2" class="ui-sortable-handle">Joueurs en ligne
<ul class="menu send ui-sortable"></ul>
</li>
</ul>
</li>
I cannot find how to create something like this:
pageid[]=1&pageid[1]=2 OR [{"pageid":1,"children":[{"pageid":2}]}]
Meaning, including parent ID in [].
Thank you for your help!
This code will produce the output required
var result = [].map.call(document.querySelectorAll('ul.menu.send.ui-sortable li.ui-sortable-handle'), function(li) {
var parent = '';
if (li.parentNode && li.parentNode.parentNode && li.parentNode.parentNode.nodeName == 'LI' && li.parentNode.parentNode.matches('li.ui-sortable-handle')) {
parent = li.parentNode.parentNode.id.replace(/\D+/g, '');
}
return "pageid[" + parent + "]=" + li.id.replace(/\D+/g, '');
}).join('&');
console.log(result); // pageid[]=1&pageid[1]=2
I haven't thought about how to do the second format, because the first format is easier to produce

JQuery find all elements with a class add their id to a coma separated list

As the title says I want to find all li tags inside an ordered list called #selectable with the class .ui-selected and add their id's to a string with each id separated by a comma.
Here's an example of what my html looks like:
<ol id="selectable">
<li id="1" class="ui-selected"><li>
<li id="2"><li>
<li id="3" class="ui-selected"><li>
<li id="4"><li>
<li id="5" class="ui-selected"><li>
</ol>
Try this:
var selectedIds = $('#selectable .ui-selected').map(function() {
return this.id;
}).get().join(',');
Example fiddle
Was working with my fiddle and couldn't figure out why my test array was returning 10 items in stead of 5. You are not closing your list items use <li></li> in stead of <li><li>.
Your source was missing a /.
I pushed them in an array and converted the array to a string with toString()
var listItems = [];
$('#selectable .ui-selected').each(function(){
var theID = $(this).attr('id');
listItems.push(theID);
});
listItems = listItems.toString();
console.log(listItems);
http://jsfiddle.net/h6G8H/4/

HTML structure in treeview with jQuery

I need to display a HTML structure in a treeview. I found some jQuery treeview plugins but they generally require a list.
Let's take a simple HTML (nodes may have different tags, not only 'div'):
<div id="node1">
<div id="node2">
<div id="node3"></div>
<div id="node4"></div>
</div>
<div>
I want to display it like this:
node1
node2
node3
node4
For now, i'm using this jQuery plugin: treeview
So I need to convert the HTML to an unordered list like this:
<ul>
<li>node1
<ul>
<li>node2
<ul>
<li>node3</li>
<li>node4</li>
</ul>
</li>
</ul>
</li>
</ul>
How can I do this using jQuery? If you think a different approach would be better, please let me know.
Here you go...that was fun. Demo - Updated to not be specific to div tags, and return an element, that could be turned into a html string.
$.fn.convertToUL = function(isTop) {
if(isTop==null) isTop=true;
var ul=$("<ul>");
var li=$("<li>");
li.append($(this).attr("id"));
var children=0;
$(this).children().each(function(){
ul.append($(this).convertToUL(false));
children++;
});
if(children>0)
li.append(ul);
if(li.is(':empty'))
return "";
if(isTop)
return $("<ul>").append(li);
return li;
}
//to get text of elements use .wrap('<div/>').parent().html()
var ulElement=$("#node1").convertToUL();
alert(ulElement.wrap('<div/>').parent().html());
$("#node1").replaceWith(ulElement);

Mustache (or Handlebars) iterating over two lists

I have two arrays:
var content = {
"girls": ["Maria", "Angela", "Bianca"],
"digits": ["21.143.191.2", "123.456.78.90", "971.6.17.18.1"]
};
and a template:
<script id="template" type="text/template">
<ul>
<li>{{girls}}</li>
</ul>
</script>
I'd like the end result to be:
<ul>
<li>Maria</li>
<li>Angela</li>
<li>Bianca</li>
</ul>
I've tried block mustaches like {{#girls}} {{.}} {{/girls}} and {{#digits}} {{.}} {{/digits}} but no matter which way I nest them I seem to get repeats instead of interlacing.
Any Ideas?
PS: Obviously in the future we'll be asking for IP addresses, not phone numbers.
PPS: None of those are intended to be real IPs, please don't try to contact those girls!
You need to rearrange your content so that you can iterate over just one thing. If you combine those two arrays with something like this:
var data = { girls: [ ] };
for(var i = 0; i < content.girls.length; ++i)
data.girls.push({
name: content.girls[i],
number: content.digits[i]
});
Then a template like this:
<script id="template" type="text/template">
<ul>
{{#girls}}
<li>{{name}}</li>
{{/girls}}
</ul>
</script>
should work.
With "mu is too short"'s advice. And a few crazy ideas I came up with an interesting approach to complex templating. *It almost works!
So let's say I have this content (or data or view) which I want to put into a template:
var content = {
title: "Black Book",
girls: ["blonde", "brunette", "redhead"],
digits: ['123', '456', '789'],
calc: function () {
return 2 + 4;
}
};
And I have a template like this:
<script type="text/template" id="template">
<h1>{{title}}</h1>
<h3>{{calc}}</h3>
<ul>
<li>{{hair}}</li>
</ul>
</script>
And the end result I want is this:
<h1>Black Book</h1>
<h3>6</h3>
<ul>
<li>blonde</li>
<li>brunette</li>
<li>redhead</li>
</ul>
The problem we'll encounter is that we have arrays (or lists) nested in our original content, and if we tried to Mustache.render(html, content) we'd end up with only one li item or a whole array within one href="" attribute. So sad...
So he's the approach, pass through the template multiple times. The first time, pass through and replace the top level items, and adjust the template for the next pass through. The second time, adjust one of the lists, and adjust the template for the third pass through, etc for how ever many layers of content you have. Here's the new starting template:
<script type="text/template" id="template">
<h1>{{title}}</h1>
<h3>{{calc}}</h3>
<ul>
{{#hair}}
{{#digits}}
<li>{{hair}}</li>
{{/digits}}
{{/hair}}
</ul>
</script>
On the first pass through fill in the top level stuff, and change {{digits}} to {{.}}
$.each(content, function (index, value) {
template2 = template.replace(/{{title}}/ig, content.title)
.replace(/{{calc}}/ig, content.calc)
.replace(/{{digits}}/ig, '{{.}}');
});
Now you have this:
<h1>Black Book</h1>
<h3>6</h3>
<ul>
{{#hair}}
{{#digits}}
<li>{{hair}}</li>
{{/digits}}
{{/hair}}
</ul>
On the next pass through we'll just call Mustache.render(template2, content.digits); and that should give us:
<h1>Black Book</h1>
<h3>6</h3>
<ul>
{{#hair}}
<li>{{hair}}</li>
<li>{{hair}}</li>
<li>{{hair}}</li>
{{/hair}}
</ul>
And that's where my logic dies, haha. Any help thinking this through would rock! I'm thinking I could take out the {{hair}} block elements and just do a $.each pass through content.girls and stack .replace three times. Or I could try to start with lowest level of content, and work my way up. I dunno.
All this basically leaves me wondering if there's some "logic-less" way for this kind of nesting or multiple pass throughs to be put into mustache does handlebars do it?

Categories

Resources