Login

django-mptt enabled replacement for SelectBox.js

Author:
anentropic
Posted:
November 5, 2009
Language:
JavaScript
Version:
Not specified
Score:
0 (after 0 ratings)

This snippet is used in conjunction with the code in #1779 to make an mptt-enabled version of the FilteredSelectMultiple widget.

See my blog for full details: http://anentropic.wordpress.com

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * This is based on the SelectBox.js that comes with Django admin media
 * 
 */

var SelectBox = {
    cache: new Object(),
    init: function(id) {
        var box = document.getElementById(id);
        var node;
        SelectBox.cache[id] = new Array();
        var cache = SelectBox.cache[id];
        for (var i = 0; (node = box.options[i]); i++) {
            cache.push({value: node.value, text: node.text, displayed: 1, tree_id: node.getAttribute('data-tree-id'), left_val: node.getAttribute('data-left-value')});
        }
    },
    redisplay: function(id) {
        // Repopulate HTML select box from cache
        var box = document.getElementById(id);
        
        // for some reason both these steps are neccessary to get browsers to work properly...
        for (i = 0; i < box.options.length; i++) {
            box.options[0] = null;
        }
        box.options.length = 0;
        
        SelectBox.sort(id);
        for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) {
            var node = SelectBox.cache[id][i];
            if (node.displayed) {
                newOpt = new Option(node.text, node.value, false, false);
                newOpt.setAttribute('data-tree-id', node.tree_id);
                newOpt.setAttribute('data-left-value', node.left_val);
                box.options[box.options.length] = newOpt;
            }
        }
    },
    filter: function(id, text) {
        // Redisplay the HTML select box, displaying only the choices containing ALL
        // the words in text. (It's an AND search.)
        var tokens = text.toLowerCase().split(/\s+/);
        var node, token;
        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
            node.displayed = 1;
            for (var j = 0; (token = tokens[j]); j++) {
                if (node.text.toLowerCase().indexOf(token) == -1) {
                    node.displayed = 0;
                }
            }
        }
        SelectBox.redisplay(id);
    },
    delete_from_cache: function(id, value) {
        var node, delete_index = null;
        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
            if (node.value == value) {
                delete_index = i;
                break;
            }
        }
        var j = SelectBox.cache[id].length - 1;
        for (var i = delete_index; i < j; i++) {
            SelectBox.cache[id][i] = SelectBox.cache[id][i+1];
        }
        SelectBox.cache[id].length--;
    },
    add_to_cache: function(id, option) {
        // in this case option is an anonymous object, not an html element
        SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1, tree_id: option.tree_id, left_val: option.left_val});
    },
    cache_contains: function(id, value) {
        // Check if an item is contained in the cache
        var node;
        for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
            if (node.value == value) {
                return true;
            }
        }
        return false;
    },
    move: function(from, to) {
        var from_box = document.getElementById(from);
        var to_box = document.getElementById(to);
        var option;
        for (var i = 0; (option = from_box.options[i]); i++) {
            if (option.selected && SelectBox.cache_contains(from, option.value)) {
                SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1, tree_id: option.getAttribute('data-tree-id'), left_val: option.getAttribute('data-left-value')});
                SelectBox.delete_from_cache(from, option.value);
            }
        }
        SelectBox.redisplay(from);
        SelectBox.redisplay(to);
    },
    move_all: function(from, to) {
        var from_box = document.getElementById(from);
        var to_box = document.getElementById(to);
        var option;
        for (var i = 0; (option = from_box.options[i]); i++) {
            if (SelectBox.cache_contains(from, option.value)) {
                SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1, tree_id: option.getAttribute('data-tree-id'), left_val: option.getAttribute('data-left-value')});
                SelectBox.delete_from_cache(from, option.value);
            }
        }
        SelectBox.redisplay(from);
        SelectBox.redisplay(to);
    },
    sort: function(id) {
        SelectBox.cache[id].sort( function(a, b) {
            a_tree_id = parseInt(a.tree_id);
            b_tree_id = parseInt(b.tree_id);
            a_left_val = parseInt(a.left_val);
            b_left_val = parseInt(b.left_val);
            try {
                if (a_tree_id > b_tree_id) return 1;
                if (a_tree_id < b_tree_id) return -1;
                if (a_tree_id == b_tree_id) {
                    if (a_left_val > b_left_val) return 1;
                    if (a_left_val < b_left_val) return -1;
                }
            }
            catch (e) {
                // silently fail on IE 'unknown' exception
            }
            return 0;
        } );
    },
    select_all: function(id) {
        var box = document.getElementById(id);
        for (var i = 0; i < box.options.length; i++) {
            box.options[i].selected = 'selected';
        }
    }
}

More like this

  1. Django Collapsed Stacked Inlines by applecat 1 year, 9 months ago
  2. Django Collapsed Stacked Inlines by mkarajohn 3 years, 10 months ago
  3. Dynamically adding forms to a formset. OOP version. by halfnibble 9 years, 6 months ago
  4. Convert multiple select for m2m to multiple checkboxes in django admin form by abidibo 11 years, 7 months ago
  5. Django admin inline ordering - javascript only implementation by ojhilt 11 years, 11 months ago

Comments

Please login first before commenting.