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.