var buscaAjaxEmAndamento = null;
var localidadesAjax = null;
$(document).ready(function () {
// $('#preco-min, #preco-max, #area-max, #area-min').selectpicker('destroy').editableSelect({ effects: 'default', filter: false });
var cmd = $("#cmd").val();
$('#transacao').change(function () {
trocarTiposImoveis();
trocarFaixaValores();
if (cmd == "imoveis" || cmd == "imovel") { // se página de resultado ou ficha do imóvel, já refazer a busca
buscarImoveis(1); // REFAZ A BUSCA, SEM PEDIR CLIQUE NO BOTÃO DE BUSCA
}
});
$("#tipo-imovel").change(function () {
if (!$("#tipo-imovel").val()) {
$(".buscador").find('.buscar-imoveis').find("button").addClass("erro");
} else {
$(".buscador").find('.buscar-imoveis').find("button").removeClass("erro");
}
if (cmd == "imoveis" || cmd == "imovel") { // se página de resultado ou ficha do imóvel, já refazer a busca
buscarImoveis(2); // REFAZ A BUSCA, SEM PEDIR CLIQUE NO BOTÃO DE BUSCA
}
});
$('.precoMinimo,.precoMaximo').maskedInput("000.000.000.000.000,00", {reverse: true});
var xhr;
$('#localidade').autoComplete({
minChars: 3,
source: function (term, response) {
try {
xhr.abort();
} catch (e) {
console.log("error ajax auto complete", e.message);
}
xhr = $.post('/ajax-pegar-localidades', {localidade: term}, function (data) {
response(data);
});
},
renderItem: function (item, search) {
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
response = null;
if (item.bairros !== "" && item.bairros !== undefined && (item.bairros.length > 0)) {
response = "
Bairros
";
zebrado_0 = null;
zn_0 = 0;
for (var i = 0; i < item.bairros.length; i++) {
if (zn_0 % 2 === 0) {
zebrado_0 = 'par';
} else {
zebrado_0 = 'impar';
}
response += '' + item.bairros[i].localidade.replace(re, "$1") + '
';
zn_0++;
}
}
if (item.cidades !== "" && item.cidades !== undefined && (item.cidades.length > 0)) {
response = "Cidades
";
zebrado_1 = null;
zn_1 = 0;
for (var i = 0; i < item.cidades.length; i++) {
if (zn_1 % 2 === 0) {
zebrado_1 = 'par';
} else {
zebrado_1 = 'impar';
}
response += '' + item.cidades[i].localidade.replace(re, "$1") + '
';
zn_1++;
}
}
return response;
},
onSelect: function (e, term, item) {
buscarImoveis(3);
}
});
$(".buscar-imoveis").change(function () {
var cmd = $("#cmd").val();
if (cmd == "imoveis" || cmd == "imovel") { // se página de resultado ou ficha do imóvel, já refazer a busca
buscarImoveis(4);
}
});
$("body").on('click', '#buscar', function(){
buscarImoveis("b");
});
$("#localidade").keyup(function () {
if ($(this).val().length > 3) {
$("#localidade").removeClass("erro");
}
});
$(".buscar").click(function () {
buscarImoveis(6);
});
$("#pesquisar-codigo").click(function () {
var obj = $("#codigo-buscar");
if (obj.val() == "") {
obj.addClass("erro");
} else {
obj.removeClass("erro");
buscarImoveis("c");
}
});
$(".banner").click(function() {
var local = $(this).attr("local");
$.post("ajax-registrar-clique-banner",
{'id': $(this).attr("id"), 'local': $(this).attr("local"), 'url': document.location.href},
function (url) {
// direcionar para a página do banner
if(url != ""){
if(local == "1") {
window.location = url;
}
else {
window.open(url, '_blank');
}
}
}
);
;
});
$(".registrar-clique").click(function() {
$.post("ajax-registrar-clique-resultado-busca",
{'pag': 'res', 'id-imovel': $("#id_imovel").val(), 'id': $(this).attr("id")},
function() {
});
});
});
function carregarVerTelefone() {
$('.b-contatar').find('#ver-telefone').on('click', function () {
$(this).addClass("ativo");
$(this).find('.texto').hide('slow');
$(this).find('.telefones').show('slow');
});
}
function maisFiltros() {
$('#mais-filtros').on('click', function () {
$('.mais-filtros').toggle('slow');
if ($(this).text() == 'MAIS FILTROS') {
$(this).text('MENOS FILTROS');
$(".buscador").addClass("area-mais-filtros");
} else {
$(this).text('MAIS FILTROS');
$(".buscador").removeClass("area-mais-filtros");
}
});
}
function buscarImoveis(controle, parametro) {
$(".buscar").attr('disabled', 'disabled');
var cmd = $("#cmd").val();
var erros = "";
if (!$("#transacao").val()) {
$("#transacao").addClass("erro");
erros += ",transação";
} else {
$("#transacao").removeClass("erro");
}
if ( ($("#tipo-imovel").val() == "" || $("#tipo-imovel").val() == "0") && cmd != "imobiliaria" ) {
$(".buscador").find('.buscar-imoveis').find("button").addClass("erro");
erros += ",localidade";
} else {
$(".buscador").find('.buscar-imoveis').find("button").removeClass("erro");
}
if (!$("#localidade").val()) {
$("#localidade").addClass("erro");
erros += ",localidade";
} else {
if($("#localidade").val().split(',')[1] != undefined && $("#localidade").val().split(',')[1].trim() != ''){
$("#localidade").removeClass("erro");
}else{
$("#localidade").addClass("erro");
erros += ",localidade";
}
}
if (erros != "") {
$("#msg-erro").html("Por favor, preencha os dados faltantes: " + erros.substr(1));
$("#erro-falta-de-dados").fadeTo(2000, 500).slideUp(500, function () {
$("#erro-falta-de-dados").slideUp(500);
});
} else {
if (controle == undefined) {
controle = (cmd == "imoveis" ? "" : "h"); // clique no botão 'BUSCAR' da página principal OU no imóvel
}
fazerBuscaImoveis(controle, parametro);
}
$(".buscar").removeAttr('disabled');
}
function removerFiltroBuscador(filtro, naoRefazerBusca) {
naoRefazerBusca = naoRefazerBusca ? true : false;
ajustarFiltroEliminadoNaTela(filtro);
var filtros = "";
var idsTiposImoveis = "";
var idsBairros = "";
var idsImobiliarias = "";
var quartos = "";
var vagasGaragem = "";
var banheiros = "";
var outrasOpcoes = "";
$(".filtro-aplicado").each(function () {
var valor = $(this).attr("value");
if (!valor || (valor && valor != filtro)) {
if (valor.substr(0, 4) == "tip-") {
idsTiposImoveis += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "bai-") {
idsBairros += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "imb-") {
idsImobiliarias += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "qto-") {
quartos += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "vag-") {
vagasGaragem += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "bnh-") {
banheiros += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "out-") {
outrasOpcoes += ";" + valor.substr(4);
} else if (valor.substr(0, 4) == "vli-" || valor.substr(0, 4) == "vls-" || valor.substr(0, 4) == "ari-" || valor.substr(0, 4) == "ars-") {
filtros += "," + valor.substr(0, 3) + "=" + valor.substr(4);
} else {
filtros += "," + valor + "=" + $(this).html().trim();
}
}
});
if (idsTiposImoveis != "") {
filtros += ",idtip=" + idsTiposImoveis.substr(1);
}
if (idsBairros != "") {
filtros += ",idbai=" + idsBairros.substr(1);
}
if (idsImobiliarias != "") {
filtros += ",idimb=" + idsImobiliarias.substr(1);
}
if (quartos != "") {
filtros += ",qto=" + quartos.substr(1);
}
if (vagasGaragem != "") {
filtros += ",vag=" + vagasGaragem.substr(1);
}
if (banheiros != "") {
filtros += ",bnh=" + banheiros.substr(1);
}
if (outrasOpcoes != "") {
filtros += ",out=" + outrasOpcoes.substr(1);
}
if (!naoRefazerBusca) {
fazerBuscaImoveis("f", filtros.substr(1));
}
}
function ajustarFiltroEliminadoNaTela(filtro) {
if (filtro.substr(0, 4) == "vli-") {
$("#preco-min").val($("#preco-min option:first").val());
} else if (filtro.substr(0, 4) == "vls-") {
$("#preco-max").val($("#preco-max option:first").val());
} else if (filtro.substr(0, 4) == "ari-") {
$("#area-min").val($("#area-min option:first").val());
} else if (filtro.substr(0, 4) == "ars-") {
$("#area-max").val($("#area-max option:first").val());
} else if (filtro.substr(0, 4) == "qto-") {
ajustarFiltroSelectNaTela("quartos", filtro);
} else if (filtro.substr(0, 4) == "vag-") {
ajustarFiltroSelectNaTela("vagas", filtro);
} else if (filtro.substr(0, 4) == "bnh-") {
ajustarFiltroSelectNaTela("banheiros", filtro);
} else if (filtro.substr(0, 4) == "out-") {
$("#" + filtro).prop("checked", false);
}
}
function ajustarFiltroSelectNaTela(id, filtro) {
$(('#' + id) + ' :selected').each(function () {
if ($(this).attr("id") == filtro) {
$(this).prop("selected", false);
}
});
$(('#' + id)).selectpicker("refresh");
}
function buscaImoveisDeCoordenadas(coordenadas) {
buscarImoveis("a", coordenadas);
}
function buscarImoveisMapa() {
buscarImoveis("m");
}
function adicionarCliqueOrdenacao() {
$('#ordenacao').change(function () {
buscarImoveis("o");
});
}
function adicionarCliquesImoveis() {
$(document).find(".imovel").each(
function (i) {
$(this).find('.ir-ficha-imovel').each(
function () {
$(this).on('mouseup', function () {
var idImovel = pegarIdImovel($(this));
var url = pegarUrlImovel($(this));
$.post("ajax-registrar-clique-resultado-busca",
{'pag': 'res', 'id-imovel': idImovel, 'id': $(this).attr("id")},
function () {
}
);
});
}
);
}
);
}
$(function () {
$('#refinar-busca').click(function () {
var btn = $(this);
btn.html("Esconder Refinar Busca").css({
cursor: "wait"
});
$(".refinar").slideToggle("slow", function () {
btn.css({
cursor: "pointer"
});
if ($(this).is(":hidden")) {
btn.html("Refinar Busca");
}
});
}); /* End Refina Busca*/
$(window).on('resize', function () {
if (!$(".toggle").is(":visible") && !$(".refinar").is(':visible'))
{
$(".refinar").css({'display': ''});
}
});
var tfocus = false;
var localidadeAnterior = $('#localidade').val();
$('#localidade').on("focus, click", function (e) {
if ($(this).val().length > 0 && tfocus || tfocus === false) {
localidadeAnterior = $('#localidade').val();
$(this).val("");
}
e.stopPropagation();
$(this).popover({
trigger: 'manual',
container: '.input-group-icon',
template: '',
html: true,
content: function () {
return $('#busca_popover').html();
}
});
if ($(this).val().length <= 0) {
$(this).popover('show');
}
}).keyup(function (e) {
e.stopPropagation();
if ($(this).val().length >= 1) {
$(this).popover('hide');
}
}).blur(function (e) {
e.stopPropagation();
tfocus = true;
// $('#localidade').popover("destroy");
$(this).popover('hide');
if ($(this).val().length == 0) {
$(this).val(localidadeAnterior);
}
}),
$(".ir-para-busca").click(function () {
irPara(SITE + "/imoveis/" + $(this).attr("alvo"));
}),
$(".ir-para-topo").click(function () {
irParaTopo();
}),
$(".posicionar-buscador").click(function () {
var link_text = $(this).text();
$("#localidade").popover({
trigger: 'manual',
container: '.input-group-icon',
template: '',
html: true,
content: function () {
$('#busca_popover_rodape').find("p strong").text(link_text);
return $('#busca_popover_rodape').html();
}
}).keyup(function (e) {
e.stopPropagation();
if ($(this).val().length >= 1) {
$(this).popover('hide');
}
}).blur(function (e) {
e.stopPropagation();
$(this).popover('destroy');
});
$("#localidade").popover('show');
posicionarBuscador($(this).attr("id-transacao"), "#menu-cabecalho");
});
});
function posicionarBuscador(idTransacao, posicao) {
$('#transacao option[value=' + idTransacao + ']').attr('selected', 'selected');
$('#transacao').selectpicker("refresh");
trocarTiposImoveis();
irParaTopo(posicao);
$("#localidade").focus();
}
function trocarTiposImoveis() {
// $.ajaxSetup({async: false});
$.post("ajax-pegar-tipos-imoveis",
{'transacao': $("#transacao").val(), 'tipo-imovel': $("#tipo-imovel").val(), 'tipo': $("#tipo-imovel").attr("tipo")},
function (html) {
$("#tipo-imovel").html(html);
}
);
}
function trocarFaixaValores() {
$.post("ajax-pegar-faixa-valores",
{'transacao': $("#transacao").val()},
function (html) {
// $("#preco-min, #preco-max").editableSelect('destroy');
// $("#preco-min, #preco-max").html(html);
// $("#preco-min, #preco-max").editableSelect({ effects: 'default', filter: false });
$("#preco-min").html(html).selectpicker('refresh');
$("#preco-max").html(html).selectpicker('refresh');
}
);
}
function pegarIdImovel(obj) {
while (($(obj) && $(obj).attr("id-imovel")) == undefined) {
obj = $(obj).parent();
}
return $(obj).attr("id-imovel");
}
function pegarUrlImovel(obj) {
while (!$(obj).hasClass("imovel")) {
obj = $(obj).parent();
}
var url = $(obj).find(".url").attr("url-imovel");
if (url != undefined && url != "/?") {
return url;
} else {
return "";
}
}
function fazerBuscaImoveis(controle, parametro) {
controle = (controle != undefined ? controle : "");
$('.bloco-aguarde').show();
/*
* controle:
* nada: faz a busca na página 1 e atualiza toda a página de resultado
* a: busca imóveis nas coordenadas passadas em 'parametro'
* b: busca vinda do botão 'buscar imóvel'
* c: busca imóveis com código(imobiliária) passado em 'parametro'
* f: busca imóveis com os filtros passados em 'parametro'
* h: busca vinda da home
* l: busca vinda do 'limpar filtros'
* m: busca do mapa
* 2: quando trocou o select do tipo de imóvel
*/
if (controle != "+" || (controle == "+" && !buscaAjaxEmAndamento)) {
if (buscaAjaxEmAndamento) {
buscaAjaxEmAndamento.abort();
buscaAjaxEmAndamento = null;
}
var filtrosAplicar = "";
if (controle == "a") {
coordenadasMapa = parametro;
} else {
coordenadasMapa = $("#coordenadasMapa").val();
}
var tipoImovel = "";
$('#tipo-imovel :selected').each(function () {
if ($(this).val().trim() != "") {
tipoImovel += "," + ($(this).val().trim());
}
});
tipoImovel = tipoImovel.substr(1);
var tipo = $('#tipo-imovel').attr("tipo");
var idsTiposImoveis = "";
// NÃO FUNCIONOU
// if(controle != "b") { // clicado no botão 'buscar'... pegar os tipos de imóveis do grupo
// $(".filtro-aplicado").each(function () { // pegar dos filtros aplicados
// var valor = $(this).attr("value");
// if (valor.substr(0, 4) == "tip-") {
// idsTiposImoveis += ";" + valor.substr(4);
// }
// });
// }
idsTiposImoveis = idsTiposImoveis.substr(1);
if (controle == "f") { // aplicar na busca somente os filtros da sessão 'filtros aplicados'
filtrosAplicar = parametro + ",tip=" + tipoImovel + ",tipi=" + tipo;
} else {
var cmd = $('#cmd').val();
var transacao = $('#transacao').val();
var localidade = $('#localidade').val();
var idImobiliaria = $('#id-imobiliaria').val(); // página de imobiliárias
idImobiliaria = idImobiliaria == undefined ? "" : idImobiliaria;
if (controle == "b" || controle == "h") { // vindo da home ou da página de imobiliárias
//$("#lista-imoveis").html("Aguarde o carregamento dos imóveis...");
$.post("ajax-montar-url-busca",
{'transacao': transacao, 'tipo-imovel': tipoImovel, 'localidade': localidade, 'tipo': tipo, 'cmd': cmd, 'id-imobiliaria': idImobiliaria},
function (url) {
irPara(SITE + "/" + url);
}
);
} else {
var valorMinimo = (null != $("#preco-min").val()) ? $("#preco-min").val().replaceAll(".", "").replaceAll(",",".") : '';
console.log('VM: '+ valorMinimo);
var valorMaximo = (null != $("#preco-max").val()) ? $("#preco-max").val().replaceAll(".", "").replaceAll(",",".") : '';
var areaMinima = (null != $("#area-min").val()) ? $("#area-min").val().replaceAll(".", "").replaceAll(",",".") : '';
var areaMaxima = (null != $("#area-max").val()) ? $("#area-max").val().replaceAll(".", "").replaceAll(",",".") : '';
var dormitorios = "";
$('#quartos :selected').each(function () {
if ($(this).val().trim() != "") {
dormitorios += (dormitorios == "" ? "" : ";") + ($(this).val().trim());
}
});
var vagasGaragem = "";
$('#vagas :selected').each(function () {
if ($(this).val().trim() != "") {
vagasGaragem += (vagasGaragem == "" ? "" : ";") + ($(this).val().trim());
}
});
var banheiros = "";
$('#banheiros :selected').each(function () {
if ($(this).val().trim() != "") {
banheiros += (banheiros == "" ? "" : ";") + ($(this).val().trim());
}
});
var somenteCodigo = "";
var codigoBuscar = "";
if (controle == "c") {
somenteCodigo = $("#somente-codigo").prop("checked");
codigoBuscar = $("#codigo-buscar").val();
}
var outrasCaracteristicas = "";
$(".buscar").each(
function () {
outrasCaracteristicas += $(this).prop("checked") ? "1" : "0";
}
);
}
}
if (controle == "+") {
var pagina = $("#pagina").val();
pagina++;
}
else {
pagina = 1;
}
$("#pagina").val(pagina);
$("#pag").html(pagina);
var ordenacao = $("#ordenacao").val();
var idLogBusca = $("#idLogBusca").val();
var visualizacao = $(".visualizacao.visualizacao-ativa").attr("id");
if (visualizacao == 'mapa' && coordenadasMapa == '')
controle = 'm';
//
//-----------------------
if(controle != "f") {
var idsBairros = "";
var idsImobiliarias = "";
var outrasOpcoes = "";
var filtrosAplicar = ",ord=" + ordenacao;
if(valorMinimo != "") {
filtrosAplicar += ",vli=" + valorMinimo;
}
if(valorMaximo != "") {
filtrosAplicar += ",vls=" + valorMaximo;
}
if(areaMinima != "") {
filtrosAplicar += ",ari=" + areaMinima;
}
if(areaMaxima != "") {
filtrosAplicar += ",ars=" + areaMaxima;
}
if(transacao != "") {
filtrosAplicar += ",trs=" + transacao;
}
if(outrasCaracteristicas != "") {
filtrosAplicar += ",out1=" + outrasCaracteristicas;
}
if(tipo.toLowerCase() == "grupo") {
filtrosAplicar += ",idgrp=" + tipoImovel;
}
if(idImobiliaria != "") {
filtrosAplicar += ",idimb=" + idImobiliaria;
}
if(idLogBusca != "") {
filtrosAplicar += ",idbus=" + idLogBusca;
}
if(localidade != "") {
filtrosAplicar += ",loc=" + localidade.replace(",",";");
}
$(".filtro-aplicado").each(function () {
var valor = $(this).attr("value");
if (valor.substr(0, 4) == "tip-") {
idsTiposImoveis += (idsTiposImoveis == "" ? "" : ";") + valor.substr(4);
} else if (valor.substr(0, 4) == "bai-") {
idsBairros += (idsBairros == "" ? "" : ";") + valor.substr(4);
} else if (valor.substr(0, 4) == "imb-") {
idsImobiliarias += (idsImobiliarias == "" ? "" : ";") + valor.substr(4);
} else if (valor.substr(0, 4) == "vli-" || valor.substr(0, 4) == "vls-" || valor.substr(0, 4) == "ari-" || valor.substr(0, 4) == "ars-") {
filtrosAplicar += (filtrosAplicar == ""? "" : ",") + valor.substr(0, 3) + "=" + valor.substr(4);
} else if (localidade == "" && (valor == "cid" || valor == "uf")) { // pegar cidade e uf se não encontrou na caixa de texto
filtrosAplicar += (filtrosAplicar == ""? "" : ",") + valor + "=" + $(this).html().trim();
}
});
if (idsTiposImoveis != "" && controle != "2") { // ao trocar o tipo de imóvel, não considerar o que tinha nos filtros
filtrosAplicar += ",idtip=" + idsTiposImoveis;
}
if (idsBairros != "") {
filtrosAplicar += ",idbai=" + idsBairros;
}
if (idsImobiliarias != "") {
filtrosAplicar += ",idimb=" + idsImobiliarias;
}
if (dormitorios != "") {
filtrosAplicar += ",qto=" + dormitorios;
}
if (vagasGaragem != "") {
filtrosAplicar += ",vag=" + vagasGaragem;
}
if (banheiros != "") {
filtrosAplicar += ",bnh=" + banheiros;
}
if (outrasOpcoes != "") {
filtrosAplicar += ",out=" + outrasOpcoes;
}
if(codigoBuscar != "") {
filtrosAplicar += ",cod=" + codigoBuscar;
if(somenteCodigo === true) {
filtrosAplicar += ",scod=true";
}
}
}
//
//-----------------------
if (controle != "m") {
// $("#lista-imoveis").html("Aguarde o carregamento dos imóveis...");
}
buscaAjaxEmAndamento = $.post("ajax-buscar-imoveis",
// {'url': document.location.href, 'transacao': transacao, 'tipo-imovel': tipoImovel, 'ids-tipos-imoveis': idsTiposImoveis, 'tipo': tipo, 'localidade': localidade, 'valor-minimo': valorMinimo, 'valor-maximo': valorMaximo, 'area-minima': areaMinima, 'area-maxima': areaMaxima, 'dormitorios': dormitorios, 'vagas-garagem': vagasGaragem, 'banheiros': banheiros, 'pagina': pagina, 'outras-caracteristicas': outrasCaracteristicas, 'codigo-buscar': codigoBuscar, 'somente-codigo': somenteCodigo, 'controle': controle, 'filtros': filtrosAplicar, 'coordenadas-mapa': coordenadasMapa, 'ordenacao': ordenacao, 'visualizacao': visualizacao, 'id-log-busca': idLogBusca, 'id-imobiliaria': idImobiliaria},
{'url': document.location.href, 'pagina': pagina, 'controle': controle, 'filtros': filtrosAplicar, 'coordenadas-mapa': coordenadasMapa, 'ordenacao': ordenacao, 'visualizacao': visualizacao},
function (html) {
if (controle == "m") { // mapa
mapa = null;
initMap(html.imoveis); // função está no arquivo resultado-busca.js
$('.lista-filtros-aplicados').html(html.filtros);
var imoveis_encontrados = '';
if (html.qtImoveisEncontrados == 0)
imoveis_encontrados = 'Nenhum imóvel encontrado';
else if (html.qtImoveisEncontrados == 1)
imoveis_encontrados = '1 imóvel encontrado';
else
imoveis_encontrados = html.qtImoveisEncontrados + ' imóveis encontrados';
$('.imoveis-encontrados').html(imoveis_encontrados);
} else if (controle == "+") { // paginação ou ordenação
$("#lista-imoveis").append(html);
$(document).find('.super-destaque').find('.left').click(); // dispara click para carregar todas as imagens do super destaque
} else {
$("#resultado-busca").html(html);
$(document).find('.super-destaque').find('.left').click(); // dispara click para carregar todas as imagens do super destaque
var url = document.location.href;
var novaURL = $("#novaURL").val();
if (url != SITE + "/" +novaURL) {
$(document).prop("title",$("#tituloPagina").val());
if(novaURL != undefined && novaURL.trim() != ''){
window.history.pushState("", "", SITE + "/" +novaURL);
}
}
}
buscaAjaxEmAndamento = null;
$('select:not(.no-select2)').selectpicker("refresh");
loadImoveis.hide();
}
);
}
}
// local https://github.com/googlemaps/v3-utility-library/blob/master/markerclusterer/src/markerclusterer.js
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @externs_url http://closure-compiler.googlecode.com/svn/trunk/contrib/externs/maps/google_maps_api_v3_3.js
// ==/ClosureCompiler==
/**
* @name MarkerClusterer for Google Maps v3
* @version version 1.0.1
* @author Luke Mahe
* @fileoverview
* The library creates and manages per-zoom-level clusters for large amounts of
* markers.
*
* This is a v3 implementation of the
* v2 MarkerClusterer.
*/
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* A Marker Clusterer that clusters markers.
*
* @param {google.maps.Map} map The Google map to attach to.
* @param {Array.=} opt_markers Optional markers to add to
* the cluster.
* @param {Object=} opt_options support the following options:
* 'gridSize': (number) The grid size of a cluster in pixels.
* 'maxZoom': (number) The maximum zoom level that a marker can be part of a
* cluster.
* 'zoomOnClick': (boolean) Whether the default behaviour of clicking on a
* cluster is to zoom into it.
* 'averageCenter': (boolean) Wether the center of each cluster should be
* the average of all markers in the cluster.
* 'minimumClusterSize': (number) The minimum number of markers to be in a
* cluster before the markers are hidden and a count
* is shown.
* 'styles': (object) An object that has style properties:
* 'url': (string) The image url.
* 'height': (number) The image height.
* 'width': (number) The image width.
* 'anchor': (Array) The anchor position of the label text.
* 'textColor': (string) The text color.
* 'textSize': (number) The text size.
* 'backgroundPosition': (string) The position of the backgound x, y.
* @constructor
* @extends google.maps.OverlayView
*/
function MarkerClusterer(map, opt_markers, opt_options) {
// MarkerClusterer implements google.maps.OverlayView interface. We use the
// extend function to extend MarkerClusterer with google.maps.OverlayView
// because it might not always be available when the code is defined so we
// look for it at the last possible moment. If it doesn't exist now then
// there is no point going ahead :)
this.extend(MarkerClusterer, google.maps.OverlayView);
this.map_ = map;
/**
* @type {Array.}
* @private
*/
this.markers_ = [];
/**
* @type {Array.}
*/
this.clusters_ = [];
this.sizes = [53, 56, 66, 78, 90];
/**
* @private
*/
this.styles_ = [];
/**
* @type {boolean}
* @private
*/
this.ready_ = false;
var options = opt_options || {};
/**
* @type {number}
* @private
*/
this.gridSize_ = options['gridSize'] || 60;
/**
* @private
*/
this.minClusterSize_ = options['minimumClusterSize'] || 2;
/**
* @type {?number}
* @private
*/
this.maxZoom_ = options['maxZoom'] || null;
this.styles_ = options['styles'] || [];
/**
* @type {string}
* @private
*/
this.imagePath_ = options['imagePath'] ||
this.MARKER_CLUSTER_IMAGE_PATH_;
/**
* @type {string}
* @private
*/
this.imageExtension_ = options['imageExtension'] ||
this.MARKER_CLUSTER_IMAGE_EXTENSION_;
/**
* @type {boolean}
* @private
*/
this.zoomOnClick_ = true;
if (options['zoomOnClick'] != undefined) {
this.zoomOnClick_ = options['zoomOnClick'];
}
/**
* @type {boolean}
* @private
*/
this.averageCenter_ = false;
if (options['averageCenter'] != undefined) {
this.averageCenter_ = options['averageCenter'];
}
this.setupStyles_();
this.setMap(map);
/**
* @type {number}
* @private
*/
this.prevZoom_ = this.map_.getZoom();
// Add the map event listeners
var that = this;
google.maps.event.addListener(this.map_, 'zoom_changed', function() {
// Determines map type and prevent illegal zoom levels
var zoom = that.map_.getZoom();
var minZoom = that.map_.minZoom || 0;
var maxZoom = Math.min(that.map_.maxZoom || 100,
that.map_.mapTypes[that.map_.getMapTypeId()].maxZoom);
zoom = Math.min(Math.max(zoom,minZoom),maxZoom);
if (that.prevZoom_ != zoom) {
that.prevZoom_ = zoom;
that.resetViewport();
}
});
google.maps.event.addListener(this.map_, 'idle', function() {
that.redraw();
});
// Finally, add the markers
if (opt_markers && (opt_markers.length || Object.keys(opt_markers).length)) {
this.addMarkers(opt_markers, false);
}
}
/**
* The marker cluster image path.
*
* @type {string}
* @private
*/
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_ = '../images/m';
/**
* The marker cluster image path.
*
* @type {string}
* @private
*/
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_ = 'png';
/**
* Extends a objects prototype by anothers.
*
* @param {Object} obj1 The object to be extended.
* @param {Object} obj2 The object to extend with.
* @return {Object} The new extended object.
* @ignore
*/
MarkerClusterer.prototype.extend = function(obj1, obj2) {
return (function(object) {
for (var property in object.prototype) {
this.prototype[property] = object.prototype[property];
}
return this;
}).apply(obj1, [obj2]);
};
/**
* Implementaion of the interface method.
* @ignore
*/
MarkerClusterer.prototype.onAdd = function() {
this.setReady_(true);
};
/**
* Implementaion of the interface method.
* @ignore
*/
MarkerClusterer.prototype.draw = function() {};
/**
* Sets up the styles object.
*
* @private
*/
MarkerClusterer.prototype.setupStyles_ = function() {
if (this.styles_.length) {
return;
}
for (var i = 0, size; size = this.sizes[i]; i++) {
this.styles_.push({
url: this.imagePath_ + (i + 1) + '.' + this.imageExtension_,
height: size,
width: size
});
}
};
/**
* Fit the map to the bounds of the markers in the clusterer.
*/
MarkerClusterer.prototype.fitMapToMarkers = function() {
var markers = this.getMarkers();
var bounds = new google.maps.LatLngBounds();
for (var i = 0, marker; marker = markers[i]; i++) {
bounds.extend(marker.getPosition());
}
this.map_.fitBounds(bounds);
};
/**
* Sets the styles.
*
* @param {Object} styles The style to set.
*/
MarkerClusterer.prototype.setStyles = function(styles) {
this.styles_ = styles;
};
/**
* Gets the styles.
*
* @return {Object} The styles object.
*/
MarkerClusterer.prototype.getStyles = function() {
return this.styles_;
};
/**
* Whether zoom on click is set.
*
* @return {boolean} True if zoomOnClick_ is set.
*/
MarkerClusterer.prototype.isZoomOnClick = function() {
return this.zoomOnClick_;
};
/**
* Whether average center is set.
*
* @return {boolean} True if averageCenter_ is set.
*/
MarkerClusterer.prototype.isAverageCenter = function() {
return this.averageCenter_;
};
/**
* Returns the array of markers in the clusterer.
*
* @return {Array.} The markers.
*/
MarkerClusterer.prototype.getMarkers = function() {
return this.markers_;
};
/**
* Returns the number of markers in the clusterer
*
* @return {Number} The number of markers.
*/
MarkerClusterer.prototype.getTotalMarkers = function() {
return this.markers_.length;
};
/**
* Sets the max zoom for the clusterer.
*
* @param {number} maxZoom The max zoom level.
*/
MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
this.maxZoom_ = maxZoom;
};
/**
* Gets the max zoom for the clusterer.
*
* @return {number} The max zoom level.
*/
MarkerClusterer.prototype.getMaxZoom = function() {
return this.maxZoom_;
};
/**
* The function for calculating the cluster icon image.
*
* @param {Array.} markers The markers in the clusterer.
* @param {number} numStyles The number of styles available.
* @return {Object} A object properties: 'text' (string) and 'index' (number).
* @private
*/
MarkerClusterer.prototype.calculator_ = function(markers, numStyles) {
var index = 0;
var count = markers.length;
var dv = count;
while (dv !== 0) {
dv = parseInt(dv / 10, 10);
index++;
}
index = Math.min(index, numStyles);
return {
text: count,
index: index
};
};
/**
* Set the calculator function.
*
* @param {function(Array, number)} calculator The function to set as the
* calculator. The function should return a object properties:
* 'text' (string) and 'index' (number).
*
*/
MarkerClusterer.prototype.setCalculator = function(calculator) {
this.calculator_ = calculator;
};
/**
* Get the calculator function.
*
* @return {function(Array, number)} the calculator function.
*/
MarkerClusterer.prototype.getCalculator = function() {
return this.calculator_;
};
/**
* Add an array of markers to the clusterer.
*
* @param {Array.} markers The markers to add.
* @param {boolean=} opt_nodraw Whether to redraw the clusters.
*/
MarkerClusterer.prototype.addMarkers = function(markers, opt_nodraw) {
if (markers.length) {
for (var i = 0, marker; marker = markers[i]; i++) {
this.pushMarkerTo_(marker);
}
} else if (Object.keys(markers).length) {
for (var marker in markers) {
this.pushMarkerTo_(markers[marker]);
}
}
if (!opt_nodraw) {
this.redraw();
}
};
/**
* Pushes a marker to the clusterer.
*
* @param {google.maps.Marker} marker The marker to add.
* @private
*/
MarkerClusterer.prototype.pushMarkerTo_ = function(marker) {
marker.isAdded = false;
if (marker['draggable']) {
// If the marker is draggable add a listener so we update the clusters on
// the drag end.
var that = this;
google.maps.event.addListener(marker, 'dragend', function() {
marker.isAdded = false;
that.repaint();
});
}
this.markers_.push(marker);
};
/**
* Adds a marker to the clusterer and redraws if needed.
*
* @param {google.maps.Marker} marker The marker to add.
* @param {boolean=} opt_nodraw Whether to redraw the clusters.
*/
MarkerClusterer.prototype.addMarker = function(marker, opt_nodraw) {
this.pushMarkerTo_(marker);
if (!opt_nodraw) {
this.redraw();
}
};
/**
* Removes a marker and returns true if removed, false if not
*
* @param {google.maps.Marker} marker The marker to remove
* @return {boolean} Whether the marker was removed or not
* @private
*/
MarkerClusterer.prototype.removeMarker_ = function(marker) {
var index = -1;
if (this.markers_.indexOf) {
index = this.markers_.indexOf(marker);
} else {
for (var i = 0, m; m = this.markers_[i]; i++) {
if (m == marker) {
index = i;
break;
}
}
}
if (index == -1) {
// Marker is not in our list of markers.
return false;
}
marker.setMap(null);
this.markers_.splice(index, 1);
return true;
};
/**
* Remove a marker from the cluster.
*
* @param {google.maps.Marker} marker The marker to remove.
* @param {boolean=} opt_nodraw Optional boolean to force no redraw.
* @return {boolean} True if the marker was removed.
*/
MarkerClusterer.prototype.removeMarker = function(marker, opt_nodraw) {
var removed = this.removeMarker_(marker);
if (!opt_nodraw && removed) {
this.resetViewport();
this.redraw();
return true;
} else {
return false;
}
};
/**
* Removes an array of markers from the cluster.
*
* @param {Array.} markers The markers to remove.
* @param {boolean=} opt_nodraw Optional boolean to force no redraw.
*/
MarkerClusterer.prototype.removeMarkers = function(markers, opt_nodraw) {
var removed = false;
for (var i = 0, marker; marker = markers[i]; i++) {
var r = this.removeMarker_(marker);
removed = removed || r;
}
if (!opt_nodraw && removed) {
this.resetViewport();
this.redraw();
return true;
}
};
/**
* Sets the clusterer's ready state.
*
* @param {boolean} ready The state.
* @private
*/
MarkerClusterer.prototype.setReady_ = function(ready) {
if (!this.ready_) {
this.ready_ = ready;
this.createClusters_();
}
};
/**
* Returns the number of clusters in the clusterer.
*
* @return {number} The number of clusters.
*/
MarkerClusterer.prototype.getTotalClusters = function() {
return this.clusters_.length;
};
/**
* Returns the google map that the clusterer is associated with.
*
* @return {google.maps.Map} The map.
*/
MarkerClusterer.prototype.getMap = function() {
return this.map_;
};
/**
* Sets the google map that the clusterer is associated with.
*
* @param {google.maps.Map} map The map.
*/
MarkerClusterer.prototype.setMap = function(map) {
this.map_ = map;
};
/**
* Returns the size of the grid.
*
* @return {number} The grid size.
*/
MarkerClusterer.prototype.getGridSize = function() {
return this.gridSize_;
};
/**
* Sets the size of the grid.
*
* @param {number} size The grid size.
*/
MarkerClusterer.prototype.setGridSize = function(size) {
this.gridSize_ = size;
};
/**
* Returns the min cluster size.
*
* @return {number} The grid size.
*/
MarkerClusterer.prototype.getMinClusterSize = function() {
return this.minClusterSize_;
};
/**
* Sets the min cluster size.
*
* @param {number} size The grid size.
*/
MarkerClusterer.prototype.setMinClusterSize = function(size) {
this.minClusterSize_ = size;
};
/**
* Extends a bounds object by the grid size.
*
* @param {google.maps.LatLngBounds} bounds The bounds to extend.
* @return {google.maps.LatLngBounds} The extended bounds.
*/
MarkerClusterer.prototype.getExtendedBounds = function(bounds) {
var projection = this.getProjection();
// Turn the bounds into latlng.
var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),
bounds.getNorthEast().lng());
var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),
bounds.getSouthWest().lng());
// Convert the points to pixels and the extend out by the grid size.
var trPix = projection.fromLatLngToDivPixel(tr);
trPix.x += this.gridSize_;
trPix.y -= this.gridSize_;
var blPix = projection.fromLatLngToDivPixel(bl);
blPix.x -= this.gridSize_;
blPix.y += this.gridSize_;
// Convert the pixel points back to LatLng
var ne = projection.fromDivPixelToLatLng(trPix);
var sw = projection.fromDivPixelToLatLng(blPix);
// Extend the bounds to contain the new bounds.
bounds.extend(ne);
bounds.extend(sw);
return bounds;
};
/**
* Determins if a marker is contained in a bounds.
*
* @param {google.maps.Marker} marker The marker to check.
* @param {google.maps.LatLngBounds} bounds The bounds to check against.
* @return {boolean} True if the marker is in the bounds.
* @private
*/
MarkerClusterer.prototype.isMarkerInBounds_ = function(marker, bounds) {
return bounds.contains(marker.getPosition());
};
/**
* Clears all clusters and markers from the clusterer.
*/
MarkerClusterer.prototype.clearMarkers = function() {
this.resetViewport(true);
// Set the markers a empty array.
this.markers_ = [];
};
/**
* Clears all existing clusters and recreates them.
* @param {boolean} opt_hide To also hide the marker.
*/
MarkerClusterer.prototype.resetViewport = function(opt_hide) {
// Remove all the clusters
for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
cluster.remove();
}
// Reset the markers to not be added and to be invisible.
for (var i = 0, marker; marker = this.markers_[i]; i++) {
marker.isAdded = false;
if (opt_hide) {
marker.setMap(null);
}
}
this.clusters_ = [];
};
/**
*
*/
MarkerClusterer.prototype.repaint = function() {
var oldClusters = this.clusters_.slice();
this.clusters_.length = 0;
this.resetViewport();
this.redraw();
// Remove the old clusters.
// Do it in a timeout so the other clusters have been drawn first.
window.setTimeout(function() {
for (var i = 0, cluster; cluster = oldClusters[i]; i++) {
cluster.remove();
}
}, 0);
};
/**
* Redraws the clusters.
*/
MarkerClusterer.prototype.redraw = function() {
this.createClusters_();
};
/**
* Calculates the distance between two latlng locations in km.
* @see http://www.movable-type.co.uk/scripts/latlong.html
*
* @param {google.maps.LatLng} p1 The first lat lng point.
* @param {google.maps.LatLng} p2 The second lat lng point.
* @return {number} The distance between the two points in km.
* @private
*/
MarkerClusterer.prototype.distanceBetweenPoints_ = function(p1, p2) {
if (!p1 || !p2) {
return 0;
}
var R = 6371; // Radius of the Earth in km
var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
};
/**
* Add a marker to a cluster, or creates a new cluster.
*
* @param {google.maps.Marker} marker The marker to add.
* @private
*/
MarkerClusterer.prototype.addToClosestCluster_ = function(marker) {
var distance = 40000; // Some large number
var clusterToAddTo = null;
var pos = marker.getPosition();
for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
var center = cluster.getCenter();
if (center) {
var d = this.distanceBetweenPoints_(center, marker.getPosition());
if (d < distance) {
distance = d;
clusterToAddTo = cluster;
}
}
}
if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
clusterToAddTo.addMarker(marker);
} else {
var cluster = new Cluster(this);
cluster.addMarker(marker);
this.clusters_.push(cluster);
}
};
/**
* Creates the clusters.
*
* @private
*/
MarkerClusterer.prototype.createClusters_ = function() {
if (!this.ready_) {
return;
}
// Get our current map view bounds.
// Create a new bounds object so we don't affect the map.
var mapBounds = new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(),
this.map_.getBounds().getNorthEast());
var bounds = this.getExtendedBounds(mapBounds);
for (var i = 0, marker; marker = this.markers_[i]; i++) {
if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {
this.addToClosestCluster_(marker);
}
}
};
/**
* A cluster that contains markers.
*
* @param {MarkerClusterer} markerClusterer The markerclusterer that this
* cluster is associated with.
* @constructor
* @ignore
*/
function Cluster(markerClusterer) {
this.markerClusterer_ = markerClusterer;
this.map_ = markerClusterer.getMap();
this.gridSize_ = markerClusterer.getGridSize();
this.minClusterSize_ = markerClusterer.getMinClusterSize();
this.averageCenter_ = markerClusterer.isAverageCenter();
this.center_ = null;
this.markers_ = [];
this.bounds_ = null;
this.clusterIcon_ = new ClusterIcon(this, markerClusterer.getStyles(),
markerClusterer.getGridSize());
}
/**
* Determins if a marker is already added to the cluster.
*
* @param {google.maps.Marker} marker The marker to check.
* @return {boolean} True if the marker is already added.
*/
Cluster.prototype.isMarkerAlreadyAdded = function(marker) {
if (this.markers_.indexOf) {
return this.markers_.indexOf(marker) != -1;
} else {
for (var i = 0, m; m = this.markers_[i]; i++) {
if (m == marker) {
return true;
}
}
}
return false;
};
/**
* Add a marker the cluster.
*
* @param {google.maps.Marker} marker The marker to add.
* @return {boolean} True if the marker was added.
*/
Cluster.prototype.addMarker = function(marker) {
if (this.isMarkerAlreadyAdded(marker)) {
return false;
}
if (!this.center_) {
this.center_ = marker.getPosition();
this.calculateBounds_();
} else {
if (this.averageCenter_) {
var l = this.markers_.length + 1;
var lat = (this.center_.lat() * (l-1) + marker.getPosition().lat()) / l;
var lng = (this.center_.lng() * (l-1) + marker.getPosition().lng()) / l;
this.center_ = new google.maps.LatLng(lat, lng);
this.calculateBounds_();
}
}
marker.isAdded = true;
this.markers_.push(marker);
var len = this.markers_.length;
if (len < this.minClusterSize_ && marker.getMap() != this.map_) {
// Min cluster size not reached so show the marker.
marker.setMap(this.map_);
}
if (len == this.minClusterSize_) {
// Hide the markers that were showing.
for (var i = 0; i < len; i++) {
this.markers_[i].setMap(null);
}
}
if (len >= this.minClusterSize_) {
marker.setMap(null);
}
this.updateIcon();
return true;
};
/**
* Returns the marker clusterer that the cluster is associated with.
*
* @return {MarkerClusterer} The associated marker clusterer.
*/
Cluster.prototype.getMarkerClusterer = function() {
return this.markerClusterer_;
};
/**
* Returns the bounds of the cluster.
*
* @return {google.maps.LatLngBounds} the cluster bounds.
*/
Cluster.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
var markers = this.getMarkers();
for (var i = 0, marker; marker = markers[i]; i++) {
bounds.extend(marker.getPosition());
}
return bounds;
};
/**
* Removes the cluster
*/
Cluster.prototype.remove = function() {
this.clusterIcon_.remove();
this.markers_.length = 0;
delete this.markers_;
};
/**
* Returns the center of the cluster.
*
* @return {number} The cluster center.
*/
Cluster.prototype.getSize = function() {
return this.markers_.length;
};
/**
* Returns the center of the cluster.
*
* @return {Array.} The cluster center.
*/
Cluster.prototype.getMarkers = function() {
return this.markers_;
};
/**
* Returns the center of the cluster.
*
* @return {google.maps.LatLng} The cluster center.
*/
Cluster.prototype.getCenter = function() {
return this.center_;
};
/**
* Calculated the extended bounds of the cluster with the grid.
*
* @private
*/
Cluster.prototype.calculateBounds_ = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);
};
/**
* Determines if a marker lies in the clusters bounds.
*
* @param {google.maps.Marker} marker The marker to check.
* @return {boolean} True if the marker lies in the bounds.
*/
Cluster.prototype.isMarkerInClusterBounds = function(marker) {
return this.bounds_.contains(marker.getPosition());
};
/**
* Returns the map that the cluster is associated with.
*
* @return {google.maps.Map} The map.
*/
Cluster.prototype.getMap = function() {
return this.map_;
};
/**
* Updates the cluster icon
*/
Cluster.prototype.updateIcon = function() {
var zoom = this.map_.getZoom();
var mz = this.markerClusterer_.getMaxZoom();
if (mz && zoom > mz) {
// The zoom is greater than our max zoom so show all the markers in cluster.
for (var i = 0, marker; marker = this.markers_[i]; i++) {
marker.setMap(this.map_);
}
return;
}
if (this.markers_.length < this.minClusterSize_) {
// Min cluster size not yet reached.
this.clusterIcon_.hide();
return;
}
var numStyles = this.markerClusterer_.getStyles().length;
var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);
this.clusterIcon_.setCenter(this.center_);
this.clusterIcon_.setSums(sums);
this.clusterIcon_.show();
};
/**
* A cluster icon
*
* @param {Cluster} cluster The cluster to be associated with.
* @param {Object} styles An object that has style properties:
* 'url': (string) The image url.
* 'height': (number) The image height.
* 'width': (number) The image width.
* 'anchor': (Array) The anchor position of the label text.
* 'textColor': (string) The text color.
* 'textSize': (number) The text size.
* 'backgroundPosition: (string) The background postition x, y.
* @param {number=} opt_padding Optional padding to apply to the cluster icon.
* @constructor
* @extends google.maps.OverlayView
* @ignore
*/
function ClusterIcon(cluster, styles, opt_padding) {
cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);
this.styles_ = styles;
this.padding_ = opt_padding || 0;
this.cluster_ = cluster;
this.center_ = null;
this.map_ = cluster.getMap();
this.div_ = null;
this.sums_ = null;
this.visible_ = false;
this.setMap(this.map_);
}
/**
* Triggers the clusterclick event and zoom's if the option is set.
*/
ClusterIcon.prototype.triggerClusterClick = function() {
var markerClusterer = this.cluster_.getMarkerClusterer();
// Trigger the clusterclick event.
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
if (markerClusterer.isZoomOnClick()) {
// Zoom into the cluster.
this.map_.fitBounds(this.cluster_.getBounds());
}
};
/**
* Adding the cluster icon to the dom.
* @ignore
*/
ClusterIcon.prototype.onAdd = function() {
this.div_ = document.createElement('DIV');
if (this.visible_) {
var pos = this.getPosFromLatLng_(this.center_);
this.div_.style.cssText = this.createCss(pos);
this.div_.innerHTML = this.sums_.text;
}
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this.div_);
var that = this;
google.maps.event.addDomListener(this.div_, 'click', function() {
that.triggerClusterClick();
});
};
/**
* Returns the position to place the div dending on the latlng.
*
* @param {google.maps.LatLng} latlng The position in latlng.
* @return {google.maps.Point} The position in pixels.
* @private
*/
ClusterIcon.prototype.getPosFromLatLng_ = function(latlng) {
var pos = this.getProjection().fromLatLngToDivPixel(latlng);
pos.x -= parseInt(this.width_ / 2, 10);
pos.y -= parseInt(this.height_ / 2, 10);
return pos;
};
/**
* Draw the icon.
* @ignore
*/
ClusterIcon.prototype.draw = function() {
if (this.visible_) {
var pos = this.getPosFromLatLng_(this.center_);
this.div_.style.top = pos.y + 'px';
this.div_.style.left = pos.x + 'px';
}
};
/**
* Hide the icon.
*/
ClusterIcon.prototype.hide = function() {
if (this.div_) {
this.div_.style.display = 'none';
}
this.visible_ = false;
};
/**
* Position and show the icon.
*/
ClusterIcon.prototype.show = function() {
if (this.div_) {
var pos = this.getPosFromLatLng_(this.center_);
this.div_.style.cssText = this.createCss(pos);
this.div_.style.display = '';
}
this.visible_ = true;
};
/**
* Remove the icon from the map
*/
ClusterIcon.prototype.remove = function() {
this.setMap(null);
};
/**
* Implementation of the onRemove interface.
* @ignore
*/
ClusterIcon.prototype.onRemove = function() {
if (this.div_ && this.div_.parentNode) {
this.hide();
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
/**
* Set the sums of the icon.
*
* @param {Object} sums The sums containing:
* 'text': (string) The text to display in the icon.
* 'index': (number) The style index of the icon.
*/
ClusterIcon.prototype.setSums = function(sums) {
this.sums_ = sums;
this.text_ = sums.text;
this.index_ = sums.index;
if (this.div_) {
this.div_.innerHTML = sums.text;
}
this.useStyle();
};
/**
* Sets the icon to the the styles.
*/
ClusterIcon.prototype.useStyle = function() {
var index = Math.max(0, this.sums_.index - 1);
index = Math.min(this.styles_.length - 1, index);
var style = this.styles_[index];
this.url_ = style['url'];
this.height_ = style['height'];
this.width_ = style['width'];
this.textColor_ = style['textColor'];
this.anchor_ = style['anchor'];
this.textSize_ = style['textSize'];
this.backgroundPosition_ = style['backgroundPosition'];
};
/**
* Sets the center of the icon.
*
* @param {google.maps.LatLng} center The latlng to set as the center.
*/
ClusterIcon.prototype.setCenter = function(center) {
this.center_ = center;
};
/**
* Create the css text based on the position of the icon.
*
* @param {google.maps.Point} pos The position.
* @return {string} The css style text.
*/
ClusterIcon.prototype.createCss = function(pos) {
var style = [];
style.push('background-image:url(' + this.url_ + ');');
var backgroundPosition = this.backgroundPosition_ ? this.backgroundPosition_ : '0 0';
style.push('background-position:' + backgroundPosition + ';');
if (typeof this.anchor_ === 'object') {
if (typeof this.anchor_[0] === 'number' && this.anchor_[0] > 0 &&
this.anchor_[0] < this.height_) {
style.push('height:' + (this.height_ - this.anchor_[0]) +
'px; padding-top:' + this.anchor_[0] + 'px;');
} else {
style.push('height:' + this.height_ + 'px; line-height:' + this.height_ +
'px;');
}
if (typeof this.anchor_[1] === 'number' && this.anchor_[1] > 0 &&
this.anchor_[1] < this.width_) {
style.push('width:' + (this.width_ - this.anchor_[1]) +
'px; padding-left:' + this.anchor_[1] + 'px;');
} else {
style.push('width:' + this.width_ + 'px; text-align:center;');
}
} else {
style.push('height:' + this.height_ + 'px; line-height:' +
this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;');
}
var txtColor = this.textColor_ ? this.textColor_ : 'black';
var txtSize = this.textSize_ ? this.textSize_ : 11;
style.push('cursor:pointer; top:' + pos.y + 'px; left:' +
pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +
txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
return style.join('');
};
// Export Symbols for Closure
// If you are not going to compile with closure then you can remove the
// code below.
window['MarkerClusterer'] = MarkerClusterer;
MarkerClusterer.prototype['addMarker'] = MarkerClusterer.prototype.addMarker;
MarkerClusterer.prototype['addMarkers'] = MarkerClusterer.prototype.addMarkers;
MarkerClusterer.prototype['clearMarkers'] =
MarkerClusterer.prototype.clearMarkers;
MarkerClusterer.prototype['fitMapToMarkers'] =
MarkerClusterer.prototype.fitMapToMarkers;
MarkerClusterer.prototype['getCalculator'] =
MarkerClusterer.prototype.getCalculator;
MarkerClusterer.prototype['getGridSize'] =
MarkerClusterer.prototype.getGridSize;
MarkerClusterer.prototype['getExtendedBounds'] =
MarkerClusterer.prototype.getExtendedBounds;
MarkerClusterer.prototype['getMap'] = MarkerClusterer.prototype.getMap;
MarkerClusterer.prototype['getMarkers'] = MarkerClusterer.prototype.getMarkers;
MarkerClusterer.prototype['getMaxZoom'] = MarkerClusterer.prototype.getMaxZoom;
MarkerClusterer.prototype['getStyles'] = MarkerClusterer.prototype.getStyles;
MarkerClusterer.prototype['getTotalClusters'] =
MarkerClusterer.prototype.getTotalClusters;
MarkerClusterer.prototype['getTotalMarkers'] =
MarkerClusterer.prototype.getTotalMarkers;
MarkerClusterer.prototype['redraw'] = MarkerClusterer.prototype.redraw;
MarkerClusterer.prototype['removeMarker'] =
MarkerClusterer.prototype.removeMarker;
MarkerClusterer.prototype['removeMarkers'] =
MarkerClusterer.prototype.removeMarkers;
MarkerClusterer.prototype['resetViewport'] =
MarkerClusterer.prototype.resetViewport;
MarkerClusterer.prototype['repaint'] =
MarkerClusterer.prototype.repaint;
MarkerClusterer.prototype['setCalculator'] =
MarkerClusterer.prototype.setCalculator;
MarkerClusterer.prototype['setGridSize'] =
MarkerClusterer.prototype.setGridSize;
MarkerClusterer.prototype['setMaxZoom'] =
MarkerClusterer.prototype.setMaxZoom;
MarkerClusterer.prototype['onAdd'] = MarkerClusterer.prototype.onAdd;
MarkerClusterer.prototype['draw'] = MarkerClusterer.prototype.draw;
Cluster.prototype['getCenter'] = Cluster.prototype.getCenter;
Cluster.prototype['getSize'] = Cluster.prototype.getSize;
Cluster.prototype['getMarkers'] = Cluster.prototype.getMarkers;
ClusterIcon.prototype['onAdd'] = ClusterIcon.prototype.onAdd;
ClusterIcon.prototype['draw'] = ClusterIcon.prototype.draw;
ClusterIcon.prototype['onRemove'] = ClusterIcon.prototype.onRemove;
Object.keys = Object.keys || function(o) {
var result = [];
for(var name in o) {
if (o.hasOwnProperty(name))
result.push(name);
}
return result;
};var mapa;
var drawingManager;
var quantidade = null;
var scroll = 0;
var verificador = 0;
$(document).ready(function () {
// $('select').selectpicker();
$(document).scroll(function () {
// -- valmir
// var num = parseInt($(document).scrollTop()) % parseInt($("#publicidade-3").height());
// if(num < 100) {
// if(parseInt($("#publicidade-3").height()) >= parseInt($(document).scrollTop())) {
// $("#publicidade-3").css("top", "auto").css("position","relative");
// }
// else if(parseInt($("#publicidade-3").css("top")) + parseInt($("#publicidade-3").height()) <= (parseInt($("#lista-imoveis").height()) - parseInt($("#lista-imoveis").offset().top)) ) {
// $("#publicidade-3").animate($("#publicidade-3").css("top", parseInt($(document).scrollTop()) - parseInt($("#col-esquerda").offset().top) - parseInt($("#filtros-aplicados").height()), 'slow'));
// }
// }
// -- valmir
var topPadrao = 800;
// andre
var tamanhoFiltros = $('#filtros-aplicados').height();
var numBanners = $("#publicidade-3 .banner").length;
if(numBanners > 0){
if(parseInt($(document).scrollTop()) > topPadrao){
$("#publicidade-3").css("top", parseInt($(document).scrollTop())-(parseInt(topPadrao)+parseInt(scroll)) );
if(verificador == 1){
scroll -= (numBanners <= 2) ? 0.5 : 5;
if($(document).scrollTop() < parseInt($('#publicidade-3 div:first-child').offset().top)){
verificador = 0;
}
}else{
scroll += (numBanners <= 2) ? 0.5 : 5;
if( ($(document).scrollTop()+$('#publicidade-3 div:last-child').height()) > parseInt($('#publicidade-3 div:last-child').offset().top)) {
verificador = 1;
}
}
}
if(parseInt($(document).scrollTop())+topPadrao > $('.lista-imoveis').height()){
$("#publicidade-3").css("top",(parseInt($('.lista-imoveis').height()) + tamanhoFiltros) - (topPadrao+parseInt($("#publicidade-3").height()))) ;
}
if(parseInt($(document).scrollTop()) <= topPadrao+tamanhoFiltros){
$("#publicidade-3").css("top",0);
}
}
// andre
// var altura = $('#lista-imoveis').offset().top + $('#lista-imoveis').height();
// var item = $('#lista-imoveis .imovel:last').offset().top-$('#lista-imoveis .imovel:last').height();
// console.log($(document).scrollTop()+' >= '+item);
// if ($(document).scrollTop() >= item ) {
// console.log('carregou');
// var pagina = $("#pagina").val();
// var quantidadeImoveis = $('#qtImoveisEncontrados').text();
// if(pagina <= 5) {
// fazerBuscaImoveis("+");
// }
// else { // deixar visivel o botão de 'carregar mais imóveis'
// if(pagina == Math.ceil(quantidadeImoveis / 10))
// $('.bloco-carregar-mais').hide();
// carregarMaisImoveis();
// }
// }
// var item = $('#lista-imoveis .imovel:last').offset().top-($('#lista-imoveis .imovel:last').height()*0.8);
//const item = $('#lista-imoveis .card-imovel:last').offset().top-($('#lista-imoveis .imovel:last').height()*3);
// if (($(document).scrollTop() ) >= item) {
// if(!$('.sem-imoveis').is(':visible')){
// var pagina = $("#pagina").val();
// if(null == quantidade){
// quantidade = $('#lista-imoveis .imovel').length;
// }
// var quantidadeImoveis = $('#qtImoveisEncontrados').text();
// if(pagina <= 5) {
// if(pagina <= Math.ceil(quantidadeImoveis / quantidade))
// fazerBuscaImoveis("+");
// }
// else { // deixar visivel o botão de 'carregar mais imóveis'
// if(pagina == Math.ceil(quantidadeImoveis / quantidade)){
// $('.bloco-carregar-mais').hide();
// }
// carregarMaisImoveis();
// }
// }
// }
});
maisFiltros();
visualizacao();
exibeBotaoVoltarTopo();
abreModalContatar();
carregarVerTelefone();
carregaAcaoMarcarArea();
semImoveis();
if ($('#exibir-modal-sugestoes-baseadas').val() == 1)
$('#modal-sugestoes-baseadas').modal();
carregarCarrossel('#lista-imoveis'); // função em geral.js
// clickBotaoDireito();
});
// function clickBotaoDireito(){
// var menu = $(".menu");
// $(document).mouseup(function(){
// menu.hide();
// });
// $('.ir-ficha-imovel').contextmenu(function(e) {
// menu.show();
// menu.css('marginLeft', e.pageX + 'px');
// menu.css('marginTop', e.pageY + 'px');
// e.preventDefault();
// menu.find('a').attr('id-imovel', pegarIdImovel(e.target));
// menu.find('.url').attr('url-imovel', pegarUrlImovel(e.target));
// });
// }
function semImoveis(){
$(document).on('click','.sem-imoveis', function(){
irParaTopo();
});
}
function exibeBotaoVoltarTopo() {
$(document).scroll(function () {
var posicaoScroll = $(document).scrollTop(); // obtem a quantidade de scroll no momento
if (posicaoScroll > 1400) {
$('#voltar-topo img').show('slow');
} else {
$('#voltar-topo img').hide('slow');
}
});
$(document).on('click','#voltar-topo', function () {
irParaTopo();
});
}
function carregarMaisImoveis() {
$('#carregar-mais-imoveis').show('slow');
$('#carregar-mais-imoveis').on('click', function () {
fazerBuscaImoveis("+");
});
}
function visualizacao() {
$(document).on('click','.visualizacao', function () {
var visualizacao_ant = $('.visualizacao-ativa').attr('id');
$('.visualizacao').removeClass('visualizacao-ativa');
$(this).addClass('visualizacao-ativa');
$('#lista-imoveis').attr('class', '').addClass('row ' + $(this).attr('id') + '-imoveis');
if ($(this).attr('id') == 'mapa') {
$('.mapa').show('slow');
$('.tipo-ordenacao').hide();
$('#carregar-mais-imoveis').addClass('dNone');
$('.imoveis-encontrados').addClass('dNone');
$('.imoveis-encontrados.do-mapa').removeClass('dNone');
$('.bloco-aguarde.botton').addClass('dNone');
carregarMapa();
} else {
$('.tipo-ordenacao').show();
$('.marcar-area').hide();
$('.mapa').hide('slow');
$('.imoveis-encontrados').removeClass('dNone');
$('.imoveis-encontrados.do-mapa').addClass('dNone');
$('#carregar-mais-imoveis').removeClass('dNone');
if(visualizacao_ant == 'mapa'){
mapa = null;
fazerBuscaImoveis();
}
}
irParaTopo('#resultado-busca');
});
if($('.visualizacao-ativa').attr('id') == 'mapa'){
$('.mapa').show('slow');
$('.tipo-ordenacao').hide();
$('#carregar-mais-imoveis').addClass('dNone');
$('.imoveis-encontrados').addClass('dNone');
$('.imoveis-encontrados.do-mapa').removeClass('dNone');
$('.bloco-aguarde.botton').addClass('dNone');
carregarMapa();
}
}
function maisFiltros() {
$('#mais-filtros').on('click', function () {
$('.mais-filtros').toggle('slow');
if ($(this).text() == 'MAIS FILTROS') {
$(this).text('MENOS FILTROS');
$(".buscador").addClass("area-mais-filtros");
} else {
$(this).text('MAIS FILTROS');
$(".buscador").removeClass("area-mais-filtros");
}
});
}
function carregaAcaoMarcarArea(){
$(document).on('click', '.marcar-area', function () {
if ($(this).hasClass('desmarcar')) {
drawingManager.setMap(null);
$('.marcar-area').removeClass('desmarcar');
} else {
desenharNoMapa();
$('.marcar-area').addClass('desmarcar');
}
});
}
function carregarMapa() {
$('.aguarde').show();
// if (mapa == null)
buscarImoveisMapa(); // função em geral/buscador.js
// else
$('.marcar-area').show();
}
function initMap(dadosJson) {
var latitude = '';
var longitude = '';
var markerCluster;
locations = new Array();
dados = new Array();
var i = 0;
// console.log(dadosJson);
// $.each(dadosJson, function (y, item) {
// if (item.latitude != '' || item.longitude != "") {
// // console.log(item);
// locations[i] = (new google.maps.LatLng(item.latitude, item.longitude));
// dados[i] = new Object();
// dados[i].id_imovel = item.id_imovel;
// dados[i].valor = item.preco;
// dados[i].foto = item.foto;
// dados[i].descricao = item.descricao_imovel;
// i++;
// }
// })
$.each(dadosJson, function (y, item) {
// latitude = item.latitude;
// longitude = item.longitude;
if (item.latitude != '' || item.longitude != "") {
// *
locations[i] = (new google.maps.LatLng(item.latitude, item.longitude));
dados[i] = new Object();
dados[i].id_imovel = item.id_imovel;
dados[i].valor = item.preco;
dados[i].foto = item.foto;
dados[i].descricao = item.descricao_imovel;
i++;
// *
if (mapa == null) {
var position = new google.maps.LatLng(item.latitude, item.longitude);
mapa = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: position,
scrollwheel: true
});
definirCentroCidade($('#localidade').val());
google.maps.event.trigger(mapa, 'resize');
$('.marcar-area').show();
}
}
})
var infowindow = new google.maps.InfoWindow({maxWidth: 300});
var markers = locations.map(function (location, i) {
var marker = new google.maps.Marker({
position: location,
animation: google.maps.Animation.DROP,
label: {
text: dados[i].valor,
color: 'white',
fontSize: '12px'
},
title: dados[i].descricao,
color: '#fff',
customInfo: i,
icon: {
url: '/site/imagens/mapa/pin-preco.png',
labelOrigin: new google.maps.Point(40, 13)
}//pinSymbol('#118bbe')
});
google.maps.event.addListener(marker, 'click', function (cluster) {
var arr = [dados[i]];
infowindow.setContent(imovelHTML(arr));
infowindow.open(mapa, this);
});
return marker;
});
if(null != mapa){
markerCluster = new MarkerClusterer(mapa, markers,
{imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
google.maps.event.addListener(markerCluster, 'clusterclick', function (cluster) {
var markers = cluster.getMarkers();
var coordenadas = '';
var cont = 0;
var arr = new Array();
var i = 0;
if (markers.length > 1 && markers.length < 20) {
/*
só exibe o info no cluster casso o numero de markers dele seja > 1 && < 20 e as coordenadas sejam as mesmas
*/
for (var y = 0; y < markers.length; y++) {
var latLng = markers[y].position.lat().toString().substr(0, 8) + ',' + markers[y].position.lng().toString().substr(0, 8);
if (coordenadas != '' && coordenadas.indexOf(latLng) < 0) {
/* caso latLng não exista no array de coordenadas, quer dizer que latLng é diferente */
cont++;
} else {
coordenadas += latLng;
arr[i] = dados[markers[y].customInfo];
/* cria um pino para que o infoWindow possa aparecer nas coordenadas certas,
esse pino não é exibido na tela.
*/
var m = new google.maps.Marker({position: markers[y].position, icon: '/site/imagens/mapa/ponto.png'});
m.setMap(mapa);
i++;
}
}
/* se cont == 0 quer dizer que não existem coordenadas diferentes nesse cluster
então o infoWindow é exibido
*/
if (cont == 0) {
infowindow.setContent(imovelHTML(arr));
infowindow.open(mapa, m);
}
}
});
}
}
function definirCentroCidade(cidade){
geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': cidade + ', Brasil', 'region': 'BR'}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
lat = results[0].geometry.location.lat();
lon = results[0].geometry.location.lng();
position = new google.maps.LatLng(lat, lon);
mapa.setCenter(position);
}
}
})
}
function desenharNoMapa() {
var polyOptions = {
strokeWeight: 3,
color: "#B9005C",
strokeColor: "#118bbe",
fillColor: "#000000",
fillOpacity: 0.15,
editable: false
};
if (drawingManager == null) {
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON
]
},
polygonOptions: polyOptions
});
}
drawingManager.setMap(mapa);
google.maps.event.addListener(drawingManager, 'polygoncomplete', function (polygon) {
var pontosRegiao = polygon.getPath();
var coordenadas = '';
for (var i = 0; i < pontosRegiao.length; i++)
{
coordenadas += pontosRegiao.getAt(i).lat() + ' ' + pontosRegiao.getAt(i).lng()+';';
}
coordenadas += pontosRegiao.getAt(0).lat() + ' ' + pontosRegiao.getAt(0).lng();
drawingManager.setMap(null);
buscaImoveisDeCoordenadas(coordenadas); // funcao em buscador.js
});
}
function imovelHTML(dados) {
var html = '';
for (var i = 0; i < dados.length; i++) {
html += '' +
// '
'+
'
' +
'
' +
'
' +
'
' +
'
' +
'R$ ' + dados[i].valor +
'
' +
'
'
+ dados[i].descricao +
'
' +
'
';
}
return html;
}
function carregarVerTelefone() {
$('.b-contatar').find('#ver-telefone').on('click', function () {
$(this).addClass("ativo");
$(this).find('.texto').hide('slow');
$(this).find('.telefones').show('slow');
});
}
function ocultarTelefone() {
$('.contatar #ver-telefone').removeClass("ativo");
$('.contatar #ver-telefone').find('.texto').show();
$('.contatar #ver-telefone').find('.telefones').hide();
}
function abreModalContatar() {
$(document).on('click','.falar-agora', function () {
var telefones = '';
var idImovel = pegarIdImovel($(this)); // funcao em buscador.js
$.post("ajax-modal-falar-agora",
{'id-imovel': idImovel, 'transacao': $("#transacao").val()},
function (retorno) {
ocultarTelefone();
$('.enviar').removeAttr('disabled');
$('.modal-falar-agora .nome-imobiliaria').text(retorno.nome_imobiliaria);
$('.modal-falar-agora .mensagem').val(retorno.mensagem);
$('.modal-falar-agora #id_imovel').val(idImovel);
$('.modal-falar-agora #id_transacao').val(retorno.id_transacao);
telefones += 'Telefone: ' + retorno.telefone.split(',')[0] + '
';
if (retorno.telefone.split(',')[1] != undefined && retorno.telefone.split(',')[1] != '') {
telefones += 'Whatsapp: ' + retorno.telefone.split(',')[1].replace('*', '');
}
$('.modal-falar-agora .ver-telefone .telefones').html(telefones);
if (retorno.logo != '') {
$('.modal-falar-agora .logo-imobiliaria img').attr('src', "http://chavefacil.com.br/imagem?imagem=http://chavefacil.com.br/site/imagens/logos/imobiliarias/" + retorno.id_imobiliaria + ".jpg,w=123");
$('.modal-falar-agora .logo-imobiliaria').removeClass('dNone');
} else {
$('.modal-falar-agora .logo-imobiliaria').addClass('dNone');
}
$('#modal-falar-agora').modal();
}
);
});
}