PageSourceSearch

https://zoom.red/wp-content/plugins/mmg-zoom-api/includes/js/asl-custom-sorting.js?ver=13.0.1790274672

js zoom.red collected 2026-09-24 18:31:35 UTC 6,402 bytes, 164 lines download raw bytes

1/**
2 * ZOOM Store Locator Optimization
3 * Integración personalizada para Agile Store Locator (ASL)
4 * 
5 * Reglas de negocio implementadas:
6 * 1. Filtro geográfico estricto (Hard filter): Solo oficinas con distancia <= radio seleccionado.
7 * 2. Jerarquía de ordenamiento de 2 niveles:
8 *    - Prioridad 1: Coincidencia por título con el término buscado (dentro del radio).
9 *    - Prioridad 2: Resto de oficinas dentro del radio ordenadas por distancia ASC.
10 */
11(function ($) {
12    'use strict';
13
14    /**
15     * Normaliza texto: minúsculas, sin acentos/tildes, sin caracteres especiales.
16     */
17    function normalizeText(text) {
18        if (!text) return '';
19        return String(text)
20            .toLowerCase()
21            .normalize('NFD')
22            .replace(/[\u0300-\u036f]/g, '') // Elimina marcas diacríticas (acentos)
23            .replace(/[^a-z0-9\s]/g, ' ')   // Remueve puntuación / caracteres especiales
24            .replace(/\s+/g, ' ')           // Unifica espacios
25            .trim();
26    }
27
28    /**
29     * Obtiene el término de búsqueda relevante ingresado por el usuario.
30     */
31    function getSearchTerms() {
32        var $input = $('#auto-complete-search, .asl-search-address, .asl-search-name');
33        var rawVal = $input.length ? ($input.val() || '') : '';
34        
35        // Si el valor es de geolocalización automática por defecto, se ignora como término de título
36        if (window.asl_configuration && window.asl_configuration.words) {
37            var geoWords = [
38                window.asl_configuration.words.your_cur_loc,
39                window.asl_configuration.words.geo,
40                'tu ubicacion actual',
41                'current location'
42            ];
43            var normVal = normalizeText(rawVal);
44            for (var k = 0; k < geoWords.length; k++) {
45                if (geoWords[k] && normVal === normalizeText(geoWords[k])) {
46                    return { raw: '', primary: '' };
47                }
48            }
49        }
50
51        var fullNorm = normalizeText(rawVal);
52        // El primer segmento antes de la coma suele ser la localidad/sucursal ("Baruta, Caracas..." -> "baruta")
53        var primaryNorm = normalizeText(rawVal.split(',')[0]);
54
55        return {
56            raw: fullNorm,
57            primary: primaryNorm
58        };
59    }
60
61    /**
62     * Calcula el puntaje de coincidencia en el título de la tienda.
63     */
64    function getTitleMatchScore(store, searchTerms) {
65        if (!searchTerms.raw && !searchTerms.primary) return 0;
66        
67        var title = '';
68        if (store.props_ && store.props_.title) {
69            title = normalizeText(store.props_.title);
70        } else if (store.title) {
71            title = normalizeText(store.title);
72        }
73
74        if (!title) return 0;
75
76        // Coincidencia con el segmento principal (ej. "Baruta" en "Zoom C.C. Baruta")
77        if (searchTerms.primary && searchTerms.primary.length >= 2 && title.indexOf(searchTerms.primary) !== -1) {
78            return 2;
79        }
80
81        // Coincidencia con el término completo
82        if (searchTerms.raw && searchTerms.raw.length >= 2 && title.indexOf(searchTerms.raw) !== -1) {
83            return 1;
84        }
85
86        return 0;
87    }
88
89    /**
90     * Inicialización e intercepción de los métodos de Agile Store Locator
91     */
92    function initAslCustomSorting() {
93        if (typeof window.asl_engine === 'undefined' || !window.asl_engine.dataSource) {
94            // Reintentar si ASL aún no está inicializado
95            setTimeout(initAslCustomSorting, 100);
96            return;
97        }
98
99        console.log('Enhanced Search On');
100
101        var proto = window.asl_engine.dataSource.prototype;
102
103        // Sobrescribir el método sortDistance de ASL
104        proto.sortDistance = function (originCoords, storeList) {
105            if (!storeList || !storeList.length) return;
106
107            var searchTerms = getSearchTerms();
108            var maxRadius = (window.asl_configuration && window.asl_configuration.radius_range)
109                ? parseFloat(window.asl_configuration.radius_range)
110                : null;
111
112            // 1. FILTRO ESTRICTO (Hard Filter por radio de distancia)
113            if (maxRadius && !isNaN(maxRadius) && maxRadius > 0) {
114                for (var idx = storeList.length - 1; idx >= 0; idx--) {
115                    var s = storeList[idx];
116                    var d = (s.props_ && typeof s.props_.distance === 'number')
117                        ? s.props_.distance
118                        : (originCoords && typeof s.distanceTo === 'function' ? s.distanceTo(originCoords) : 0);
119                    
120                    if (d > maxRadius) {
121                        storeList.splice(idx, 1);
122                    }
123                }
124            }
125
126            // 2. JERARQUÍA DE ORDENAMIENTO (1° Título dentro del radio, 2° Distancia ASC)
127            storeList.sort(function (a, b) {
128                var distA = (a.props_ && typeof a.props_.distance === 'number')
129                    ? a.props_.distance
130                    : (originCoords && typeof a.distanceTo === 'function' ? a.distanceTo(originCoords) : 0);
131
132                var distB = (b.props_ && typeof b.props_.distance === 'number')
133                    ? b.props_.distance
134                    : (originCoords && typeof b.distanceTo === 'function' ? b.distanceTo(originCoords) : 0);
135
136                var scoreA = getTitleMatchScore(a, searchTerms);
137                var scoreB = getTitleMatchScore(b, searchTerms);
138
139                // Prioridad 1: Coincidencia de título
140                if (scoreA !== scoreB) {
141                    return scoreB - scoreA; // El que tenga mayor score va primero
142                }
143
144                // Prioridad 2: Proximidad (distancia menor a mayor)
145                return distA - distB;
146            });
147        };
148
149        // Adicionalmente, asegurar que en refreshView de la vista se mantenga la jerarquía
150        if (typeof window.asl_locator !== 'undefined' && window.asl_locator.View) {
151            var originalRefreshView = window.asl_locator.View.prototype.refreshView;
152            
153            window.asl_locator.View.prototype.refreshView = function (t) {
154                var viewInstance = this;
155                originalRefreshView.call(viewInstance, t);
156            };
157        }
158    }
159
160    $(document).ready(function () {
161        initAslCustomSorting();
162    });
163
164})(jQuery);

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.