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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-rules-filter",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "para crear reglas avanzadas de filtrado sobre datasets JSON de forma dinámica y visual.",
5
5
  "main": "src/jquery.jsonRulesFilter.js",
6
6
  "scripts": {
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.5/src/jquery.jsonRulesFilter.js" class="script_" type="text/javascript"></script>
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
- string: {
125
- sContain: "Contiene",
126
- sEquals: "Igual a"
127
- },
128
- number: {
129
- nEquals: "Igual a",
130
- nGreatherThan: "Mayor que"
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
- let columnasHtml = '<div class="row g-2">';
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="col-6 list-unstyled">
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 += '</div><div class="row g-2">';
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
- <b><h4>${this.settings.title}</h4></b>
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 data-bs-popper-config='{"strategy":"fixed"}' class="${this.settings.buttons.dropdown.className} dropdown-toggle" type="button" data-bs-toggle="dropdown">
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
- // Generate unique ID for the new row based on the last element
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
- id_select = last_container.data("id") + 1;
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="form-label font-bold"><span class="text-danger">*</span>${type}</label>
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="row flex-grow-1">
213
+ <div class="${rowClass} flex-grow-1">
177
214
  <div class="col-4">
178
- <label class="form-label font-bold">${name}</label>
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
  },