views:

39

answers:

1

i have a multiple select tag, look at script please

<select multiple="multiple" size="5" id="cities_select">
     <option value="1">city1</option>
     <option value="2">city2</option>
     <option value="3">city3</option>
     <option value="4">city4</option>
     <option value="5">city5</option>
     <option value="6">city6</option>
     ................................
</select>

and jquery script:

$("#supply_cities_select").change(function()
{
    var i = 1;
    $('#supply_cities_select :selected').each(function(u) 
    {
         src += '&c'+i+'='+$(this).val();//generates the string like &c1=1&c2=2&c3=7...
         i++;
    });
})

i need my string not to have elements greater then 5

example:

if i allready have 5 selected elements, my string looks like

&c1=2&c2=3&c3=5&c4=6&c5=7

now if one more option will be selected, i need to get the string

 &c1=3&c2=5&c3=6&c4=7&c5=8

if be short, i need to remove selected attribute of first selected element.

(but i can't use .first here, because it can be element N8 the first selected)

how can i do it?

Thanks a lot.

UPDATE

var a = $("#supply_cities_select :selected").length;
if(a > 5)
{
     $("#supply_cities_select :selected:lt(1)").attr("selected",false);
}

it just remove the firs selected option, isn't it?


+2  A: 

You can do this a little simpler usign .map() and :lt() like this:

var src;
$("#supply_cities_select").change(function() {
  src = $("#supply_cities_select :selected:lt(5)").map(function(i) {
      return '&c'+(i+1)+'='+this.value; //i starts at 0, so add 1
  }).get().join('');
})​;

You can try a demo here. The :lt() selector gets the first 5 (less than 5, 0-based, so (0-4), then we're using .map() to get the values into an array, then just calling .join() to get a string of that array added together.


For the update: to get the last 5 elements it's better to use .slice(), like this:

var src;
$("#supply_cities_select").change(function() {
  src = $("#supply_cities_select :selected").slice(-5).map(function(i) {
      return '&c'+(i+1)+'='+this.value; //i starts at 0, so add 1
  }).get().join('');
})​;

You can give it a try here.

Nick Craver
Thanks much, i don't know about `:lt()` method, and what about another solution, look at update please
Syom
But does this answer this? "if be short, i need to remove selected attribute of first selected element."I guess the only way of effectively doing this is to implement a queue and maintain that alongside the select element. This is probably not the best solution in terms of UX - there's no obvious feedback to indicate that the first-selected item is now unselected, which is compounded when the first-selected item is off-screen.
Simon Scarfe
@Syom - I added how to get the string as if the item was unselected, but I agree with Simon's comment from a UI/UX perspective this may not be the best idea, since it's only 5 tall.
Nick Craver
@Simon Scarfe: I think you are right that you need to keep a queue but you can feedback by deselecting whichever one you are taking off the queue. Though as @Nick Craver said with a height of five there is a fair chance that you won't have the one being taken off in view. I'd personally be inclined to have the list replicated on screen somewhere as standard text that is always visible and showing what is currently selected. http://jsfiddle.net/p8h4a/ shows the showing the separate list thing. (not done the deselecting bit)
Chris