简体   繁体   中英

strange jquery .tmpl recursion

I have a real head-scratcher here. I am using a .tmpl to create the contents of a hierarchical dropdown combobox. When I use the data and template to just create nested divs the tmpl library works quite nicely.

But when I use a very similar template to create the optgroups and options that go inside the select they end up not nested correctly at all.

The example is here: jsfiddle example

The HTML looks like this:

<div id="MySelect">
</div>
<select id="MySelectData" style='display: none;'>
</select>
<br />
<div id="MyDiv">
</div>
<script id="MyTemplate" type="text/x-jquery-tmpl">
    {{if children}}
    <optgroup label='${data}'>
        {{tmpl(children) "#MyTemplate"}}
    </optgroup> 
    {{else}}
    <option label='${data}'>
        ${data}
    </option>
    {{/if}}
</script>
<script id="MyDump" type="text/x-jquery-tmpl">
    {{if children}}
    <div style="padding: 5px 5px 5px 5px;">
        ${data}
        {{tmpl(children) "#MyDump"}}
    </div> 
    {{else}}
    <div style="padding: 5px 5px 5px 5px;">
        ${data}
    </div>
    {{/if}}
</script>

And the jQuery (including data):

var data = [{
    "data": "Corporate",
    "children": [{
        "data": "Division A",
        "children": [{
            "data": "Department AA",
            "children": [{
                "data": "Product AA1"},
            {
                "data": "Product AA2"}]},
        {
            "data": "Department AB",
            "children": [{
                "data": "Product AB1"}]},
        {
            "data": "Department AC",
            "children": [{
                "data": "Product AC1"},
            {
                "data": "Product AC2"},
            {
                "data": "Product AC3"},
            {
                "data": "Product AC4"}]}]},
    {
        "data": "Division B",
        "children": [{
            "data": "Department BA",
            "children": [{
                "data": "Product BA2"},
            {
                "data": "Product BA`1"}]},
        {
            "data": "Department BB",
            "children": [{
                "data": "Product BB1"},
            {
                "data": "Product BB2"},
            {
                "data": "Product BB3"}]}]},
    {
        "data": "Division C",
        "children": [{
            "data": "Department CA",
            "children": [{
                "data": "Product CA1"}]}]}]}];
$("#MyTemplate").tmpl(data).appendTo('#MySelectData');
$('#MySelect').combo({
    selectId: 'MySelectData',
    editable: false,
    width: 150
});
$("#MyDump").tmpl(data).appendTo('#MyDiv');

And these plugins:

You're trying to nest <optgroup> elements but that is invalid HTML. HTML-5 has this to say about <optgroup> :

Contexts in which this element can be used:
As a child of a select element.
Content model:
Zero or more option elements.

And HTML-4 has this to say :

In HTML 4, all OPTGROUP elements must be specified directly within a SELECT element (ie, groups may not be nested).

So you're giving the browser invalid HTML and the browser is trying to correct it by unnesting the invalidly nested <optgroup> elements. Once the browser has finished correcting your HTML your nesting is gone and get the odd behavior that you're seeing.

How do you solve this? You could use nested <ul> s (inside a hidden <div> ) for the JavaScript version and a completely different <select> without nested <optgroup> elements for the non-JavaScript version. You could also try playing tricks with an extra depth attribute so that your JavaScript could rebuild the nesting (I've done this before, doesn't mean that it is a good idea just that it is possible).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM