json-rules-filter 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/readme.md +34 -15
- package/src/jquery.jsonRulesFilter.js +58 -22
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -58,7 +58,7 @@ Instalar via **cdn**:
|
|
|
58
58
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
|
59
59
|
|
|
60
60
|
<!-- jsonRulesFilter -->
|
|
61
|
-
<script src="https://unpkg.com/json-rules-filter@1.0.
|
|
61
|
+
<script src="https://unpkg.com/json-rules-filter@1.0.9/src/jquery.jsonRulesFilter.js" class="script_" type="text/javascript"></script>
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
---
|
|
@@ -96,10 +96,20 @@ $("#miFiltro").jsonRulesFilter(data,
|
|
|
96
96
|
|
|
97
97
|
## 🧠 Configuración
|
|
98
98
|
|
|
99
|
+
### bsVersion
|
|
100
|
+
|
|
101
|
+
Define la compatibilidad del plugin con la version de bootstrap , actualmente solo acepta dos valores , **4** para **bootstrap4** y **5** para **bootstrap5**
|
|
102
|
+
```javascript
|
|
103
|
+
bsVersion:5 //Bootstrap 5
|
|
104
|
+
```
|
|
105
|
+
---
|
|
106
|
+
|
|
99
107
|
### filters
|
|
100
108
|
|
|
101
109
|
Define las columnas disponibles para filtrar.
|
|
102
|
-
|
|
110
|
+
- name: (título del filtro)
|
|
111
|
+
- type: tipo de filtrado. Las opciones disponibles son **number**,**string** y **select**
|
|
112
|
+
- data: clave de referencia en el dataset de JSON, se usa tanto para filtrar como para generar las opciones únicas de los tipo **select**
|
|
103
113
|
```javascript
|
|
104
114
|
filters: [
|
|
105
115
|
{
|
|
@@ -121,15 +131,23 @@ Personaliza los operadores de filtrado.
|
|
|
121
131
|
|
|
122
132
|
```javascript
|
|
123
133
|
language: {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
string: {
|
|
135
|
+
sContain: "Contiene",
|
|
136
|
+
sNotContain: "No contiene",
|
|
137
|
+
sEquals: "Igual a",
|
|
138
|
+
sDifference: "Diferente de",
|
|
139
|
+
sStartWith: "Empieza con",
|
|
140
|
+
sEndWith: "Termina con"
|
|
141
|
+
},
|
|
142
|
+
number: {
|
|
143
|
+
nEquals: "Igual a",
|
|
144
|
+
nDifference: "Diferente de",
|
|
145
|
+
nGreatherThan: "Mayor que",
|
|
146
|
+
nGreatherThanOrEquals: "Mayor o igual que",
|
|
147
|
+
nLowerThan: "Menor que",
|
|
148
|
+
nLowerThanOrEquals: "Menor o igual que"
|
|
149
|
+
}
|
|
131
150
|
}
|
|
132
|
-
}
|
|
133
151
|
```
|
|
134
152
|
|
|
135
153
|
---
|
|
@@ -162,7 +180,7 @@ buttons: {
|
|
|
162
180
|
Título del componente.
|
|
163
181
|
|
|
164
182
|
```javascript
|
|
165
|
-
title: "Reglas de filtrado"
|
|
183
|
+
title: {text:"Reglas de filtrado",className:"fs-4"}
|
|
166
184
|
```
|
|
167
185
|
|
|
168
186
|
---
|
|
@@ -212,7 +230,7 @@ onApply: function (rules, filteredData) {
|
|
|
212
230
|
## 🛠️ Métodos públicos
|
|
213
231
|
|
|
214
232
|
### updateData
|
|
215
|
-
|
|
233
|
+
El datasets de JSON se mantiene en memoria tras la inicialización , si tu datasets cambió , debes pasarle en todo momento los datos actualizados.
|
|
216
234
|
```javascript
|
|
217
235
|
$("#miFiltro").jsonRulesFilter("updateData", nuevosDatos);
|
|
218
236
|
```
|
|
@@ -229,6 +247,7 @@ const empleados = [
|
|
|
229
247
|
];
|
|
230
248
|
|
|
231
249
|
$("#container-rules").jsonRulesFilter(empleados, {
|
|
250
|
+
bsVersion:5,
|
|
232
251
|
filters: [
|
|
233
252
|
{ name: "Nombre", type: "text", data: "name" },
|
|
234
253
|
{ name: "Total", type: "number", data: "total" },
|
|
@@ -238,10 +257,10 @@ $("#container-rules").jsonRulesFilter(empleados, {
|
|
|
238
257
|
],
|
|
239
258
|
onApply: function (rules, results) {
|
|
240
259
|
$("#container-rules-collapse").empty();
|
|
241
|
-
|
|
260
|
+
//aquí podemos actualizar la tabla de datos con los datos ya filtrados
|
|
242
261
|
//generamos indicador budge para contenedor de filtros
|
|
243
262
|
$.each(reglas, function (index, element) {
|
|
244
|
-
|
|
263
|
+
|
|
245
264
|
let text = `${element.dataName} ${element.optionFilterText.join("").toLowerCase()} ${element.searchValue}`;
|
|
246
265
|
|
|
247
266
|
if (element.typeFilter === 'select') {
|
|
@@ -282,7 +301,7 @@ $("#container-rules").jsonRulesFilter(empleados, {
|
|
|
282
301
|
---
|
|
283
302
|
|
|
284
303
|
## 📌 Notas
|
|
285
|
-
|
|
304
|
+
- Compatibilidad con bootstrap 4 y 5
|
|
286
305
|
- Soporta propiedades anidadas (ej: user.name)
|
|
287
306
|
- Usa lógica AND entre reglas
|
|
288
307
|
- Basado en Select2
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
// --- DEFAULT CONFIGURATION ---
|
|
22
22
|
const settings = $.extend(true, {
|
|
23
|
+
bsVersion:5,
|
|
23
24
|
filters: [
|
|
24
25
|
{ name: "Example", type: "number", data: "example", render: function(data){return data.text /*Callback to render html in options type select*/}}
|
|
25
26
|
],
|
|
@@ -33,10 +34,10 @@
|
|
|
33
34
|
nGreatherThanOrEquals: "Mayor o igual que", nLowerThan: "Menor que", nLowerThanOrEquals: "Menor o igual que"
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
|
-
title: "Reglas de filtrado",
|
|
37
|
+
title: {text:"Reglas de filtrado",className:"fs-6 fw-semibold"},
|
|
37
38
|
buttons: {
|
|
38
39
|
reset: { text: "Resetear", className: "fw-semibold link-danger link-offset-2 link-underline link-underline-opacity-0" },
|
|
39
|
-
dropdown: { text: "Añadir regla", className: "btn btn-secondary"
|
|
40
|
+
dropdown: { text: "Añadir regla", className: "btn btn-secondary"},
|
|
40
41
|
apply: { text: "Aplicar regla", className: "btn btn-primary" },
|
|
41
42
|
},
|
|
42
43
|
onApply: function (filtros, datosFiltrados) { }
|
|
@@ -51,6 +52,32 @@
|
|
|
51
52
|
settings: settings,
|
|
52
53
|
$contenedor: $contenedor,
|
|
53
54
|
|
|
55
|
+
// ---- Compatibility helper bs5/bs4 ------
|
|
56
|
+
bs: function(classes) {
|
|
57
|
+
if (this.settings.bootstrapVersion === 5) return classes;
|
|
58
|
+
|
|
59
|
+
const map = {
|
|
60
|
+
'fs-6':'',
|
|
61
|
+
'fw-semibold': 'font-weight-bold',
|
|
62
|
+
'fw-bold': 'font-weight-bold',
|
|
63
|
+
'link-danger': 'text-danger',
|
|
64
|
+
'ms-': 'ml-', // Margin start -> Margin left
|
|
65
|
+
'me-': 'mr-', // Margin end -> Margin right
|
|
66
|
+
'ps-': 'pl-', // Padding start -> Padding left
|
|
67
|
+
'pe-': 'pr-', // Padding end -> Padding right
|
|
68
|
+
'g-': 'row-grid-',
|
|
69
|
+
'link-offset-2': '',
|
|
70
|
+
'link-underline': '',
|
|
71
|
+
'link-underline-opacity-0': ''
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
let result = classes;
|
|
75
|
+
Object.keys(map).forEach(key => {
|
|
76
|
+
result = result.replace(new RegExp(key, 'g'), map[key]);
|
|
77
|
+
});
|
|
78
|
+
return result;
|
|
79
|
+
},
|
|
80
|
+
|
|
54
81
|
// Updates dataset from external source and refreshes the UI
|
|
55
82
|
updateData: function (newData) {
|
|
56
83
|
this.data = newData;
|
|
@@ -88,28 +115,36 @@
|
|
|
88
115
|
|
|
89
116
|
// Render main plugin skeleton
|
|
90
117
|
render: function () {
|
|
91
|
-
|
|
118
|
+
const self = this;
|
|
119
|
+
// Atributo de toggle dinámico
|
|
120
|
+
const toggleAttr = this.settings.bootstrapVersion === 4 ? 'data-toggle="dropdown"' : 'data-bs-toggle="dropdown"';
|
|
121
|
+
|
|
122
|
+
// Ajuste de Gutters para BS4 (usamos form-row en lugar de row g-2 si es BS4)
|
|
123
|
+
const rowClass = this.settings.bootstrapVersion === 4 ? 'form-row' : 'row g-2';
|
|
124
|
+
const colClass = this.settings.bootstrapVersion === 4 ? 'col-6' : 'col-6';
|
|
125
|
+
|
|
126
|
+
let columnasHtml = `<div class="${rowClass}">`;
|
|
92
127
|
this.settings.filters.forEach((col, index) => {
|
|
93
128
|
let icon = col.type === "number" ? "fa-solid fa-hashtag" : (col.type === "string" ? "fa-solid fa-language" : "fa-solid fa-circle-chevron-down");
|
|
94
129
|
columnasHtml += `
|
|
95
|
-
<li class="
|
|
130
|
+
<li class="${colClass} list-unstyled">
|
|
96
131
|
<a class="dropdown-item dropdown-rules-item" href="#" data-column-type="${col.type}" data-column-data="${col.data}" data-column-name="${col.name}">
|
|
97
132
|
<i class="${icon}"></i> ${col.name}
|
|
98
133
|
</a>
|
|
99
134
|
</li>`;
|
|
100
|
-
if (index % 2 !== 0 && index !== 0) columnasHtml +=
|
|
135
|
+
if (index % 2 !== 0 && index !== 0) columnasHtml += `</div><div class="${rowClass}">`;
|
|
101
136
|
});
|
|
102
137
|
columnasHtml += "</div>";
|
|
103
138
|
|
|
104
139
|
let template = `
|
|
105
140
|
<div class="d-flex justify-content-between">
|
|
106
|
-
<
|
|
107
|
-
<p><a class="${this.settings.buttons.reset.className} remove-rules-containers" href="#">${this.settings.buttons.reset.text}</a></p>
|
|
141
|
+
<p class="${this.bs(this.settings.title.className)}">${this.settings.title.text}</p>
|
|
142
|
+
<p><a class="${this.bs(this.settings.buttons.reset.className)} remove-rules-containers" href="#">${this.settings.buttons.reset.text}</a></p>
|
|
108
143
|
</div>
|
|
109
144
|
<div class="py-2" id="container-rules-filters"></div>
|
|
110
145
|
<div class="mt-2">
|
|
111
146
|
<div class="d-flex justify-content-start dropdown">
|
|
112
|
-
<button
|
|
147
|
+
<button class="${this.bs(this.settings.buttons.dropdown.className)} dropdown-toggle" type="button" ${toggleAttr}>
|
|
113
148
|
${this.settings.buttons.dropdown.text}
|
|
114
149
|
</button>
|
|
115
150
|
<div class="dropdown-menu p-2 dropdown-rules-columns" style="min-width: 300px;">
|
|
@@ -117,7 +152,7 @@
|
|
|
117
152
|
</div>
|
|
118
153
|
</div>
|
|
119
154
|
<div class="mt-2 d-flex justify-content-start">
|
|
120
|
-
<button type="button" id="apply-rules-btn" class="${this.settings.buttons.apply.className}">${this.settings.buttons.apply.text}</button>
|
|
155
|
+
<button type="button" id="apply-rules-btn" class="${this.bs(this.settings.buttons.apply.className)}">${this.settings.buttons.apply.text}</button>
|
|
121
156
|
</div>
|
|
122
157
|
</div>`;
|
|
123
158
|
this.$contenedor.append(template);
|
|
@@ -156,40 +191,41 @@
|
|
|
156
191
|
addRuleRow: function (type, dataField, name) {
|
|
157
192
|
const self = this;
|
|
158
193
|
const $container = this.$contenedor.find("#container-rules-filters");
|
|
159
|
-
let id_select = 0;
|
|
160
194
|
|
|
161
|
-
|
|
195
|
+
// Generate unique ID for the new row based on the last element
|
|
196
|
+
let id_select = 0;
|
|
162
197
|
const last_container = $contenedor.find("select[name=select-rule-option]").last();
|
|
163
|
-
if (last_container.length > 0) {
|
|
164
|
-
|
|
165
|
-
|
|
198
|
+
if (last_container.length > 0) { id_select = last_container.data("id") + 1; }
|
|
199
|
+
|
|
200
|
+
// Usar 'form-group' y 'font-weight-bold' si es BS4
|
|
201
|
+
const labelClass = this.settings.bootstrapVersion === 4 ? 'font-weight-bold' : 'form-label fw-bold';
|
|
202
|
+
const rowClass = this.settings.bootstrapVersion === 4 ? 'form-row' : 'row';
|
|
166
203
|
|
|
167
204
|
// Define search input template (hidden for 'select' type)
|
|
168
205
|
const searchInput = `
|
|
169
206
|
<div class="col-7">
|
|
170
|
-
<label class="
|
|
207
|
+
<label class="${labelClass}"><span class="text-danger">*</span>${type}</label>
|
|
171
208
|
<input type="text" class="form-control" name="input-rule-search" id="input-rule-search-${id_select}">
|
|
172
209
|
</div>`;
|
|
173
210
|
|
|
174
211
|
const row = `
|
|
175
212
|
<div id="select-rule-container-${id_select}" class="d-flex justify-content-between mt-2 pt-2 mb-4 ${$contenedor.find("[name=select-rule-option]").length > 0 ? ' border-top my-3' : ""}">
|
|
176
|
-
<div class="
|
|
213
|
+
<div class="${rowClass} flex-grow-1">
|
|
177
214
|
<div class="col-4">
|
|
178
|
-
<label class="
|
|
179
|
-
<select class="form-select" ${type === 'select' ? 'multiple' : ''} data-type="${type}" data-name="${name}" data-field="${dataField}" id="select-rule-option-${id_select}" data-id="${id_select}" name="select-rule-option"></select>
|
|
215
|
+
<label class="${labelClass}">${name}</label>
|
|
216
|
+
<select class="form-select form-control" ${type === 'select' ? 'multiple' : ''} data-type="${type}" data-name="${name}" data-field="${dataField}" id="select-rule-option-${id_select}" data-id="${id_select}" name="select-rule-option"></select>
|
|
180
217
|
</div>
|
|
181
218
|
${type === 'select' ? '' : searchInput}
|
|
182
219
|
</div>
|
|
183
|
-
<div class="">
|
|
184
|
-
<a href="#" class="link-danger btn-remove-rule" data-target="select-rule-container-${id_select}">
|
|
220
|
+
<div class="ml-2">
|
|
221
|
+
<a href="#" class="link-danger text-danger btn-remove-rule" data-target="select-rule-container-${id_select}">
|
|
185
222
|
<i class="fa-solid fa-trash-can"></i>
|
|
186
223
|
</a>
|
|
187
224
|
</div>
|
|
188
225
|
</div>`;
|
|
189
226
|
|
|
190
227
|
$container.append(row);
|
|
191
|
-
|
|
192
|
-
// Fetch custom render function from settings
|
|
228
|
+
// Fetch custom render function from settings
|
|
193
229
|
const render = self.settings.filters.find((e) => e.data === dataField).render;
|
|
194
230
|
this.initSelect2(id_select, type, dataField, render);
|
|
195
231
|
},
|