Ox.OptionGroup = function(items, min, max, property) { /* to be used by ButtonGroup, CheckboxGroup, Select and Menu */ var property = property || 'checked' length = items.length, max = max == -1 ? length : max; function getLastBefore(pos) { // returns the position of the last checked item before position pos var last = -1; /*Ox.print(items, items.length, length, $.merge( pos > 0 ? Ox.range(pos - 1, -1, -1) : [], pos < items.length - 1 ? Ox.range(items.length - 1, pos, -1) : [] ))*/ // fixme: why is length not == items.length here? Ox.forEach($.merge( pos > 0 ? Ox.range(pos - 1, -1, -1) : [], pos < items.length - 1 ? Ox.range(items.length - 1, pos, -1) : [] ), function(v) { //Ox.print(pos, v) if (items[v][property]) { last = v; return false; } }); return last; } function getNumber() { // returns the number of checked items var num = 0; items.forEach(function(item) { if (item[property]) { num++; } }) return num; } this[property] = function() { // returns an array with the positions of all checked item var checked = []; items.forEach(function(item, i) { if (item[property]) { checked.push(i); } }) return checked; }; this.init = function() { var num = getNumber(), count = 0; //if (num < min || num > max) { items.forEach(function(item) { if (Ox.isUndefined(item[property])) { item[property] = false; } if (item[property]) { count++; if (count > max) { item[property] = false; } } else { if (num < min) { item[property] = true; num++; } } }); //} return items; }; this.toggle = function(pos) { var last, num = getNumber(), toggled = []; if (!items[pos][property]) { // check if (num >= max) { last = getLastBefore(pos); items[last][property] = false; toggled.push(last); } if (!items[pos][property]) { items[pos][property] = true; toggled.push(pos); } } else { // uncheck if (num > min) { items[pos][property] = false; toggled.push(pos); } } return toggled; } return this; }