[stringtemplate-interest] selecting a dropdown option

Nate misc at n4te.com
Tue May 15 21:08:03 PDT 2007


Cool idea! Here is what I came up with (note I had to add support for 
Java 1.5's Iterable class to AstExpr#convertAnythingIteratableToIterator 
and AstExpr#convertAnythingToIterator)...

<select name="location">
$locations,locationsSelected:{location,selected|
    <option $if(selected)$selected$endif$ 
value="$location.id$">$location.name$</option>
}$
</select>

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class Selection implements Iterable<Boolean> {
    private TreeSet<Integer> indices = new TreeSet();

    public Selection (Integer... indices) {
        add(indices);
    }

    public Selection (Collection values, Object... selectedValues) {
        add(values, selectedValues);
    }

    public void add (Collection values, Object... selectedValues) {
        if (selectedValues == null || selectedValues.length == 0) return;
        Set selectedValuesSet = new HashSet(Arrays.asList(selectedValues));
        int index = 0;
        for (Object value : values) {
            if (selectedValuesSet.contains(value)) add(index);
            index++;
        }
    }

    public void add (Integer... indices) {
        if (indices == null || indices.length == 0) return;
        this.indices.addAll(Arrays.asList(indices));
    }

    public Iterator<Boolean> iterator () {
        return new Iterator() {
            private int index;

            public void remove () {
                throw new UnsupportedOperationException();
            }

            public Boolean next () {
                try {
                    return indices.contains(index);
                } finally {
                    index++;
                }
            }

            public boolean hasNext () {
                return !indices.isEmpty() && index <= indices.last();
            }
        };
    }

    public static void main (String[] args) {
        Selection selection = new Selection(4, 5);
        selection.add(20, 14);
        selection.add(Arrays.asList("a", "b", "c", "d"), "b");
        int i = 0;
        for (Boolean b : selection)
            System.out.println(i++ + ": " + b);
    }
}


John Snyders wrote:
> How about parallel list iteration. I think I may have mentioned this 
> technique in the past but in a different context.
> I was going to say I didn't have time to try my solution out but then 
> I remembered stst.
> Putting stst 
> (http://hardlikesoftware.com/weblog/2007/04/26/on-learning-stringtemplate/) 
> to good use here is an example:
>
> file listData.js is:
> {locations: [
>  { name: "France"},
>  { name: "Canada"},
>  { name: "USA"},
>  { name: "England"},
>  ],
> locsel: [ null, null, 1, null ]
> }
> file selectlist.st is:
> <select name="location">
> $locations,locsel:{location,sel|
>    <option$if(sel)$selected$endif$>$location.name$</option>
> }$
> </select>
>
> stst selectlist listData.js produces:
> <select name="location">
>
>    <option>France</option>
>
>    <option>Canada</option>
>
>    <option selected>USA</option>
>
>    <option>England</option>
>
> </select>
>
> Back before objects were invented rather than have an array of objects 
> with name and selected properties you would sometimes use parallel 
> arrays. You may not have control over the locations collection but you 
> can add your own listsel collection. To make it even better don't 
> actually store an array of null references with one non null one. Just 
> implement your own collection that knows which index is selected and 
> implement an iterator that returns non null for just that index.
>
> -John
>
> Nate wrote:
>> I have a template similar to this where I want to select one of the 
>> locations...
>>
>> <select name="location">
>> $locations:{location|
>>     <option $if(location.name == 
>> selectedLocation)$selected$endif$>$location.name$</option>
>> }$
>> </select>
>>
>> Obviously that isn't valid ST and would break separation. The 
>> location objects are part of an object model I don't have access to, 
>> otherwise I could add an "isSelected" method and use a template like 
>> this...
>>
>> <select name="location">
>> $locations:{location|
>>     <option 
>> $if(location.selected)$selected$endif$>$location.name$</option>
>> }$
>> </select>
>>
>> Is there any other way than to wrap the location objects in my own 
>> class and have a whole slew of delegate methods? This is a common 
>> scenario in my webapp.
>>
>> -Nate
>>
>> _______________________________________________
>> stringtemplate-interest mailing list
>> stringtemplate-interest at antlr.org
>> http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest
>>
>>   



More information about the stringtemplate-interest mailing list