First draft of a select all feature.

This commit is contained in:
Patrick Filler 2012-02-23 18:16:59 -05:00
parent 6a5d61b061
commit 1466f160fc
8 changed files with 179 additions and 21 deletions

View file

@ -387,3 +387,7 @@
direction: rtl; direction: rtl;
} }
/* @end */ /* @end */
/* @group Select all options */
.chzn-select-all { background: #f8f8f8; border-top: 1px solid #ededed; color: #346f9b; cursor:pointer; display: block; font-size: 12px; font-weight: bold; padding: 5px 6px; text-align: center; text-decoration: none; }
/* @end */

View file

@ -106,8 +106,6 @@ Copyright (c) 2011 by Harvest
this.form_field = form_field; this.form_field = form_field;
this.options = options != null ? options : {}; this.options = options != null ? options : {};
this.set_default_values(); this.set_default_values();
this.is_multiple = this.form_field.multiple;
this.default_text_default = this.is_multiple ? "Select Some Options" : "Select an Option";
this.setup(); this.setup();
this.set_up_html(); this.set_up_html();
this.register_observers(); this.register_observers();
@ -116,6 +114,8 @@ Copyright (c) 2011 by Harvest
AbstractChosen.prototype.set_default_values = function() { AbstractChosen.prototype.set_default_values = function() {
var _this = this; var _this = this;
this.is_multiple = this.form_field.multiple;
this.default_text_default = this.is_multiple ? "Select Some Options" : "Select an Option";
this.click_test_action = function(evt) { this.click_test_action = function(evt) {
return _this.test_active_click(evt); return _this.test_active_click(evt);
}; };
@ -129,6 +129,8 @@ Copyright (c) 2011 by Harvest
this.result_single_selected = null; this.result_single_selected = null;
this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
this.disable_search_threshold = this.options.disable_search_threshold || 0; this.disable_search_threshold = this.options.disable_search_threshold || 0;
this.enable_select_all = (this.options.enable_select_all != null) && this.is_multiple ? this.options.enable_select_all : false;
console.log(this.enable_select_all);
this.choices = 0; this.choices = 0;
return this.results_none_found = this.options.no_results_text || "No results match"; return this.results_none_found = this.options.no_results_text || "No results match";
}; };
@ -204,15 +206,15 @@ Copyright (c) 2011 by Harvest
switch (stroke) { switch (stroke) {
case 8: case 8:
if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) { if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
return this.keydown_backstroke(); this.keydown_backstroke();
} else if (!this.pending_backstroke) { } else if (!this.pending_backstroke) {
this.result_clear_highlight(); this.result_clear_highlight();
return this.results_search(); this.results_search();
} }
break; break;
case 13: case 13:
evt.preventDefault(); evt.preventDefault();
if (this.results_showing) return this.result_select(evt); if (this.results_showing) this.result_select(evt);
break; break;
case 27: case 27:
if (this.results_showing) this.results_hide(); if (this.results_showing) this.results_hide();
@ -225,8 +227,9 @@ Copyright (c) 2011 by Harvest
case 17: case 17:
break; break;
default: default:
return this.results_search(); this.results_search();
} }
if (this.enable_select_all) return this.select_all_toggle();
}; };
AbstractChosen.prototype.generate_field_id = function() { AbstractChosen.prototype.generate_field_id = function() {
@ -313,6 +316,7 @@ Copyright (c) 2011 by Harvest
this.container = $('#' + this.container_id); this.container = $('#' + this.container_id);
this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single")); this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single"));
this.dropdown = this.container.find('div.chzn-drop').first(); this.dropdown = this.container.find('div.chzn-drop').first();
if (this.enable_select_all) this.select_all_setup();
dd_top = this.container.height(); dd_top = this.container.height();
dd_width = this.f_width - get_side_border_padding(this.dropdown); dd_width = this.f_width - get_side_border_padding(this.dropdown);
this.dropdown.css({ this.dropdown.css({
@ -560,7 +564,8 @@ Copyright (c) 2011 by Harvest
this.results_showing = true; this.results_showing = true;
this.search_field.focus(); this.search_field.focus();
this.search_field.val(this.search_field.val()); this.search_field.val(this.search_field.val());
return this.winnow_results(); this.winnow_results();
if (this.enable_select_all) return this.select_all_toggle();
}; };
Chosen.prototype.results_hide = function() { Chosen.prototype.results_hide = function() {
@ -574,6 +579,49 @@ Copyright (c) 2011 by Harvest
return this.results_showing = false; return this.results_showing = false;
}; };
Chosen.prototype.select_all_setup = function() {
var select_all_temp,
_this = this;
select_all_temp = $("<a />", {
"class": "chzn-select-all"
}).html("Select all options");
this.dropdown.append(select_all_temp);
this.select_all_link = this.dropdown.find(".chzn-select-all").first();
return this.select_all_link.click(function(evt) {
return _this.select_all_options(evt);
});
};
Chosen.prototype.select_all_options = function(evt) {
var option, options, _i, _len;
evt.preventDefault();
options = this.form_field_jq.find("option");
for (_i = 0, _len = options.length; _i < _len; _i++) {
option = options[_i];
if (!option.disabled) option.selected = true;
}
this.form_field_jq.trigger("liszt:updated");
return this.select_all_disable();
};
Chosen.prototype.select_all_disable = function() {
return this.select_all_link.hide();
};
Chosen.prototype.select_all_enable = function() {
return this.select_all_link.show();
};
Chosen.prototype.select_all_toggle = function() {
var actives;
actives = this.search_results.find("li.active-result");
if (!actives.length || this.search_field.val().length) {
return this.select_all_disable();
} else {
return this.select_all_enable();
}
};
Chosen.prototype.set_tab_index = function(el) { Chosen.prototype.set_tab_index = function(el) {
var ti; var ti;
if (this.form_field_jq.attr("tabindex")) { if (this.form_field_jq.attr("tabindex")) {

File diff suppressed because one or more lines are too long

View file

@ -106,8 +106,6 @@ Copyright (c) 2011 by Harvest
this.form_field = form_field; this.form_field = form_field;
this.options = options != null ? options : {}; this.options = options != null ? options : {};
this.set_default_values(); this.set_default_values();
this.is_multiple = this.form_field.multiple;
this.default_text_default = this.is_multiple ? "Select Some Options" : "Select an Option";
this.setup(); this.setup();
this.set_up_html(); this.set_up_html();
this.register_observers(); this.register_observers();
@ -116,6 +114,8 @@ Copyright (c) 2011 by Harvest
AbstractChosen.prototype.set_default_values = function() { AbstractChosen.prototype.set_default_values = function() {
var _this = this; var _this = this;
this.is_multiple = this.form_field.multiple;
this.default_text_default = this.is_multiple ? "Select Some Options" : "Select an Option";
this.click_test_action = function(evt) { this.click_test_action = function(evt) {
return _this.test_active_click(evt); return _this.test_active_click(evt);
}; };
@ -129,6 +129,8 @@ Copyright (c) 2011 by Harvest
this.result_single_selected = null; this.result_single_selected = null;
this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
this.disable_search_threshold = this.options.disable_search_threshold || 0; this.disable_search_threshold = this.options.disable_search_threshold || 0;
this.enable_select_all = (this.options.enable_select_all != null) && this.is_multiple ? this.options.enable_select_all : false;
console.log(this.enable_select_all);
this.choices = 0; this.choices = 0;
return this.results_none_found = this.options.no_results_text || "No results match"; return this.results_none_found = this.options.no_results_text || "No results match";
}; };
@ -204,15 +206,15 @@ Copyright (c) 2011 by Harvest
switch (stroke) { switch (stroke) {
case 8: case 8:
if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) { if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
return this.keydown_backstroke(); this.keydown_backstroke();
} else if (!this.pending_backstroke) { } else if (!this.pending_backstroke) {
this.result_clear_highlight(); this.result_clear_highlight();
return this.results_search(); this.results_search();
} }
break; break;
case 13: case 13:
evt.preventDefault(); evt.preventDefault();
if (this.results_showing) return this.result_select(evt); if (this.results_showing) this.result_select(evt);
break; break;
case 27: case 27:
if (this.results_showing) this.results_hide(); if (this.results_showing) this.results_hide();
@ -225,8 +227,9 @@ Copyright (c) 2011 by Harvest
case 17: case 17:
break; break;
default: default:
return this.results_search(); this.results_search();
} }
if (this.enable_select_all) return this.select_all_toggle();
}; };
AbstractChosen.prototype.generate_field_id = function() { AbstractChosen.prototype.generate_field_id = function() {
@ -284,7 +287,8 @@ Copyright (c) 2011 by Harvest
this.single_temp = new Template('<a href="javascript:void(0)" class="chzn-single"><span>#{default}</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>'); this.single_temp = new Template('<a href="javascript:void(0)" class="chzn-single"><span>#{default}</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
this.multi_temp = new Template('<ul class="chzn-choices"><li class="search-field"><input type="text" value="#{default}" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>'); this.multi_temp = new Template('<ul class="chzn-choices"><li class="search-field"><input type="text" value="#{default}" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>');
this.choice_temp = new Template('<li class="search-choice" id="#{id}"><span>#{choice}</span><a href="javascript:void(0)" class="search-choice-close" rel="#{position}"></a></li>'); this.choice_temp = new Template('<li class="search-choice" id="#{id}"><span>#{choice}</span><a href="javascript:void(0)" class="search-choice-close" rel="#{position}"></a></li>');
return this.no_results_temp = new Template('<li class="no-results">' + this.results_none_found + ' "<span>#{terms}</span>"</li>'); this.no_results_temp = new Template('<li class="no-results">' + this.results_none_found + ' "<span>#{terms}</span>"</li>');
return this.select_all_temp = new Template('<a href="javascript:void(0)" class="chzn-select-all">#{copy}</a>');
}; };
Chosen.prototype.set_up_html = function() { Chosen.prototype.set_up_html = function() {
@ -308,6 +312,7 @@ Copyright (c) 2011 by Harvest
this.container = $(this.container_id); this.container = $(this.container_id);
this.container.addClassName("chzn-container-" + (this.is_multiple ? "multi" : "single")); this.container.addClassName("chzn-container-" + (this.is_multiple ? "multi" : "single"));
this.dropdown = this.container.down('div.chzn-drop'); this.dropdown = this.container.down('div.chzn-drop');
if (this.enable_select_all) this.select_all_setup();
dd_top = this.container.getHeight(); dd_top = this.container.getHeight();
dd_width = this.f_width - get_side_border_padding(this.dropdown); dd_width = this.f_width - get_side_border_padding(this.dropdown);
this.dropdown.setStyle({ this.dropdown.setStyle({
@ -554,7 +559,8 @@ Copyright (c) 2011 by Harvest
this.results_showing = true; this.results_showing = true;
this.search_field.focus(); this.search_field.focus();
this.search_field.value = this.search_field.value; this.search_field.value = this.search_field.value;
return this.winnow_results(); this.winnow_results();
if (this.enable_select_all) return this.select_all_toggle();
}; };
Chosen.prototype.results_hide = function() { Chosen.prototype.results_hide = function() {
@ -568,6 +574,44 @@ Copyright (c) 2011 by Harvest
return this.results_showing = false; return this.results_showing = false;
}; };
Chosen.prototype.select_all_setup = function() {
var _this = this;
this.dropdown.insert(this.select_all_temp.evaluate({
"copy": "Select all options"
}));
this.select_all_link = this.dropdown.down(".chzn-select-all");
return this.select_all_link.observe("click", function(evt) {
return _this.select_all_options(evt);
});
};
Chosen.prototype.select_all_options = function(evt) {
evt.stop();
this.form_field.select("option").each(function(option) {
if (!option.disabled) return option.selected = true;
});
this.form_field.fire("liszt:updated");
return this.select_all_disable();
};
Chosen.prototype.select_all_disable = function() {
return this.select_all_link.hide();
};
Chosen.prototype.select_all_enable = function() {
return this.select_all_link.show();
};
Chosen.prototype.select_all_toggle = function() {
var actives;
actives = this.search_results.select("li.active-result");
if (!actives.length || this.search_field.value.length) {
return this.select_all_disable();
} else {
return this.select_all_enable();
}
};
Chosen.prototype.set_tab_index = function(el) { Chosen.prototype.set_tab_index = function(el) {
var ti; var ti;
if (this.form_field.tabIndex) { if (this.form_field.tabIndex) {

File diff suppressed because one or more lines are too long

View file

@ -47,6 +47,8 @@ class Chosen extends AbstractChosen
@container.addClass( "chzn-container-" + (if @is_multiple then "multi" else "single") ) @container.addClass( "chzn-container-" + (if @is_multiple then "multi" else "single") )
@dropdown = @container.find('div.chzn-drop').first() @dropdown = @container.find('div.chzn-drop').first()
this.select_all_setup() if @enable_select_all
dd_top = @container.height() dd_top = @container.height()
dd_width = (@f_width - get_side_border_padding(@dropdown)) dd_width = (@f_width - get_side_border_padding(@dropdown))
@ -242,6 +244,7 @@ class Chosen extends AbstractChosen
@search_field.val @search_field.val() @search_field.val @search_field.val()
this.winnow_results() this.winnow_results()
this.select_all_toggle() if @enable_select_all
results_hide: -> results_hide: ->
@selected_item.removeClass "chzn-single-with-drop" unless @is_multiple @selected_item.removeClass "chzn-single-with-drop" unless @is_multiple
@ -249,6 +252,33 @@ class Chosen extends AbstractChosen
@dropdown.css {"left":"-9000px"} @dropdown.css {"left":"-9000px"}
@results_showing = false @results_showing = false
select_all_setup: ->
select_all_temp = $("<a />", { class: "chzn-select-all" }).html("Select all options")
@dropdown.append(select_all_temp)
@select_all_link = @dropdown.find(".chzn-select-all").first()
@select_all_link.click((evt) => this.select_all_options(evt))
select_all_options: (evt) ->
evt.preventDefault()
options = @form_field_jq.find("option")
for option in options
option.selected = true if not option.disabled
@form_field_jq.trigger("liszt:updated")
this.select_all_disable()
select_all_disable: ->
@select_all_link.hide()
select_all_enable: ->
@select_all_link.show()
select_all_toggle: ->
actives = @search_results.find("li.active-result")
if not actives.length or @search_field.val().length
this.select_all_disable()
else
this.select_all_enable()
set_tab_index: (el) -> set_tab_index: (el) ->
if @form_field_jq.attr "tabindex" if @form_field_jq.attr "tabindex"

View file

@ -20,6 +20,7 @@ class Chosen extends AbstractChosen
@multi_temp = new Template('<ul class="chzn-choices"><li class="search-field"><input type="text" value="#{default}" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>') @multi_temp = new Template('<ul class="chzn-choices"><li class="search-field"><input type="text" value="#{default}" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>')
@choice_temp = new Template('<li class="search-choice" id="#{id}"><span>#{choice}</span><a href="javascript:void(0)" class="search-choice-close" rel="#{position}"></a></li>') @choice_temp = new Template('<li class="search-choice" id="#{id}"><span>#{choice}</span><a href="javascript:void(0)" class="search-choice-close" rel="#{position}"></a></li>')
@no_results_temp = new Template('<li class="no-results">' + @results_none_found + ' "<span>#{terms}</span>"</li>') @no_results_temp = new Template('<li class="no-results">' + @results_none_found + ' "<span>#{terms}</span>"</li>')
@select_all_temp = new Template('<a href="javascript:void(0)" class="chzn-select-all">#{copy}</a>')
set_up_html: -> set_up_html: ->
@container_id = @form_field.identify().replace(/(:|\.)/g, '_') + "_chzn" @container_id = @form_field.identify().replace(/(:|\.)/g, '_') + "_chzn"
@ -34,11 +35,13 @@ class Chosen extends AbstractChosen
@default_text = if @form_field.readAttribute 'data-placeholder' then @form_field.readAttribute 'data-placeholder' else @default_text_default @default_text = if @form_field.readAttribute 'data-placeholder' then @form_field.readAttribute 'data-placeholder' else @default_text_default
base_template = if @is_multiple then new Element('div', container_props).update( @multi_temp.evaluate({ "default": @default_text}) ) else new Element('div', container_props).update( @single_temp.evaluate({ "default":@default_text }) ) base_template = if @is_multiple then new Element('div', container_props).update( @multi_temp.evaluate({ "default": @default_text}) ) else new Element('div', container_props).update( @single_temp.evaluate({ "default":@default_text }) )
@form_field.hide().insert({ after: base_template }) @form_field.hide().insert({ after: base_template })
@container = $(@container_id) @container = $(@container_id)
@container.addClassName( "chzn-container-" + (if @is_multiple then "multi" else "single") ) @container.addClassName( "chzn-container-" + (if @is_multiple then "multi" else "single") )
@dropdown = @container.down('div.chzn-drop') @dropdown = @container.down('div.chzn-drop')
this.select_all_setup() if @enable_select_all
dd_top = @container.getHeight() dd_top = @container.getHeight()
dd_width = (@f_width - get_side_border_padding(@dropdown)) dd_width = (@f_width - get_side_border_padding(@dropdown))
@ -233,6 +236,7 @@ class Chosen extends AbstractChosen
@search_field.value = @search_field.value @search_field.value = @search_field.value
this.winnow_results() this.winnow_results()
this.select_all_toggle() if @enable_select_all
results_hide: -> results_hide: ->
@selected_item.removeClassName('chzn-single-with-drop') unless @is_multiple @selected_item.removeClassName('chzn-single-with-drop') unless @is_multiple
@ -240,6 +244,30 @@ class Chosen extends AbstractChosen
@dropdown.setStyle({"left":"-9000px"}) @dropdown.setStyle({"left":"-9000px"})
@results_showing = false @results_showing = false
select_all_setup: ->
@dropdown.insert(@select_all_temp.evaluate({ "copy": "Select all options" }))
@select_all_link = @dropdown.down(".chzn-select-all")
@select_all_link.observe("click", (evt) => this.select_all_options(evt))
select_all_options: (evt) ->
evt.stop()
@form_field.select("option").each (option) ->
option.selected = true if not option.disabled
@form_field.fire("liszt:updated")
this.select_all_disable()
select_all_disable: ->
@select_all_link.hide()
select_all_enable: ->
@select_all_link.show()
select_all_toggle: ->
actives = @search_results.select("li.active-result")
if not actives.length or @search_field.value.length
this.select_all_disable()
else
this.select_all_enable()
set_tab_index: (el) -> set_tab_index: (el) ->
if @form_field.tabIndex if @form_field.tabIndex

View file

@ -8,9 +8,6 @@ class AbstractChosen
constructor: (@form_field, @options={}) -> constructor: (@form_field, @options={}) ->
this.set_default_values() this.set_default_values()
@is_multiple = @form_field.multiple
@default_text_default = if @is_multiple then "Select Some Options" else "Select an Option"
this.setup() this.setup()
@ -20,6 +17,9 @@ class AbstractChosen
this.finish_setup() this.finish_setup()
set_default_values: -> set_default_values: ->
@is_multiple = @form_field.multiple
@default_text_default = if @is_multiple then "Select Some Options" else "Select an Option"
@click_test_action = (evt) => this.test_active_click(evt) @click_test_action = (evt) => this.test_active_click(evt)
@activate_action = (evt) => this.activate_field(evt) @activate_action = (evt) => this.activate_field(evt)
@active_field = false @active_field = false
@ -29,6 +29,8 @@ class AbstractChosen
@result_single_selected = null @result_single_selected = null
@allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]? and @form_field.options[0].text is "" then @options.allow_single_deselect else false @allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]? and @form_field.options[0].text is "" then @options.allow_single_deselect else false
@disable_search_threshold = @options.disable_search_threshold || 0 @disable_search_threshold = @options.disable_search_threshold || 0
@enable_select_all = if @options.enable_select_all? and @is_multiple then @options.enable_select_all else false
console.log @enable_select_all
@choices = 0 @choices = 0
@results_none_found = @options.no_results_text or "No results match" @results_none_found = @options.no_results_text or "No results match"
@ -95,6 +97,8 @@ class AbstractChosen
when 9, 38, 40, 16, 91, 17 when 9, 38, 40, 16, 91, 17
# don't do anything on these keys # don't do anything on these keys
else this.results_search() else this.results_search()
this.select_all_toggle() if @enable_select_all
generate_field_id: -> generate_field_id: ->
new_id = this.generate_random_id() new_id = this.generate_random_id()