Пользовательский вид выпадающих опций с использованием jQuery - PullRequest
3 голосов
/ 27 апреля 2020

Мне нужна помощь с сортировкой опций выпадающего меню. У меня есть следующее:

<select name="models" id="models">
    <option value="14b">14b</option>
    <option value="ab">ab</option>
    <option value="14">14</option>
    <option value="bc">bc</option>
    <option value="15">15</option>
    <option value="101">101</option>
    <option value="13">13</option>
</select>

Я бы хотел отсортировать параметры так, чтобы они выглядели следующим образом:

<select name="models" id="models">
    <option value="ab">ab</option>
    <option value="bc">bc</option>
    <option value="13">13</option>
    <option value="14">14</option>
    <option value="14b">14b</option>
    <option value="15">15</option>
    <option value="101">101</option>
</select>

В раскрывающемся списке будет 2 типа записей, начинающихся с число и те, которые начинаются с буквы. Я хотел бы сначала просто отсортировать те, которые начинаются с буквы в алфавитном порядке, и поместить их в начало раскрывающегося списка. Затем, некоторые из тех, которые начинаются с числа, могут иногда иметь букву или два в конце. Те, у которых есть буквы, будут считаться на один шаг больше, чем те, у которых нет символов, и будут располагаться впоследствии, поэтому порядок будет 14> 14b> 15, например

. Я искал и нашел несколько сообщений о том, как сортировать списки. / dropdowns, но это немного сложнее, и я не могу понять, как собрать все воедино. Может кто-нибудь, пожалуйста, помогите? Спасибо!

Ответы [ 2 ]

3 голосов
/ 27 апреля 2020

Попробуйте это

function natcmp(a, b) {
    var ra = a.innerText.match(/\D+|\d+/g);
    var rb = b.innerText.match(/\D+|\d+/g);
    var r = 0;

    while(!r && ra.length && rb.length) {
        var x = ra.shift(), y = rb.shift(),
            nx = parseInt(x), ny = parseInt(y);
        if(isNaN(nx) && isNaN(ny))
           { r = x > y ? 1 : -1}
        else if(isNaN(nx) || isNaN(ny))
           { r = x < y ? 1 : (x > y ? -1 : 0); }
        else
            r = nx - ny;
    }
    return r || ra.length - rb.length;
}


$("#models").html(
Array.prototype.slice.call($("#models")[0].querySelectorAll("option"), 0).sort(natcmp)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="models" id="models">
    <option value="14b">14b</option>
    <option value="ab">ab</option>
    <option value="14">14</option>
    <option value="bc">bc</option>
    <option value="15">15</option>
    <option value="101">101</option>
    <option value="13">13</option>
</select>
1 голос
/ 27 апреля 2020

Мы можем сделать это следующим образом (vanilla JS):

(По существу, поместите дочерние элементы в массив, отсортируйте их, а затем добавьте их снова в порядке отсортированного массива - по существу, перемещая их в правильном порядке)

(Функция сортировки, в основном, проверяет, есть ли у a и b целые числа, которые могут быть проанализированы - если да, сравните их, и равны ли они, сравнивайте и буквы после чисел. Если оба только Буквы выполняют только текстовое сравнение. Если a - только буквы, а b имеет хотя бы цифры, то a идет первым и наоборот)

const select = document.querySelector('#models');

[...select.children].sort(mySort).map(node => select.appendChild(node));
console.log([...select.children]);

function mySort(a,b) {  
  const [a_val, b_val]  = [a.value, b.value];
  
  if (Math.abs(parseInt(a_val) - parseInt(b_val)) >= 0){
    //both are numbers (or at least start with numbers)
    if (parseInt(a_val) - parseInt(b_val) == 0){
      //then we need to compare the letters after too:
      const a_letters = a_val.replace(parseInt(a_val), "");
      const b_letters = b_val.replace(parseInt(b_val), "");
      return a_letters.localeCompare(b_letters)
    } else {
      //the letters after don't matter for comparison:
      return parseInt(a_val) - parseInt(b_val)
    }        
  } else if(Math.abs(parseInt(a_val)) >= 0) {
    //only a is a number, so b goes first:
    return 1;    
  } else if(Math.abs(parseInt(b_val)) >= 0) {
    //only b is a number, so a goes first:
    return -1;    
  } else {
    //both are letters only so do a textual comparison:
    return a_val.localeCompare(b_val)
  }  
    
}
<select name="models" id="models">
    <option value="14b">14b</option>
    <option value="ab">ab</option>
    <option value="14">14</option>
    <option value="bc">bc</option>
    <option value="15">15</option>
    <option value="101">101</option>
    <option value="13">13</option>
</select>

Выход:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...