function make_combo_select_liste(options, container_source, container_cible, grp) {
    // options : la source des options
    // container_source : l'élément auquel on va rajouter les listes
    // container_cible : l'élément qui va 'recevoir' les éléments cliqués

    var childrens = options.getChildren(); // on récupère les descendants directs (options et optgroup)

    var ul = new Element('ul');            // la liste "source"
    container_source.appendChild(ul);

    var ul_to = new Element('ul');         // la liste "cible"
    container_cible.grab(ul_to);

    for (var i=0; i<childrens.length; i++) {
        var text = '';
        var label = '';

        var li_source = new Element('li');
        li_source.option = childrens[i];             // l'option "source", celle du formulaire initial
        li_source.ul=ul;

        var li_cible = new Element('li').setStyle('display','none'); // le clone de l'élément de liste "source" dans "cible" ( faux clone )
        li_cible.ul=ul_to;

        if (grp) {
            container_source.selectable=container_source.selectable + 1;
            li_source.grp=container_source;
            // todo : calcul de profondeur ?
        }

        if (label = childrens[i].get('label')) {  // C'est un optgroup
            li_source.set('type', 'optgroup');
            li_source.grab(bold(label));
            li_cible.li_source=li_source;    // le li_cible doit connaitre sa source
            li_source.li_cible=li_cible;       // la source doit connaitre sa cible
            li_cible.grab(bold(label));
            li_source.selected=0;
            li_source.selectable=0;
            make_combo_select_liste(childrens[i], li_source, li_cible, true); // l'élément de cible devient container source avec les options du optgroup
        }
        else if(text = childrens[i].get('text')) {  // C'est une option
            li_source.set('type', 'option');
            li_source.appendText(text);
            li_cible.li_source=li_source;    // le li_cible doit connaitre sa source
            li_source.li_cible=li_cible;       // la source doit connaitre sa cible
            li_cible.appendText(text);
        }

        li_cible.show = function () {
            this.setStyle('display', 'block');
        }
        li_cible.hide = function () {
            this.setStyle('display', 'none');
        }

        li_source.select = function () {
            this.setStyle('display', 'none');
            // this.setStyle('color', '#FF0000');
            this.li_cible.show();
            if (this.get('type')=='optgroup') {
                var childrens = this.getElements('li');
                for (var i=0; i<childrens.length; i++) {
                    childrens[i].select();
                }
            }
            else {
                this.option.set('selected', true);
            }
            if (this.grp) {
                this.grp.selected += 1;
                if (this.grp.selected==this.grp.selectable) {
                    this.grp.setStyle('display', 'none');
                }
                this.grp.li_cible.setStyle('display', 'block');
            }
        }

        li_source.deselect = function () {
            this.setStyle('display', 'block');
            // this.setStyle('color', '#00FF00');
            this.li_cible.hide();
            if (this.get('type')=='optgroup') {
                var childrens = this.getElements('li');
                for (var i=0; i<childrens.length; i++) {
                    childrens[i].deselect();
                }
            }
            else {
                this.option.selected=false;
            }
            if (this.grp) {
                this.grp.selected -= 1;
                if (this.grp.selected<this.grp.selectable) {
                    this.grp.setStyle('display', 'block');
                }
                if (this.grp.selected==0) {
                    this.grp.li_cible.setStyle('display', 'none');
                }
            }
        }

        li_source.addEvent('click',  function() {
            this.select();
            colorize(this.ul);
            colorize(this.li_cible.ul);
            return false;
        });

        ul.appendChild(li_source);

        // Gestion du li_cible
        li_cible.addEvent('click',  function() {
            this.li_source.deselect();
            colorize(this.ul);
            colorize(this.li_source.ul);
            return false;
        });

        ul_to.grab(li_cible);

        if (childrens[i].selected) { li_source.select(); }

    }

    colorize(ul);
    colorize(ul_to);

}

function bold(txt) {
    var bold = new Element('strong');
    bold.appendText(txt);
    return bold;
}

function colorize(ul) {
    var k=0;
    var lis = ul.getElements('li');
    for (var i=0; i<lis.length; i++) {
        if (lis[i].getStyle('display')!='none') {
            var zeclass = ((++k%2)==0)?'pair':'odd';
            lis[i].set('class', zeclass);
        }
    }
}

document.addEvent('domready', function() {

    combo_selects = document.getElements('.combo_select');
    for(var i=0; i<combo_selects.length; i++) {
        var rel=$(combo_selects[i].get('rel'));
        if (rel) {
            var container_source=new Element('div', {'class':'combo_select_liste'}); // Le div de substitution du select
            make_combo_select_liste(combo_selects[i], container_source, rel);
            container_source.inject(combo_selects[i], 'after');
        }
    }

});
