json-rules-filter 1.0.7 → 1.0.9

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.7",
3
+ "version": "1.0.9",
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
  ---
@@ -72,7 +72,19 @@ const data = [
72
72
  { name: "Luis", total: 150, cargo: "Admin" }
73
73
  ];
74
74
 
75
- $("#miFiltro").jsonRulesFilter(data, {
75
+ $("#miFiltro").jsonRulesFilter(data,
76
+ {
77
+ filters:[
78
+ {
79
+ name: "Total",
80
+ type: "number",
81
+ data: "total",
82
+ render: function(data) {
83
+ return data.text;
84
+ }
85
+ },
86
+
87
+ ],
76
88
  onApply: function (rules, filteredData) {
77
89
  console.log("Reglas:", rules);
78
90
  console.log("Resultados:", filteredData);
@@ -84,10 +96,20 @@ $("#miFiltro").jsonRulesFilter(data, {
84
96
 
85
97
  ## 🧠 Configuración
86
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
+
87
107
  ### filters
88
108
 
89
109
  Define las columnas disponibles para filtrar.
90
-
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**
91
113
  ```javascript
92
114
  filters: [
93
115
  {
@@ -109,15 +131,23 @@ Personaliza los operadores de filtrado.
109
131
 
110
132
  ```javascript
111
133
  language: {
112
- string: {
113
- sContain: "Contiene",
114
- sEquals: "Igual a"
115
- },
116
- number: {
117
- nEquals: "Igual a",
118
- 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
+ }
119
150
  }
120
- }
121
151
  ```
122
152
 
123
153
  ---
@@ -150,7 +180,7 @@ buttons: {
150
180
  Título del componente.
151
181
 
152
182
  ```javascript
153
- title: "Reglas de filtrado"
183
+ title: {text:"Reglas de filtrado",className:"fs-4"}
154
184
  ```
155
185
 
156
186
  ---
@@ -200,7 +230,7 @@ onApply: function (rules, filteredData) {
200
230
  ## 🛠️ Métodos públicos
201
231
 
202
232
  ### updateData
203
-
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.
204
234
  ```javascript
205
235
  $("#miFiltro").jsonRulesFilter("updateData", nuevosDatos);
206
236
  ```
@@ -217,6 +247,7 @@ const empleados = [
217
247
  ];
218
248
 
219
249
  $("#container-rules").jsonRulesFilter(empleados, {
250
+ bsVersion:5,
220
251
  filters: [
221
252
  { name: "Nombre", type: "text", data: "name" },
222
253
  { name: "Total", type: "number", data: "total" },
@@ -226,10 +257,10 @@ $("#container-rules").jsonRulesFilter(empleados, {
226
257
  ],
227
258
  onApply: function (rules, results) {
228
259
  $("#container-rules-collapse").empty();
229
-
260
+ //aquí podemos actualizar la tabla de datos con los datos ya filtrados
230
261
  //generamos indicador budge para contenedor de filtros
231
262
  $.each(reglas, function (index, element) {
232
-
263
+
233
264
  let text = `${element.dataName} ${element.optionFilterText.join("").toLowerCase()} ${element.searchValue}`;
234
265
 
235
266
  if (element.typeFilter === 'select') {
@@ -270,7 +301,7 @@ $("#container-rules").jsonRulesFilter(empleados, {
270
301
  ---
271
302
 
272
303
  ## 📌 Notas
273
-
304
+ - Compatibilidad con bootstrap 4 y 5
274
305
  - Soporta propiedades anidadas (ej: user.name)
275
306
  - Usa lógica AND entre reglas
276
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-4"},
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,31 @@
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
+ 'fw-semibold': 'font-weight-bold',
61
+ 'fw-bold': 'font-weight-bold',
62
+ 'link-danger': 'text-danger',
63
+ 'ms-': 'ml-', // Margin start -> Margin left
64
+ 'me-': 'mr-', // Margin end -> Margin right
65
+ 'ps-': 'pl-', // Padding start -> Padding left
66
+ 'pe-': 'pr-', // Padding end -> Padding right
67
+ 'g-': 'row-grid-',
68
+ 'link-offset-2': '',
69
+ 'link-underline': '',
70
+ 'link-underline-opacity-0': ''
71
+ };
72
+
73
+ let result = classes;
74
+ Object.keys(map).forEach(key => {
75
+ result = result.replace(new RegExp(key, 'g'), map[key]);
76
+ });
77
+ return result;
78
+ },
79
+
54
80
  // Updates dataset from external source and refreshes the UI
55
81
  updateData: function (newData) {
56
82
  this.data = newData;
@@ -88,28 +114,36 @@
88
114
 
89
115
  // Render main plugin skeleton
90
116
  render: function () {
91
- let columnasHtml = '<div class="row g-2">';
117
+ const self = this;
118
+ // Atributo de toggle dinámico
119
+ const toggleAttr = this.settings.bootstrapVersion === 4 ? 'data-toggle="dropdown"' : 'data-bs-toggle="dropdown"';
120
+
121
+ // Ajuste de Gutters para BS4 (usamos form-row en lugar de row g-2 si es BS4)
122
+ const rowClass = this.settings.bootstrapVersion === 4 ? 'form-row' : 'row g-2';
123
+ const colClass = this.settings.bootstrapVersion === 4 ? 'col-6' : 'col-6';
124
+
125
+ let columnasHtml = `<div class="${rowClass}">`;
92
126
  this.settings.filters.forEach((col, index) => {
93
127
  let icon = col.type === "number" ? "fa-solid fa-hashtag" : (col.type === "string" ? "fa-solid fa-language" : "fa-solid fa-circle-chevron-down");
94
128
  columnasHtml += `
95
- <li class="col-6 list-unstyled">
129
+ <li class="${colClass} list-unstyled">
96
130
  <a class="dropdown-item dropdown-rules-item" href="#" data-column-type="${col.type}" data-column-data="${col.data}" data-column-name="${col.name}">
97
131
  <i class="${icon}"></i> ${col.name}
98
132
  </a>
99
133
  </li>`;
100
- if (index % 2 !== 0 && index !== 0) columnasHtml += '</div><div class="row g-2">';
134
+ if (index % 2 !== 0 && index !== 0) columnasHtml += `</div><div class="${rowClass}">`;
101
135
  });
102
136
  columnasHtml += "</div>";
103
137
 
104
138
  let template = `
105
139
  <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>
140
+ <p class="${this.bs(this.settings.title.className)}">${this.settings.title.text}</p>
141
+ <p><a class="${this.bs(this.settings.buttons.reset.className)} remove-rules-containers" href="#">${this.settings.buttons.reset.text}</a></p>
108
142
  </div>
109
143
  <div class="py-2" id="container-rules-filters"></div>
110
144
  <div class="mt-2">
111
145
  <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">
146
+ <button class="${this.bs(this.settings.buttons.dropdown.className)} dropdown-toggle" type="button" ${toggleAttr}>
113
147
  ${this.settings.buttons.dropdown.text}
114
148
  </button>
115
149
  <div class="dropdown-menu p-2 dropdown-rules-columns" style="min-width: 300px;">
@@ -117,7 +151,7 @@
117
151
  </div>
118
152
  </div>
119
153
  <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>
154
+ <button type="button" id="apply-rules-btn" class="${this.bs(this.settings.buttons.apply.className)}">${this.settings.buttons.apply.text}</button>
121
155
  </div>
122
156
  </div>`;
123
157
  this.$contenedor.append(template);
@@ -156,40 +190,41 @@
156
190
  addRuleRow: function (type, dataField, name) {
157
191
  const self = this;
158
192
  const $container = this.$contenedor.find("#container-rules-filters");
159
- let id_select = 0;
160
193
 
161
- // Generate unique ID for the new row based on the last element
194
+ // Generate unique ID for the new row based on the last element
195
+ let id_select = 0;
162
196
  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
- }
197
+ if (last_container.length > 0) { id_select = last_container.data("id") + 1; }
198
+
199
+ // Usar 'form-group' y 'font-weight-bold' si es BS4
200
+ const labelClass = this.settings.bootstrapVersion === 4 ? 'font-weight-bold' : 'form-label fw-bold';
201
+ const rowClass = this.settings.bootstrapVersion === 4 ? 'form-row' : 'row';
166
202
 
167
203
  // Define search input template (hidden for 'select' type)
168
204
  const searchInput = `
169
205
  <div class="col-7">
170
- <label class="form-label font-bold"><span class="text-danger">*</span>${type}</label>
206
+ <label class="${labelClass}"><span class="text-danger">*</span>${type}</label>
171
207
  <input type="text" class="form-control" name="input-rule-search" id="input-rule-search-${id_select}">
172
208
  </div>`;
173
209
 
174
210
  const row = `
175
211
  <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">
212
+ <div class="${rowClass} flex-grow-1">
177
213
  <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>
214
+ <label class="${labelClass}">${name}</label>
215
+ <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
216
  </div>
181
217
  ${type === 'select' ? '' : searchInput}
182
218
  </div>
183
- <div class="">
184
- <a href="#" class="link-danger btn-remove-rule" data-target="select-rule-container-${id_select}">
219
+ <div class="ml-2">
220
+ <a href="#" class="link-danger text-danger btn-remove-rule" data-target="select-rule-container-${id_select}">
185
221
  <i class="fa-solid fa-trash-can"></i>
186
222
  </a>
187
223
  </div>
188
224
  </div>`;
189
225
 
190
226
  $container.append(row);
191
-
192
- // Fetch custom render function from settings
227
+ // Fetch custom render function from settings
193
228
  const render = self.settings.filters.find((e) => e.data === dataField).render;
194
229
  this.initSelect2(id_select, type, dataField, render);
195
230
  },