jqGrid の外部で、ボタンやスライダーなどの jquery.ui コンポーネントを使用して (Web ショップで) フィルタリングを実装しました。リスト (グリッド) で使用できるフィルターは、現在アクティブなカテゴリによって異なります。ルールを作成し、ボタンとスライダーが押された/使用されたときにフィルター プロパティに追加し、必要に応じて削除します。
ほとんどの場合、これは魔法のように機能しますが、100 未満から 100 を超える値を含むカテゴリの特定のフィルターを作成するときに、スライダーを使用してフィルター処理すると、結果に奇妙なことが起こります。スライダーの下部を引っ張り始めるとすぐに、下側の値が最小値 (つまり < 100) よりも大きく、100 よりも小さい場合、結果セット全体が消えます。この場合、最小値は 97,6 であり、スライダーの値が 98 と 99 の場合、結果は空になります。しかし、スライダーの値が 100 以上になると、結果は正しくなります。また、値が 100 未満の記事を > 100 に変更すると、すべてが意図したとおりに機能します。
スライダーの下端を引っ張るとフィルターに「ge」ルールを追加し、上端を引っ張ると「le」ルールを追加します。
私たちはjqgrid 4.3.1を使用していますが、今日はバージョン4.4.4でも試しましたが、同じ結果です。
jqGrid がグリッド内の値を解釈する方法に関係がある場合は、スウェーデン語ロケールも使用しています。
更新 (コード) :
まず、グリッドに表示されるアイテムのコレクションから最小値と最大値を取得します。
else if (dynamicFilters[l].Type == "slider") {
//Get the smallest and the biggest value that we should be able to filter on
//Parse the value so that there are no non-numberic characters, and also replace ',' with '.' so that it can be converted to a numeric value
var currentValue = property.Value.replace(/[^0-9.,]/g, '').replace(/[,]/g, '.');
var index = property.Value.indexOf(".");
if (index >= 0) {
currentValue = property.Value.substring(0, index);
}
currentValue = Number(currentValue);
//Specific case where no value has been set
if (dynamicFilters[l].Values[0] == 0 && dynamicFilters[l].Values[1] == 0) {
dynamicFilters[l].Values[0] = currentValue;
dynamicFilters[l].Values[1] = currentValue;
} else {
//Else check if the value is either smaller or larger than those in the array
if (dynamicFilters[l].Values[0] > currentValue) {
dynamicFilters[l].Values[0] = currentValue;
}
if (dynamicFilters[l].Values[1] < currentValue) {
dynamicFilters[l].Values[1] = currentValue;
}
}
}
これはうまくいくようです。Chrome devtools でこれをデバッグしましたが、値は正しいです。
次に、GUI で実際のスライダーを作成します。
else if (filter.Type == "slider") {
//Create the slider filters
//Start the container for the slider filter, the second div is then used to create the slider with the jQuery UI control
$("#dynamicFilters").append('<div class="dynamic-filter"><strong>' + filter.DisplayName + '</strong> <input type="text" id="' + filterId + '_amount" class="dynamic-filter-amount"></input><div id="' + filterId + '" class="dynamic-slider-filter" filter-property="' + filter.ParameterName + '" filter-type="' + filter.Type + '" filter-unit="' + filter.Unit + '" filter-value="' + filter.Values[0] + ';' + filter.Values[1] + '"></div></div>');
var filters = currentProfile.Filters;
var minValue = -1;
var maxValue = -1;
//Check if there are any values saved for this very filter, if so set the values of the slider
if (filters != null && !currentProfile.FilterListUrlChanged) {
for (var j = 0; j < filters.length; j++) {
if (filters[j].Field == filter.ParameterName && filters[j].OperatorType == "ge") {
minValue = filters[j].Data;
}
if (filters[j].Field == filter.ParameterName && filters[j].OperatorType == "le") {
maxValue = filters[j].Data;
}
}
} else {
minValue = filter.Values[0];
maxValue = filter.Values[1];
}
if (minValue == -1) {
minValue = filter.Values[0];
}
if (maxValue == -1) {
maxValue = filter.Values[1];
}
//Create the actual slider
if (filter.Values[0] != filter.Values[1]) {
$("#" + filterId).slider({
range: true,
min: parseInt(filter.Values[0]),
max: parseInt(filter.Values[1]),
values: [parseInt(minValue), parseInt(maxValue)],
slide: function (event, ui) {
var filterProperty = $(this).attr("filter-property");
var filterType = $(this).attr("filter-type");
var filterUnit = $(this).attr("filter-unit");
$("#" + filterProperty + "_amount").val("(" + ui.values[0] + " " + filterUnit + " - " + ui.values[1] + " " + filterUnit + ")");
articleListFilter._applyFilter(that, filterProperty, filterType, [ui.values[0], ui.values[1]]);
},
stop: function (event, ui) {
//Add the slider filter to the current profile, but only if they have actually moved from their initial position
if (ui.values[0] != $(this).slider("option", "min")) {
articleListFilter._addProfileFilter(document.URL, $(this).attr("filter-property"), "ge", $(this).attr("filter-type"), ui.values[0]);
}
else {
articleListFilter._removeProfileFilter(document.URL, $(this).attr("filter-property"), $(this).attr("filter-type"), "ge", ui.values[0]);
}
if (ui.values[1] != $(this).slider("option", "max")) {
articleListFilter._addProfileFilter(document.URL, $(this).attr("filter-property"), "le", $(this).attr("filter-type"), ui.values[1]);
}
else {
articleListFilter._removeProfileFilter(document.URL, $(this).attr("filter-property"), $(this).attr("filter-type"), "le", ui.values[1]);
}
}
});
$("#" + filterId + "_amount").val("(" + $("#" + filterId).slider("values", 0) + " " + filter.Unit + " - " + $("#" + filterId).slider("values", 1) + " " + filter.Unit + ")");
}
}
この部分も (私が見る限り) 機能し、値は正しく設定されており、スライダーでフィルター処理しようとする他のすべてのプロパティで機能します。範囲が < 100 から > 100 の場合でも。
_applyFilter 関数は次のようになります。
_applyFilter: function (that, property, type, value) {
var myfilter = {};
//Get a new fresh filter or the current one
if (that.data("Filter") == null) {
myfilter.filter = { groupOp: "AND", rules: [] };
myfilter.HasPriceFilter = false;
myfilter.HasBrandFilter = false;
myfilter.HasSmallFilter = false;
myfilter.HasMediumFilter = false;
myfilter.HasLargeFilter = false;
myfilter.HasAdditionFilter = false;
myfilter.HasMiscFilter = false;
} else {
myfilter = that.data("Filter");
}
myfilter = articleListFilter._filterDynamic(myfilter, property, type, value);
//Must reload here so that the paging won't get stuck on a page that has no items. Must be done before the filter is set.
$("#articles").trigger("reloadGrid");
that.data("Filter", myfilter);
articleListFilter._setFilter(that, myfilter.filter, 1);
}
_filterDynamic 関数は次のように機能します。
else if (type == "slider") {
//Need to check if there already is a filter for the same property and type, if the data should be changed or pushed into the rules array
var addMinRule = true;
var addMaxRule = true;
var minValue = $("#" + property).slider("option", "min");
var maxValue = $("#" + property).slider("option", "max");
for (var j = 0; j < myFilter.filter.rules.length; j++) {
var rule = myFilter.filter.rules[j];
if (rule.field == property && rule.op == "ge") {
rule.data = value[0];
addMinRule = false;
}
else if (rule.field == property && rule.op == "le") {
rule.data = value[1];
addMaxRule = false;
}
}
if (addMinRule) {
myFilter.filter.rules.push({ field: property, op: "ge", data: value[0] });
}
if (addMaxRule) {
myFilter.filter.rules.push({ field: property, op: "le", data: value[1] });
}
if (value[0] == minValue || value[1] == maxValue) {
for (var k = 0; k < myFilter.filter.rules.length; k++) {
var removeRule = myFilter.filter.rules[k];
if (removeRule.field == property && removeRule.op == "ge") {
if (value[0] == minValue) {
myFilter.filter.rules.splice(k, 1);
}
}
else if (removeRule.field == property && removeRule.op == "le") {
if (value[1] == maxValue) {
myFilter.filter.rules.splice(k, 1);
}
}
}
}
}
ヘルプや同様の話は大歓迎です!
敬具、ビョルン