SitePoint Sponsor

User Tag List

Results 1 to 4 of 4
  1. #1
    SitePoint Zealot Skibum1321's Avatar
    Join Date
    Jun 2003
    Location
    Malden, MA
    Posts
    142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Removing Select Menu Items on the Fly

    I currently am creating a form where I allow the user to add new select lists on the fly. I do not want the new selects to have the options that are selected in any of the others. For example, if a user selected Windows in a select box, then Windows should not appear in any of the others.

    As I see it, this involves doing 2 things:
    1) Whenever I add a new select, I need to remove all elements that are selected in any other select.
    2) Whenever I change the value of a select, I need to update every select to remove that option from the list and add the old one back in.

    I have implemented part 1, but I would be welcome to ideas on how it could be done faster or cleaner:

    Code JavaScript:
    function addOSFields( dupID )
    {
        var newField = document.getElementById(dupID).cloneNode(true);
        newField.id = '';
        newField.style.display = '';
     
        // Remove all of the options that are already selected from our menu
        var osTable = document.getElementById('os_add_table');
        var oss = osTable.getElementsByTagName('select');
        var selOS = getSelectedOS(oss);
        var opts = newField.getElementsByTagName('option');
        for( var i=0; i < selOS.length; i++  )
        {
            for( var j=0; j < opts.length; j++  )
            {
                if( selOS[i] == opts[j].value )
                {
                    alert( "REMOVE " + selOS[i] );
                    opts[j].parentNode.removeChild(opts[j]);
                }
            }
        }
     
        document.getElementById('os_add_table').firstChild.appendChild(newField);
    }
     
    function getSelectedOS( oss )
    {
        var sel = new Array();
     
        // Get all of our OS selects and put their values in an array
        for( var i=0; i < oss.length; i++  )
        {
            if( oss[i].value )
            {
                sel[i] = oss[i].value;
            }
        }
     
        return sel;
    }

    As for the second part, I need to figure out a way to determine what is the value that must be added to all of my lists. Either that or I could replace all of the lists on the fly and just remove any of the selected items.

    Any suggestions?
    Keith Rousseau

  2. #2
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Storing references to options

    How about this kind of thing?

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
    	<title>Select Lists</title>
    	<script type="text/javascript">
    	window.onload = function() {
    		var sels = document.getElementsByTagName("select");
    		for (var i = 0; i < sels.length; i++) {
    			sels[i].lookup = {};
    			var opts = sels[i].getElementsByTagName("option");
    			for (var j = 0; j < opts.length; j++) {
    				sels[i].lookup[opts[j].value] = opts[j];
    			}
    			sels[i].onchange = function() {
    				for (var k = 0; k < sels.length; k++) {
    					if (sels[k] != this) {
    						if (sels[k].stored) {
    							sels[k].appendChild(sels[k].stored);
    							sels[k].stored = null;
    						}
    						sels[k].removeChild(sels[k].lookup[this.value]);
    						sels[k].stored = sels[k].lookup[this.value];
    					}
    				}
    			}
    		}
    	}
    	</script>
    </head>
    <body>
    <select>
    <option value="windows">Windows</option>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    </select>
    <select>
    <option value="windows">Windows</option>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    </select>
    <select>
    <option value="windows">Windows</option>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    </select>
    <select>
    <option value="windows">Windows</option>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    </select>
    </body>
    </html>
    Each select element maintains a lookup of its options keyed by their values. When an option is selected the value is passed to the other selects which remove and store their elements of the same value.

    Let me know if it doesn't make any sense.

  3. #3
    SitePoint Zealot Skibum1321's Avatar
    Join Date
    Jun 2003
    Location
    Malden, MA
    Posts
    142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It seems like that would work, but I need them to be in alphabetical order, where you append them to the end of the list.

    What I ended up doing is just cloning a select box, removing the selected elements and then replacing the existing select box. Here is a selection from the code:

    Code:
    function updateOSMenus()
    {
        var osTable = document.getElementById('os_add_table');
        var oss = osTable.getElementsByTagName('select');
        var selOS = getSelectedOS(oss);
        for( var i=0; i < oss.length; i++  )
        {
            var selected = oss[i].value;
            addOSSelect(oss[i], selOS, selected);
        }
    }
    
    function getSelectedOS( oss )
    {
        var sel = new Array();
        
        // Get all of our OS selects and put their values in an array
        for( var i=0; i < oss.length; i++  )
        {
            if( oss[i].value )
            {
                sel[i] = oss[i].value;
            }
        }
        
        return sel;
    }
    
    function addOSSelect( el, selOS, selected )
    {
        var newField = document.getElementById('os_select').cloneNode(true);
        newField.id = '';
        newField.style.display = '';
        
        // Remove all of the options that are already selected from our menu
        var osTable = document.getElementById('os_add_table');
        var opts = newField.getElementsByTagName('option');
        for( var i=0; i < selOS.length; i++  )
        {
            for( var j=0; j < opts.length; j++  )
            {
                if( selOS[i] == opts[j].value && selOS[i] != selected )
                {
                    opts[j].parentNode.removeChild(opts[j]);
                } else if( opts[j].value == selected ) {
                    newField.selectedIndex = j;
                }
            }
        }
        
        el.parentNode.replaceChild(newField, el);
    }
    Keith Rousseau

  4. #4
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks good.
    I tweaked my code so it maintains the original order of the select items.
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
    	<title>Select Lists</title>
    	<script type="text/javascript">
    	window.onload = function() {
    		var sels = document.getElementsByTagName("select");
    		for (var i = 0; i < sels.length; i++) {
    			var opts = sels[i].getElementsByTagName("option");
    			sels[i].opts = [];
    			for (var j = 0; j < opts.length; j++)
    				sels[i].opts.push({el:opts[j], show:true});
    				
    			sels[i].onchange = function() {
    				for (var i = 0; i < sels.length; i++) {
    					if (sels[i] !== this) {
    						for (var j = 0; j < sels[i].opts.length; j++) {
    							if (this.value == sels[i].opts[j].el.value)
    								sels[i].opts[j].show = false;
    							else if (this.stored && this.stored == sels[i].opts[j].el.value)
    								sels[i].opts[j].show = true;
    							
    							if (sels[i].opts[j].show) 
    								sels[i].appendChild(sels[i].opts[j].el);
    							else if (sels[i].opts[j].el.parentNode && sels[i].opts[j].el.parentNode === sels[i])
    								sels[i].removeChild(sels[i].opts[j].el);
    						}
    					}
    				}
    				this.stored = this.value;
    			}
    			
    		}
    	}
    	</script>
    </head>
    <body>
    <select>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    <option value="windows">Windows</option>
    </select>
    <select>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    <option value="windows">Windows</option>
    </select>
    <select>
    <option value="linux">Linux</option>
    <option value="macosx">Mac OS X</option>
    <option value="unix">UNIX</option>
    <option value="windows">Windows</option>
    </select>
    </body>
    </html>
    It's a bit mind bending but seems to work ok.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •