Ticket #13883: 13883-fix.patch

File 13883-fix.patch, 5.1 KB (added by Michael McLarnon, 2 years ago)

Patch to retain option groups, and test

  • django/contrib/admin/static/admin/js/SelectBox.js

    diff --git a/django/contrib/admin/static/admin/js/SelectBox.js b/django/contrib/admin/static/admin/js/SelectBox.js
    index ace6d9dfb8..14c7b8bda7 100644
    a b  
    11'use strict';
    22{
     3    const getOptionGroupName = (option) => option.parentElement.label;
    34    const SelectBox = {
    45        cache: {},
    56        init: function(id) {
     
    78            SelectBox.cache[id] = [];
    89            const cache = SelectBox.cache[id];
    910            for (const node of box.options) {
    10                 cache.push({value: node.value, text: node.text, displayed: 1});
     11                const group = getOptionGroupName(node);
     12                cache.push({group, value: node.value, text: node.text, displayed: 1});
    1113            }
     14            SelectBox.sort(id);
    1215        },
    1316        redisplay: function(id) {
    1417            // Repopulate HTML select box from cache
    1518            const box = document.getElementById(id);
    1619            const scroll_value_from_top = box.scrollTop;
    1720            box.innerHTML = '';
    18             for (const node of SelectBox.cache[id]) {
    19                 if (node.displayed) {
    20                     const new_option = new Option(node.text, node.value, false, false);
     21            let node = box;
     22            let group = null;
     23            for (const option of SelectBox.cache[id]) {
     24                if (option.group && option.group !== group && option.displayed) {
     25                    group = option.group;
     26                    node = document.createElement('optgroup');
     27                    node.setAttribute('label', option.group);
     28                    box.appendChild(node);
     29                }
     30                if (option.displayed) {
     31                    const new_option = new Option(option.text, option.value, false, false);
    2132                    // Shows a tooltip when hovering over the option
    22                     new_option.title = node.text;
    23                     box.appendChild(new_option);
     33                    new_option.title = option.text;
     34                    node.appendChild(new_option);
    2435                }
    2536            }
    2637            box.scrollTop = scroll_value_from_top;
     
    5364            cache.splice(delete_index, 1);
    5465        },
    5566        add_to_cache: function(id, option) {
    56             SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
     67            SelectBox.cache[id].push({group: option.group, value: option.value, text: option.text, displayed: 1});
     68            SelectBox.sort(id);
    5769        },
    5870        cache_contains: function(id, value) {
    5971            // Check if an item is contained in the cache
     
    6981            for (const option of from_box.options) {
    7082                const option_value = option.value;
    7183                if (option.selected && SelectBox.cache_contains(from, option_value)) {
    72                     SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
     84                    const group = getOptionGroupName(option);
     85                    SelectBox.add_to_cache(to, {group, value: option_value, text: option.text, displayed: 1});
    7386                    SelectBox.delete_from_cache(from, option_value);
    7487                }
    7588            }
     
    8194            for (const option of from_box.options) {
    8295                const option_value = option.value;
    8396                if (SelectBox.cache_contains(from, option_value)) {
    84                     SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
     97                    const group = getOptionGroupName(option);
     98                    SelectBox.add_to_cache(to, {group, value: option_value, text: option.text, displayed: 1});
    8599                    SelectBox.delete_from_cache(from, option_value);
    86100                }
    87101            }
     
    90104        },
    91105        sort: function(id) {
    92106            SelectBox.cache[id].sort(function(a, b) {
    93                 a = a.text.toLowerCase();
    94                 b = b.text.toLowerCase();
     107                a = (a.group && a.group.toLowerCase() || '') + a.text.toLowerCase();
     108                b = (b.group && b.group.toLowerCase() || '') + b.text.toLowerCase();
    95109                if (a > b) {
    96110                    return 1;
    97111                }
  • js_tests/admin/SelectBox.test.js

    diff --git a/js_tests/admin/SelectBox.test.js b/js_tests/admin/SelectBox.test.js
    index 7d127b5d59..2808dbcacb 100644
    a b QUnit.test('preserve scroll position', function(assert) {  
    4545    assert.equal(toSelectBox.options.length, selectedOptions.length);
    4646    assert.notEqual(fromSelectBox.scrollTop, 0);
    4747});
     48
     49QUnit.test('retain optgroups', function(assert) {
     50    const $ = django.jQuery;
     51    $('<select id="id"></select>').appendTo('#qunit-fixture');
     52    const grp = $('<optgroup label="group one">').appendTo('#id');
     53    $('<option value="0">A</option>').appendTo(grp);
     54    $('</optgroup>').appendTo('#id');
     55    $('<option value="1">B</option>').appendTo('#id');
     56    SelectBox.init('id');
     57    SelectBox.redisplay('id');
     58    assert.equal($('#id option').length, 2);
     59    assert.equal($('#id optgroup').length, 1);
     60});
Back to Top