PageSourceSearch

https://sancarlos-antioquia.gov.co/SiteAssets/SanCarlos/components/home/ServicioCiudadano/main.js

js sancarlos-antioquia.gov.co collected 2026-10-02 23:06:53 UTC 8,214 bytes, 305 lines download raw bytes

1(function() {
2    "use strict";
3
4    var CONFIG = {
5        siteUrl: _spPageContextInfo.webAbsoluteUrl,
6        listTitle: "ServicioCiudadano",
7        select: "Title,FileRef,Url,Publicado,Orden",
8        orderBy: "Orden",
9        ascending: true,
10        itemsPerPage: 100
11    };
12
13    var state = {
14        items: [],
15        visibleRows: 1,
16        columns: 5,
17        expanded: false
18    };
19
20    var grid = null;
21    var moreWrapper = null;
22    var moreButton = null;
23
24    function escapeHtml(value) {
25        return String(value == null ? "" : value).replace(/[&<>"']/g, function(char) {
26            return {
27                "&": "&amp;",
28                "<": "&lt;",
29                ">": "&gt;",
30                '"': "&quot;",
31                "'": "&#039;"
32            }[char];
33        });
34    }
35
36    function isPublished(value) {
37        if (value === true || value === 1) {
38            return true;
39        }
40
41        if (value === false || value === 0 || value === null || value === undefined) {
42            return false;
43        }
44
45        var normalized = String(value).trim().toLowerCase();
46
47        return normalized === "true" ||
48               normalized === "1" ||
49               normalized === "sí" ||
50               normalized === "si" ||
51               normalized === "yes";
52    }
53
54    function getUrl(value) {
55        if (value && typeof value === "object") {
56            return value.Url || value.url || "#";
57        }
58
59        return typeof value === "string" && value.trim()
60            ? value
61            : "#";
62    }
63
64    function createCard(item) {
65        var title = escapeHtml(item.Title || "Servicio");
66        var image = escapeHtml(item.FileRef || "");
67        var url = escapeHtml(getUrl(item.Url));
68
69        return (
70            '<a class="sc-card" href="' + url + '" target="_blank" rel="noopener noreferrer">' +
71                '<span class="sc-card-image">' +
72                    (
73                        image
74                            ? '<img src="' + image + '" alt="' + title + '" loading="lazy">'
75                            : '<span class="sc-card-image-placeholder"></span>'
76                    ) +
77                '</span>' +
78                '<span class="sc-card-content">' +
79                    '<span class="sc-card-title">' + title + '</span>' +
80                    '<span class="sc-card-action">' +
81                        'Consultar servicio' +
82                        '<i class="fa-solid fa-arrow-right"></i>' +
83                    '</span>' +
84                '</span>' +
85            '</a>'
86        );
87    }
88
89    function getColumns() {
90        if (window.innerWidth <= 600) {
91            return 1;
92        }
93
94        if (window.innerWidth <= 900) {
95            return 2;
96        }
97
98        if (window.innerWidth <= 1150) {
99            return 3;
100        }
101
102        if (window.innerWidth <= 1350) {
103            return 4;
104        }
105
106        return 5;
107    }
108
109    function getVisibleItems() {
110        var visibleCount = state.visibleRows * state.columns;
111
112        return state.items.slice(0, visibleCount);
113    }
114
115    function render() {
116        if (!grid) {
117            return;
118        }
119
120        state.columns = getColumns();
121
122        var visibleItems = getVisibleItems();
123
124        grid.innerHTML = visibleItems.map(createCard).join("");
125
126        updateButton();
127    }
128
129    function updateButton() {
130        if (!moreWrapper || !moreButton) {
131            return;
132        }
133
134        var totalItems = state.items.length;
135        var totalRows = Math.ceil(totalItems / state.columns);
136
137        if (totalRows <= 1) {
138            moreWrapper.style.display = "none";
139            return;
140        }
141
142        moreWrapper.style.display = "flex";
143
144        var text = moreButton.querySelector(".sc-more-text");
145        var icon = moreButton.querySelector(".sc-more-icon i");
146
147        if (!text || !icon) {
148            return;
149        }
150
151        if (state.expanded) {
152            text.textContent = "Ocultar";
153            icon.className = "fa-solid fa-chevron-up";
154            moreButton.classList.add("is-expanded");
155        } else {
156            text.textContent = "Ver más";
157            icon.className = "fa-solid fa-chevron-down";
158            moreButton.classList.remove("is-expanded");
159        }
160    }
161
162    function showMore() {
163        var totalRows = Math.ceil(state.items.length / state.columns);
164
165        if (state.visibleRows < totalRows) {
166            state.visibleRows++;
167        }
168
169        if (state.visibleRows >= totalRows) {
170            state.expanded = true;
171        }
172
173        render();
174    }
175
176    function hideMore() {
177        state.visibleRows = 1;
178        state.expanded = false;
179
180        render();
181
182        var section = document.getElementById("servicioCiudadano");
183
184        if (section) {
185            section.scrollIntoView({
186                behavior: "smooth",
187                block: "start"
188            });
189        }
190    }
191
192    function handleMoreClick() {
193        if (state.expanded) {
194            hideMore();
195        } else {
196            showMore();
197        }
198    }
199
200    function loadServices() {
201        var endpoint =
202            CONFIG.siteUrl +
203            "/_api/web/lists/getbytitle('" +
204            encodeURIComponent(CONFIG.listTitle) +
205            "')/items?$select=" +
206            CONFIG.select +
207            "&$orderby=" +
208            CONFIG.orderBy +
209            " " +
210            (CONFIG.ascending ? "asc" : "desc") +
211            "&$top=" +
212            CONFIG.itemsPerPage;
213
214        fetch(endpoint, {
215            method: "GET",
216            headers: {
217                "Accept": "application/json;odata=verbose"
218            },
219            credentials: "same-origin"
220        })
221        .then(function(response) {
222            if (!response.ok) {
223                throw new Error("HTTP " + response.status);
224            }
225
226            return response.json();
227        })
228        .then(function(data) {
229            var items =
230                data &&
231                data.d &&
232                Array.isArray(data.d.results)
233                    ? data.d.results
234                    : [];
235
236            state.items = items
237                .filter(function(item) {
238                    return isPublished(item.Publicado);
239                })
240                .sort(function(a, b) {
241                    return (Number(a.Orden) || 0) - (Number(b.Orden) || 0);
242                });
243
244            state.visibleRows = 1;
245            state.expanded = false;
246
247            render();
248        })
249        .catch(function(error) {
250            console.error(
251                "ServicioCiudadano: error cargando servicios.",
252                error
253            );
254
255            state.items = [];
256
257            if (grid) {
258                grid.innerHTML =
259                    '<div class="sc-empty">' +
260                        '<span>No fue posible cargar los servicios.</span>' +
261                    '</div>';
262            }
263
264            if (moreWrapper) {
265                moreWrapper.style.display = "none";
266            }
267        });
268    }
269
270    function init() {
271        grid = document.getElementById("servicioCiudadanoGrid");
272        moreWrapper = document.getElementById("servicioCiudadanoMore");
273        moreButton = document.getElementById("scMoreButton");
274
275        if (!grid) {
276            return;
277        }
278
279        if (moreButton) {
280            moreButton.addEventListener("click", handleMoreClick);
281        }
282
283        window.addEventListener("resize", function() {
284            var oldColumns = state.columns;
285            var newColumns = getColumns();
286
287            if (oldColumns !== newColumns) {
288                state.columns = newColumns;
289                state.visibleRows = 1;
290                state.expanded = false;
291
292                render();
293            }
294        });
295
296        loadServices();
297    }
298
299    if (document.readyState === "loading") {
300        document.addEventListener("DOMContentLoaded", init);
301    } else {
302        init();
303    }
304
305})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.