pull/6827/head
jwollert 13 years ago
commit 7c623958b1
  1. 103
      assets/javascripts/reporting/filters.js
  2. 74
      assets/javascripts/reporting/restore_query.js
  3. 3
      lib/report/controller.rb
  4. 2
      lib/widget/filters/multi_choice.rb
  5. 6
      lib/widget/filters/multi_values.rb

@ -5,6 +5,12 @@ Reporting.Filters = {
load_available_values_for_filter: function (filter_name, callback_func) {
var select, radio_options, post_select_values;
select = $$('.filter-value[data-filter-name="' + filter_name + '"]').first();
// check if we might have a radio-box
radio_options = $$('.' + filter_name + '_radio_option input');
if (radio_options && radio_options.size() !== 0) {
radio_options.first().checked = true;
callback_func();
}
if (select === null || select === undefined) {
return;
}
@ -30,7 +36,6 @@ Reporting.Filters = {
},
onComplete: function (a, b) {
$$("select[data-filter-name='" + filter_name + "']").each(function (e) { e.enable(); });
callback_func();
if (select.tagName.toLowerCase() === "select") {
if (post_select_values === undefined || post_select_values === null || post_select_values.size() === 0) {
select.selectedIndex = 0;
@ -38,20 +43,13 @@ Reporting.Filters = {
Reporting.Filters.select_values(select, post_select_values);
}
}
callback_func();
}
});
Reporting.Filters.multi_select(select, false);
} else {
callback_func();
}
// select first option by default
if (select.tagName.toLowerCase() === "div") {
// check if we might have a radio-box
radio_options = $$('.' + filter_name + '_radio_option input');
if (radio_options && radio_options.size() !== 0) {
radio_options.first().checked = true;
}
}
},
show_filter: function (field, options) {
@ -67,6 +65,9 @@ Reporting.Filters = {
if (options.show_filter === undefined) {
options.show_filter = true;
}
if (options.hide_only === undefined) {
options.hide_only = false;
}
var field_el = $('tr_' + field);
if (field_el !== null) {
if (options.insert_after === undefined) {
@ -74,9 +75,11 @@ Reporting.Filters = {
}
if (options.insert_after !== undefined && options.show_filter) {
// Move the filter down to appear after the last currently visible filter
if (field_el.id !== options.insert_after.id) {
field_el.remove();
options.insert_after.insert({after: field_el});
}
}
// the following command might be included into the callback_function (which is called after the ajax request) later
var display_functor;
if (options.show_filter) {
@ -87,7 +90,9 @@ Reporting.Filters = {
Reporting.Filters.set_filter_value_widths(100);
} else {
(options.slowly ? Effect.Fade : Element.hide)(field_el);
if (!options.hide_only) { // remember that this filter used to be selected
field_el.removeAttribute('data-selected');
}
$('rm_' + field).value = ""; // reset the value, so the serialized form will not return this filter
Reporting.Filters.set_filter_value_widths(5000);
}
@ -96,6 +101,40 @@ Reporting.Filters = {
}
},
/**
* Activates the filter with the given name and loads dependent filters if necessary.
*
* @param filter_name Name of the filter to be activated.
*/
add_filter: function (filter_name, activate_dependent, on_complete) {
var field = filter_name
if (activate_dependent === undefined) {
activate_dependent = true;
}
if (on_complete === undefined) {
on_complete = function() { };
}
Reporting.Filters.show_filter(field, { slowly: true, callback_func: function() {
if (activate_dependent) {
Reporting.Filters.activate_dependents($(field + "_arg_1_val"));
}
Reporting.Filters.select_option_enabled($("add_filter_select"), filter_name, false);
on_complete();
}
});
},
remove_filter: function (field, hide_only) {
Reporting.Filters.show_filter(field, { show_filter: false, hide_only: hide_only });
var dependent = Reporting.Filters.get_dependents($(field + '_arg_1_val'), false).find(function(d) {
return Reporting.Filters.visible_filters().include(d);
});
if (dependent !== undefined) {
Reporting.Filters.remove_filter(dependent);
}
Reporting.Filters.select_option_enabled($("add_filter_select"), field, true);
},
/*
Smoothly sets the width of currently displayed filters.
Params:
@ -210,15 +249,6 @@ Reporting.Filters = {
}
},
add_filter: function (select) {
var field;
field = select.value;
Reporting.Filters.show_filter(field, { slowly: true });
select.selectedIndex = 0;
Reporting.Filters.select_option_enabled(select, field, false);
Reporting.Filters.activate_dependents($(field + "_arg_1_val"))
},
select_option_enabled: function (box, value, state) {
var option = box.select("[value='" + value + "']").first();
if (option !== undefined) {
@ -243,17 +273,6 @@ Reporting.Filters = {
Reporting.Filters.multi_select(select, !select.multiple);
},
remove_filter: function (field) {
Reporting.Filters.show_filter(field, { show_filter: false });
var dependent = Reporting.Filters.get_dependents($(field + '_arg_1_val'), false).find(function(d) {
return Reporting.Filters.visible_filters().include(d);
});
if (dependent !== undefined) {
Reporting.Filters.remove_filter(dependent);
}
Reporting.Filters.select_option_enabled($("add_filter_select"), field, true);
},
visible_filters: function () {
return $("filter_table").select("tr").select(function (tr) {
return tr.visible() === true;
@ -289,11 +308,14 @@ Reporting.Filters = {
// Param: select [optional] - the select-box of the filter which should activate it's dependents
activate_dependents: function (selectBox, callbackWhenFinished) {
var all_dependents, next_dependents, dependent, active_filters, source;
if (selectBox !== undefined && selectBox.tagName.toLowerCase() !== "select") {
return; // only multi_value filters have dependents
}
if (selectBox === undefined || selectBox.type.toLowerCase() == 'change') {
selectBox = this;
}
if (callbackWhenFinished === undefined) {
callbackWhenFinished = function() {};
callbackWhenFinished = function(dependent) { };
}
source = selectBox.getAttribute("data-filter-name");
all_dependents = Reporting.Filters.get_dependents(selectBox);
@ -326,14 +348,18 @@ Reporting.Filters = {
var active_dependents = all_dependents.select(function (d) {
return active_filters.include(d);
});
Reporting.Filters.narrow_values(Reporting.Filters.dependent_for(source), active_dependents, callbackWhenFinished);
Reporting.Filters.narrow_values(
Reporting.Filters.dependent_for(source),
active_dependents,
function() { callbackWhenFinished(dependent); }
);
}, 1);
},
// return an array of all filters that depend on the given filter plus the given filter
dependent_for: function(field) {
var deps = $$('.filters-select[data-all-dependents]').findAll(function(selectBox) {
return selectBox.up('tr').visible() && Reporting.Filters.get_dependents(selectBox).include(field)
return (selectBox.up('tr').visible()) && Reporting.Filters.get_dependents(selectBox).include(field)
}).map(function(selectBox) {
return selectBox.getAttribute("data-filter-name");
});
@ -400,7 +426,9 @@ Reporting.Filters = {
// cannot use .innerhtml due to IE wierdness
$(selectBox).insert(new Element('option', {value: value}).update(label.escapeHTML()));
});
Reporting.Filters.select_values(selectBox, selected);
sources.push(currentDependent); // Add as last element
dependents.splice(0, 1); // Delete first element
// if we got no values besides the <<inactive>> value, do not show this selectBox
@ -421,10 +449,13 @@ Reporting.Filters = {
if (continue_narrowing) {
Reporting.Filters.narrow_values(sources, dependents);
}
}
callbackWhenFinished();
}
},
onException: function (response, error) {
if (console) {
console.log(error);
}
Reporting.flash("Loading of filter values failed. Probably, the server is temporary offline for maintenance.");
var selectBox = $(currentDependent + "_arg_1_val");
$(selectBox).insert(new Element('option', {value: '<<inactive>>'}).update('Failed to load values.'));
@ -445,7 +476,8 @@ Reporting.onload(function () {
if ($("add_filter_select")) {
$("add_filter_select").observe("change", function () {
if (!(Reporting.Filters.exists(this.value))) {
Reporting.Filters.add_filter(this);
Reporting.Filters.add_filter(this.value);
this.selectedIndex = 0;
};
});
}
@ -481,8 +513,5 @@ Reporting.onload(function () {
$$('.filters-select[data-all-dependents]').each(function (dependency) {
dependency.observe("change", Reporting.Filters.activate_dependents);
});
Reporting.Filters.visible_filters().each(function (filter) {
Reporting.Filters.load_available_values_for_filter(filter, function () {});
});
});

@ -27,58 +27,44 @@ Reporting.RestoreQuery = {
}
},
// This is called the first time the report loads.
// Params:
// elements: Array of visible filter-select-boxes that have dependents
// (and possibly are dependents themselfes)
initialize_load_dependent_filters: function(elements) {
var filters_to_load, dependent_filters;
dependent_filters = elements.findAll(function (select) { return select.getValue() == '<<inactive>>' || select.select('option[selected]').size()==0 });
filters_to_load = elements.reject( function (select) { return select.getValue() == '<<inactive>>' });
// Filters which are <<inactive>> are probably dependents themselfes, so remove and forget them for now.
// This is OK as they get reloaded later
dependent_filters.each(function(select) {
Reporting.Filters.remove_filter(select.up('tr').readAttribute("data-filter-name"));
});
// For each dependent filter we reload its dependent chain
filters_to_load.each(function(selectBox) {
var sources, selected_values;
Reporting.Filters.activate_dependents(selectBox, function() {
sources = Reporting.Filters.get_dependents(selectBox).collect(function(field) {
return $('tr_' + field).select('.filter_values select').first();
});
sources.each(function(source) {
if (source.hasAttribute('data-initially-selected')) {
selected_values = source.readAttribute('data-initially-selected').replace(/'/g, '"').evalJSON(true);
Reporting.Filters.select_values(source, selected_values);
Reporting.Filters.value_changed(source.up('tr').readAttribute("data-filter-name"));
restore_dependent_filters: function(filter_name) {
$$("tr.filter[data-filter-name=" + filter_name + "] select.filter-value").each(function(selectBox) {
var activateNext = function(dependent) {
if (!dependent) return;
Reporting.RestoreQuery.restore_dependent_filters(dependent);
};
if (selectBox.hasAttribute('data-initially-selected')) {
var selected_values = selectBox.readAttribute('data-initially-selected').replace(/'/g, '"').evalJSON(true);
Reporting.Filters.select_values(selectBox, selected_values);
Reporting.Filters.value_changed(filter_name);
}
});
if (sources.reject( function (select) { return select.value == '<<inactive>>' }).size() == 0) {
Reporting.Filters.activate_dependents(selectBox);
if (selectBox.getValue() !== '<<inactive>>') {
Reporting.Filters.activate_dependents(selectBox, activateNext);
}
else {
Reporting.RestoreQuery.initialize_load_dependent_filters(sources);
}
});
});
},
restore_filters: function () {
// FIXME: rm_xxx values for filters have to be set after re-displaying them
var deps = $$('.filters-select.filter-value').each(function(select) {
var tr = select.up('tr');
if (tr.visible()) {
var filter = tr.readAttribute('data-filter-name');
var dependent = select.readAttribute('data-dependent');
if (filter && dependent) {
Reporting.Filters.remove_filter(filter, false);
}
}
});
$$("tr[data-selected=true]").each(function (e) {
var rm_box, filter_name;
rm_box = e.select("input[id^=rm]").first();
filter_name = e.getAttribute("data-filter-name");
rm_box.value = filter_name;
Reporting.Filters.select_option_enabled($("add_filter_select"), filter_name, false);
// correctly display number of arguments of filters depending on their arity
Reporting.Filters.operator_changed(filter_name, $("operators[" + filter_name + "]"));
var select = e.down(".filter_values select");
if (select && select.hasAttribute("data-dependent")) return;
var filter_name = e.getAttribute("data-filter-name");
var on_complete = function() {
Reporting.RestoreQuery.restore_dependent_filters(filter_name);
};
Reporting.Filters.add_filter(filter_name, false, on_complete);
});
// restore values of dependent filters
Reporting.RestoreQuery.initialize_load_dependent_filters($$('.filters-select[data-all-dependents]').findAll(function(select) {
return select.up('tr').visible()
}));
},
restore_group_bys: function () {

@ -340,15 +340,12 @@ module Report::Controller
# renders option tags for each available value for a single filter
def available_values
if name = params[:filter_name]
begin
f_cls = report_engine::Filter.const_get(name.to_s.camelcase)
filter = f_cls.new.tap do |f|
f.values = JSON.parse(params[:values].gsub("'", '"')) if params[:values].present? and params[:values]
end
render_widget Widget::Filters::Option, filter, :to => canvas = ""
render :text => canvas, :layout => !request.xhr?
rescue NameError
end
end
end

@ -12,7 +12,7 @@ class Widget::Filters::MultiChoice < Widget::Filters::Base
:id => "#{filterName}_radio_option_#{i}",
:value => value
}
opts[:checked] = "checked" if filter.values == value
opts[:checked] = "checked" if filter.values == [value].flatten
radio_button = tag :input, opts
content_tag :label, radio_button + translate(label),
:for => "#{filterName}_radio_option_#{i}",

@ -23,9 +23,11 @@ class Widget::Filters::MultiValues < Widget::Filters::Base
# store selected value(s) in data-initially-selected if this filter is a dependent
# of another filter, as we have to restore values manually in the client js
if (filter_class.is_dependent? || @options[:lazy]) && !Array(filter.values).empty?
select_options.merge! :"data-initially-selected" => filter.values.to_json.gsub!('"', "'")
select_options.merge! :"data-initially-selected" =>
filter.values.to_json.gsub!('"', "'") || "[" + filter.values.map { |v| "'#{v}'" }.join(',') + "]"
end
box_content = ""
select_options.merge! :"data-dependent" => true if filter_class.is_dependent?
box_content = "".html_safe
box = content_tag :select, select_options do
render_widget Widget::Filters::Option, filter, :to => box_content unless @options[:lazy]
end

Loading…
Cancel
Save