PageSourceSearch

https://www.marketplacejamaica.com/templates/marketplace_jamaica/controllers/search_map/search_map.js?rev=1007

js marketplacejamaica.com collected 2026-10-07 19:39:52 UTC 17,700 bytes, 526 lines download raw bytes

1
2/******************************************************************************
3 *  
4 *  PROJECT: Flynax Classifieds Software
5 *  VERSION: 4.10.2
6 *  LICENSE: FL72OD54Z4G6 - https://www.flynax.com/flynax-software-eula.html
7 *  PRODUCT: General Classifieds
8 *  DOMAIN: marketplacejamaica.com
9 *  FILE: SEARCH_MAP.JS
10 *  
11 *  The software is a commercial product delivered under single, non-exclusive,
12 *  non-transferable license for one domain or IP address. Therefore distribution,
13 *  sale or transfer of the file in whole or in part without permission of Flynax
14 *  respective owners is considered to be illegal and breach of Flynax License End
15 *  User Agreement.
16 *  
17 *  You are not allowed to remove this information from the file without permission
18 *  of Flynax respective owners.
19 *  
20 *  Flynax Classifieds Software 2026 | All copyrights reserved.
21 *  
22 *  https://www.flynax.com
23 ******************************************************************************/
24
25var flMapSearch = function(){
26    var self = this;
27
28    this.options = {
29        mapContainer: null,
30        mapCenter: null,
31        mapAltLocation: null,
32        mapZoom: 14,
33        listingGrid: null,
34        searchForm: null,
35        tabBar: null,
36        perPage: 10,
37        desktopLimit: 500,
38        mobileLimit: 75,
39        geocoder: true
40    };
41
42    this.$gridHeader = null;
43    this.$gridContainer = null;
44    this.$listingContainer = null;
45
46    this.requestTimeout = 1 * 1000;
47    this.listingsTimer = false;
48    this.preventCall = false;
49    this.adsLimit = 0;
50    this.activeTypeKey = null;
51    this.formData = [];
52
53    this.map = null;
54    this.mapClass = null;
55
56    this.init = function(options) {
57        this.options = $.extend(this.options, options);
58
59        this.adsLimit = media_query == 'mobile' ? this.options.mobileLimit : this.options.desktopLimit;
60
61        // Pan map to the visitor location defined by IPGeo plugin
62        if (this.options.mapAltLocation && !this.options.mapCenter.length) {
63            var data = {
64                mode: 'geocoder',
65                lang: rlLang,
66                params: this.options.mapAltLocation
67            };
68
69            flUtil.ajax(data, function(response, status){
70                if (status == 'success' && response.status == 'OK' && response.results[0]) {
71                    self.options.mapCenter = [response.results[0].lat,response.results[0].lng];
72                } else {
73                    self.options.mapCenter = [];
74                }
75
76                self.initMap();
77            });
78        }
79        // Init map with default location
80        else {
81            self.initMap();
82        }
83
84        // Define listing grid related elements
85        if (this.options.listingGrid) {
86            this.$gridHeader = this.options.listingGrid.find('#listings_cont > header');
87            this.$listingContainer = this.options.listingGrid.find('div.wrapper > div');
88            this.$container = $('.search-map-container');
89            this.$mobileNav = self.$container.find('.mobile-navigation > div');
90        }
91    }
92
93    this.initMap = function(){
94        flMap.init(this.options.mapContainer, {
95            center: this.options.mapCenter,
96            zoom: this.options.mapZoom,
97            markerCluster: {
98                groupCount: true
99            },
100            geocoder: !this.options.geocoder ? false : {
101                placeholder: lang['enter_a_location'],
102                position: 'topright'
103            },
104            interactive: true,
105            minimizePrice: {
106                centSeparator: rlConfig['price_separator'],
107                priceDelimiter: rlConfig['price_delimiter'],
108                kPhrase: lang['short_price_k'],
109                mPhrase: lang['short_price_m'],
110                bPhrase: lang['short_price_b']
111            },
112            userLocation: true,
113            idle: function(map){
114                self.map = map;
115                self.mapClass = this;
116
117                self.searchForm();
118                self.tabBar();
119                self.setEvents();
120
121                if (!flynax.getHash()) {
122                    self.getListings();
123                }
124            }
125        });
126    }
127
128    this.setEvents = function(){
129        this.map.on('moveend', function(e){
130            self.callListings();
131        });
132
133        if (this.options.listingGrid) {
134            $('.control.btn').click(function(){
135                var side = rlLangDir == 'ltr' ? 'left' : 'right';
136                var $mapListings = $('#map_listings');
137                var margin = self.$container.hasClass('collapse') ? 0 : '-' + $mapListings.width() + 'px';
138                $mapListings.css('margin-' + side, margin);
139                self.$container.toggleClass('collapse');
140
141                $mapListings.on('transitionend', function(e){
142                    if (e.originalEvent.propertyName == 'margin-' + side) {
143                        self.map.invalidateSize();
144                    }
145                });
146            });
147
148            enquire.register("screen and (max-width: 767px)", {
149                match: function(){
150                    self.gridModeSwitcher(true);
151                },
152                unmatch: function(){
153                    self.gridModeSwitcher(false);
154                }
155            });
156
157            this.options.mapContainer.click(function(){
158                var $mapButton = self.$mobileNav.filter('.map');
159                if (!$mapButton.hasClass('active')) {
160                    $mapButton.trigger('click');
161                }
162            });
163
164            this.$mobileNav.click(function(){
165                if ($(this).hasClass('active')) {
166                    return;
167                }
168
169                self.$mobileNav.filter('.active').removeClass('active');
170                var mode = $(this).attr('class');
171                $(this).addClass('active');
172
173                self.$container
174                    .attr('class', 'search-map-container')
175                    .addClass(mode);
176            });
177        }
178    }
179
180    this.gridModeSwitcher = function(list){
181        var mode = list ? 'list' : 'grid';
182        $('#map_area .first-slide #listings').attr('class', 'clearfix ' + mode);
183    }
184
185    this.searchForm = function(){
186        if (!this.options.searchForm) {
187            return;
188        }
189
190        var $activeForm = this.options.searchForm.filter(':not(.hide)').find('form');
191
192        this.activeTypeKey = $activeForm.attr('accesskey');
193        this.formData      = $activeForm.find('select,input[type=radio]:checked,input[type=text],input[type=number],input[type=hidden]').seri
193alizeArray();
194
195        this.options.searchForm.find('form').submit(function(e) {
196            self.formData = $(this).find('select,input[type=radio]:checked,input[type=text],input[type=number],input[type=hidden]').serializeArray();
197            self.activeTypeKey = $(this).attr('accesskey');
198
199            self.mapClass.closePopups();
200            self.getListings(true);
201
202            // Show map
203            if (self.options.listingGrid && media_query == 'mobile') {
204                self.$mobileNav.filter('.map').trigger('click');
205            }
206
207            e.preventDefault();
208        });
209    }
210
211    this.tabBar = function(){
212        if (!this.options.tabBar) {
213            return;
214        }
215
216        var timer = false;
217
218        this.options.tabBar.find('li a, label').click(function(){
219            if (media_query == 'mobile') {
220                return;
221            }
222
223            clearTimeout(timer);
224
225            var id = $(this).data('target');
226
227            timer = setTimeout(function(){
228                $('#area_' + id + ' form').submit();
229            }, 1000);
230        });
231
232        if (flynax.getHash()) {
233            $('#area_' + flynax.getHash().replace('_tab', '') + ' form').submit();
234        }
235    }
236
237    this.callListings = function(){
238        clearTimeout(this.listingsTimer);
239        this.listingsTimer = setTimeout(function(){
240            if (!self.preventCall) {
241                self.getListings();
242            } else {
243                self.preventCall = false;
244            }
245        }, this.requestTimeout);
246    }
247
248    this.getListings = function(clear){
249        self.loading(true);
250
251        var data = {
252            mode: 'getListingsByCoordinates',
253            ajaxKey: 'getListingsByCoordinates',
254            lang: rlLang,
255            type: self.activeTypeKey,
256            start: 0,
257            form: self.formData,
258            device: media_query,
259            home_page: rlPageInfo['key'] == 'home' ? 1 : 0
260        };
261
262        flUtil.ajax($.extend({}, data, self.getEdgeBounds()), function(result, status){
263            if (status == 'success') {
264                var listingIDs = [];
265                totalListings = 0;
266
267                if (result && result.count > 0) {
268                    totalListings = parseInt(result.listings.length);
269
270                    // Prepare listings
271                    for (var i in result.listings) {
272                        result.listings[i].preview = {
273                            id: result.listings[i].ID,
274                            onClick: function(){
275                                self.preventCall = true;
276                            }
277                        }
278
279                        var gc = parseInt(result.listings[i].gc);
280
281                        if (gc > 1) {
282                            totalListings += gc - 1;
283                            result.listings[i].label = lang['count_properties'].replace('{count}', gc);
284                            result.listings[i].preview.onOpen = self.onGroupOpen;
285                        } else {
286                            result.listings[i].label = result.listings[i].price;
287                        }
288
289                        listingIDs.push(parseInt(result.listings[i].ID));
290                    }
291
292                    self.mapClass.addMarkers(result.listings);
293
294                    // show limit message
295                    if (result.count > self.adsLimit) {
296                        printMessage('warning', lang['map_search_limit_warning']);
297                        clear = true;
298                    }
299                }
300
301                if (clear) {
302                    self.mapClass.removeAllMarkersExcept(listingIDs);
303                }
304
305                // Listing grid
306                if (self.options.listingGrid) {
307                    self.$listingContainer.empty();
308
309                    var $caption = self.$gridHeader.find('.caption');
310
311                    if (result && result.count > 0) {
312                        $caption.text(lang['number_property_found'].replace('{count}', totalListings));
313
314                        // Render listings
315                        self.buildGrid(result.listings);
316                    } else {
317                        $caption.text(lang['no_properties_found']);
318                    }
319                }
320            } else {
321                printMessage('error', lang['map_listings_request_fail']);
322            }
323
324            self.loading(false);
325        });
326    }
327
328    this.getGridMode = function(){
329        return media_query == 'mobile' ? 'list' : 'grid row';
330    }
331
332    this.buildGrid = function(listings){
333        // interface
334        this.$listingContainer.append('<section id="listings" class="clearfix '+ this.getGridMode() +'"></section><div></div>');
335
336        var current_page = 1;
337        var $listingContainer = this.$listingContainer.find('#listings');
338        var $paginationContainer = $listingContainer.next();
339        var ls = null;
340        var rs = null;
341        var pages = Math.ceil(listings.length / this.options.perPage);
342
343        var loadPage = function(){
344            var from = (current_page * self.options.perPage) - self.options.perPage;
345            var to = from + self.options.perPage;
346
347            $listingContainer.empty();
348
349            $('#tmplListing').tmpl(listings.slice(from, to)).appendTo($listingContainer);
350            $listingContainer.find('> article > *').on('mouseenter mouseleave', function(e){
351                var id = parseInt($(this).parent().attr('id').split('_')[2]);
352                self.highlightListing(id, e.type == 'mouseleave');
353            })
354
355            $listingContainer.find('> article.group > *') .on('click', function(){
356                var id = parseInt($(this).parent().attr('id').split('_')[2]);
357                self.zoomToGroup(id);
358            });
359
360            $paginationContainer.find('input').val(current_page);
361            self.options.listingGrid.find('> div').animate({scrollTop: 0}, 'fast');
362
363            flFavoritesHandler();
364            flContactOwnerHandler();
365
366            if (pages > 1) {
367                if (current_page == 1) {
368                    ls.hide();
369                    rs.show();
370                }
371                else if (current_page == pages) {
372                    ls.show();
373                    rs.hide();
374                }
375                else {
376                    ls.show();
377                    rs.show();
378                }
379            }
380        }
381
382        // build pagination
383        if (pages > 1) {
384            $('#tmplPagination').tmpl({pages: pages}).appendTo($paginationContainer);
385            ls = $paginationContainer.find('li.navigator.ls');
386            rs = $paginationContainer.find('li.navigator.rs');
387
388            // events
389            rs.click(function(){
390                current_page++;
391                loadPage();
392            });
393
394            ls.click(function(){
395                current_page--;
396                loadPage();
397            });
398
399            $paginationContainer.find('input').keypress(function(e){
400                if (e.which == 13) {
401                    var r_page = parseInt($(this).val());
402                    if (r_page > 0 && r_page <= pages) {
403                        current_page = r_page;
404                        loadPage();
405                    }
406                }
407            });
408        }
409
410        loadPage();
411    }
412
413    this.onGroupOpen = function(popup, address){
414        if (!address.contentLoaded) {
415            var data = {
416                mode: 'getListingsByCoordinates',
417                item: 'n/a',
418                lang: rlLang,
419                type: self.activeTypeKey,
420                start: 0,
421                form: self.formData,
422                group: 1,
423                lat: address.lat,
424                lng: address.lng
425            };
426            flUtil.ajax(data, function(response, status){
427                if (status == 'success') {
428                    address.contentLoaded = true;
429
430                    if (response.count) {
431                        var content = $('<header>')
432                            .text(lang['number_property_found'].replace('{count}', response.count))
433                            .get(0).outerHTML;
434
435                        $.get(rlConfig.tpl_cors_base + 'components/map-listing/map-listing.tmpl', function(data){
436                            var tmpl = $.templates(data);
437                            content += tmpl.render(response.listings);
438                            popup.popup.setContent(content);
439
440                            flFavoritesHandler();
441                            flContactOwnerHandler();
442                        });
443                    } else {
444                        popup.popup.setContent(lang['system_error']);
445                    }
446                } else {
447                    printMessage('error', lang['system_error']);
448                }
449            });
450        } else {
451            flFavoritesHandler();
452            flContactOwnerHandler();
453        }
454    }
455
456    this.highlightListing = function(id, reset){
457        var marker = this.mapClass.getMarkerByID(id);
458
459        if (marker) {
460            var cluster = this.mapClass.getClusterByMarker(marker);
461
462            if (cluster) {
463                $(cluster.getElement())[
464                    reset ? 'removeClass' : 'addClass'
465                ]('marker-cluster_hover');
466            } else {
467                $(marker.getElement())[
468                    reset ? 'removeClass' : 'addClass'
469                ]('marker-label_hover');
470            }
471        }
472    }
473
474    this.zoomToGroup = function(id){
475        var marker = this.mapClass.getMarkerByID(id);
476
477        if (marker && marker.groupCount > 1) {
478            var cluster = this.mapClass.getClusterByMarker(marker);
479
480            if (cluster) {
481                this.mapClass.markerCluster.zoomToShowLayer(marker, function(){
482                    marker.openPopup();
483                });
484            } else {
485                if (!marker.getPopup().isOpen()) {
486                    marker.openPopup();
487                }
488            }
489        }
490
491        // Show map
492        if (this.options.listingGrid && media_query == 'mobile') {
493            clearTimeout(this.listingsTimer);
494            self.preventCall = true;
495            self.$mobileNav.filter('.map').trigger('click');
496        }
497    }
498
499    this.getEdgeBounds = function(){
500        return {
501            centerLat: this.map.getCenter().lat,
502            centerLng: this.map.getCenter().lng,
503            northEastLat: this.map.getBounds().getNorthEast().lat,
504            northEastLng: this.map.getBounds().getNorthEast().lng,
505            southWestLat: this.map.getBounds().getSouthWest().lat,
506            southWestLng: this.map.getBounds().getSouthWest().lng
507        };
508    }
509
510    this.loading = function(enable){
511        $('.loading-container')[
512            enable ? 'addClass' : 'removeClass'
513        ]('loading-container_show');
514
515        if (enable) {
516            $('.notification div.close').trigger('click');
517        }
518
519        if (this.options.listingGrid) {
520            this.$gridHeader[
521                enable ? 'addClass' : 'removeClass'
522            ]('progress');
523        }
524    }
525};
526var mapSearch = new flMapSearch();

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.