Scriptcaser
gmaps

Integrando o Google Maps em um Form [Parte 2]

Continuando o post anterior, a partir de agora iremos botar a mão na massa dentro do scriptcase.

Incorporando o Google Maps no formulário do scriptcase

Espero que a essa altura você já tenha criado uma aplicação formulário no scriptcase, então abra a aplicação e crie um campo personalizado em Campos > Novo Campo do tipo texto.

Abra o campo criado (no meu caso criei o campo map) e marque a opção de Campo Label.

No campos latitude e longitude marque a opção para esconder o campo (é importante que se marque para esconder o campo e não remover o campo da visualização em editar campos)

Agora no evento onLoad carregue o boilerplate do mapa.

<div class="pac-card" id="pac-card">
    <div>
        <div id="title">Buscar Local</div>
        <div id="type-selector" class="pac-controls">
            <input type="radio" name="type" id="changetype-all" checked="checked">
            <label for="changetype-all">Todos</label>
            <input type="radio" name="type" id="changetype-establishment">
            <label for="changetype-establishment">Estabelecimentos</label>
            <input type="radio" name="type" id="changetype-address">
            <label for="changetype-address">Endereços</label>
            <input type="radio" name="type" id="changetype-geocode">
            <label for="changetype-geocode">Geocodes</label>
        </div>
        <div id="strict-bounds-selector" class="pac-controls">
            <input type="checkbox" id="use-strict-bounds" value="">
            <label for="use-strict-bounds">Strict Bounds</label>
        </div>
    </div>
    <div id="pac-container">
        <input id="pac-input" type="text" placeholder="Insira a localização">
    </div>
</div>
<div id="map"></div>
<div id="infowindow-content">
    <img src="" width="16" height="16" id="place-icon"><span id="place-name" class="title"></span>
    <br><span id="place-address"></span>
</div>

Nesse caso é melhor criar um arquivo php em bibliotecas externa e fazer uma chamada php usando o file_get_contents ficando assim:

// init map field
{map} = file_get_contents(sc_url_library("prj", "assets", "boilerplate/map/map.php"));

É importante minificar o arquivo antes de salvar, pois por algum motivo no scriptcase o file_get_contents não aceita se ele não estiver minificado.

No evento onScriptInit carregue o arquivo css do mapa no scriptcase (para o código ficar mais organizado e aproveitar o seu reuso, crie um arquivo css map-custom.css em bibliotecas externas e use a macro sc_url_libary para carregar o css.

/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
	height: 400px;
	width: 100%;
}

#description {
	font-family: Roboto;
	font-size: 15px;
	font-weight: 300;
}

#infowindow-content .title {
	font-weight: bold;
}

#infowindow-content {
	display: none;
}

#map #infowindow-content {
	display: inline;
}

.pac-card {
	margin: 10px 10px 0 0;
	border-radius: 2px 0 0 2px;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	outline: none;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
	background-color: #fff;
	font-family: Roboto;
}

#pac-container {
	padding-bottom: 12px;
	margin-right: 12px;
	display: flex;
}

.pac-controls {
	display: inline-block;
	padding: 5px 11px;
}

.pac-controls label {
	font-family: Roboto;
	font-size: 13px;
	font-weight: 300;
}

#pac-input {
	background-color: #fff;
	font-family: Roboto;
	font-size: 15px;
	font-weight: 300;
	margin-left: 12px;
	padding: 0 11px 0 13px;
	text-overflow: ellipsis;
	width: 100%;
	border: 1px solid #DDDDDD;
	-webkit-transition: all 0.30s ease-in-out;
	-moz-transition: all 0.30s ease-in-out;
	-ms-transition: all 0.30s ease-in-out;
	-o-transition: all 0.30s ease-in-out;
	outline: none;
}

#pac-input:focus {
	box-shadow: 0 0 5px rgba(81, 203, 238, 1);
	margin-left: 12px;
	padding: 0 11px 0 13px;
	border: 1px solid rgba(81, 203, 238, 1);
}

#title {
	color: #fff;
	background-color: #4d90fe;
	font-size: 25px;
	font-weight: 500;
	padding: 6px 12px;
}

Carregue o API Google Maps no evento onScriptInit

<!-- API Google Maps V3 -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<?php echo getConfig('geral_gmaps_api'); ?>&libraries=places"></script>

Onde você vê <?php echo getConfig('geral_maps_api'); ?> é onde você deverá colocar a Chave API gerada. No caso do meu sistema essa chave é gravada em uma tabela de configuração e capturada automaticamente pela função getConfig, que é assunto para outro post.

Obs: Não esqueça de habilitar a diretiva places na sua API do Google Maps

Para popular os campos automaticamente teremos que passar os seus respectivos ids para manipular os elementos do DOM.

Note que o id dos campos no scriptcase segue um padrão, todos tem o prefixo #id_sc_field_, logo se o campo é conveniadoCep o id ficará #id_sc_field_conveniadocep (note que o id é gerado em lower case).

Em bibliotecas externas crie o arquivo map.js e cole o seguinte código:

// globals variables
var map, geocoder, marker, autocomplete, props = {};

/**
 *  Inicializa o mapa
 */

function initMap(_arr){
	
	for (var prop in _arr) {
		props[prop] = document.querySelector(_arr[prop]);	
	}
	
	/**
	 * 	Caso latitude e longitude não sejam passados por parâmetro
	 * 	é carregado o padrão "Praça Almeida Couto - Nazaré"
	 */

	props.lat.value = props.lat.value != '' ? props.lat.value : -12.9730401;
	props.lng.value = props.lng.value != '' ? props.lng.value : -38.50230399999998;
	
	var latlng = new google.maps.LatLng(props.lat.value, props.lng.value),
		options = {
		zoom: 14,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	
	map = new google.maps.Map(document.querySelector('#map'), options);
	geocoder = new google.maps.Geocoder();
	
	marker = new google.maps.Marker({
		map: map,
		draggable: true,
	});
	
	marker.setPosition(latlng);
	
	var card = document.querySelector('#pac-card');
	var input = document.querySelector('#pac-input');
    var types = document.querySelector('#type-selector');
    var strictBounds = document.querySelector('#strict-bounds-selector');

    map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
	
    autocomplete = new google.maps.places.Autocomplete(input);

	
	// Bind the map's bounds (viewport) property to the autocomplete object,
    // so that the autocomplete requests use the current map bounds for the
    // bounds option in the request.
	autocomplete.bindTo('bounds', map);

	// Set the data fields to return when the user selects a place.
	autocomplete.setFields(['address_components', 'geometry']);
	
	autocomplete.addListener('place_changed', function() {
		var place = autocomplete.getPlace();
		if (!place.geometry) {
			// User entered the name of a Place that was not suggested and
			// pressed the Enter key, or the Place Details request failed.
			window.alert("Nenhuma informação disponível para o local pesquisado: '" + place.name + "'");
			return;
		}

		// If the place has a geometry, then present it on a map.
		if (place.geometry.viewport) {
			map.fitBounds(place.geometry.viewport);
		} else {
			map.setCenter(place.geometry.location);
		}
		
		marker.setPosition(place.geometry.location);

		if (place) {
			//console.log(place.address_components)
			var dados = retornaDados(place.address_components);

			dados.lat = place.geometry.location.lat();
			dados.lng = place.geometry.location.lng();
			
			popularCampos(dados);
		}
	});
	
	setupClickListener('#changetype-all', []);
	setupClickListener('#changetype-address', ['address']);
	setupClickListener('#changetype-establishment', ['establishment']);
	setupClickListener('#changetype-geocode', ['geocode']);

	document.querySelector('#use-strict-bounds')
	.addEventListener('click', function() {
		console.log('Checkbox clicked! New state=' + this.checked);
		autocomplete.setOptions({strictBounds: this.checked});
	});
	
	google.maps.event.addListener(marker, 'dragend', function() {
		geocodePosition(marker.getPosition());
		map.panTo(marker.getPosition());
	});
}

// populate form fields
function popularCampos(dados) {
	props.cep.value = typeof dados.cep === 'undefined' ? "" : dados.cep;
	props.estado.value = typeof dados.estado === 'undefined' ? "" : dados.estado;
	props.cidade.value = typeof dados.cidade === 'undefined' ? "" : dados.cidade;
	props.bairro.value = typeof dados.bairro === 'undefined' ? "" : dados.bairro;
	props.logradouro.value = typeof dados.logradouro === 'undefined' ? "" : dados.logradouro;
	props.numero.value = typeof dados.numero === 'undefined' ? "" : dados.numero;
	
	props.lat.value = dados.lat;
	props.lng.value = dados.lng;
}

// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
	var radioButton = document.querySelector(id);
	radioButton.addEventListener('click', function() {
		autocomplete.setTypes(types);
	});
}

/**
 * Método utilizado para traduzir os dados do geocode
 * para um array associativo
 */

function retornaDados(matriz) {
	
    let dados = {};

    for (var i in matriz) {
        switch (matriz[i].types[0]) {
            case 'postal_code':
                dados.cep = matriz[i].long_name;
                console.log('CEP: ', dados.cep);
                break;
             case 'political':
                dados.bairro = matriz[i].long_name;
                console.log('Bairro: ', dados.bairro);
                break;
            case 'street_number':
                dados.numero = matriz[i].short_name;
                console.log('Numero: ', dados.numero);
                break;
            case 'administrative_area_level_1':
                dados.estado = matriz[i].short_name;
                console.log('UF: ', dados.estado);
                break;
            case 'administrative_area_level_2':
                dados.cidade = matriz[i].long_name;
                console.log('Cidade: ', dados.cidade);
                break;
            case 'route':
                dados.logradouro = matriz[i].long_name;
                console.log('Logradouro: ', dados.logradouro);
                break;
        }
    }

    return dados;
}

/**
 * Setar marcador em tempo de execução
 * para chamadas dentro da aplicação
 */

function setMarker(lat, lng) {
	let location = new google.maps.LatLng(lat, lng);
	marker.setPosition(location);
	map.setCenter(location);
	map.setZoom(17);
}

/**
 * Capturar endereço da posição do marcador ao arrastar
 */

function geocodePosition(pos) {
	geocoder.geocode({ latLng: pos }, function(results, status) {
		if (status === 'OK') {
			let dados = retornaDados(results[0].address_components);
			
			dados.lat = pos.lat();
			dados.lng = pos.lng();
			
			popularCampos(dados);
		} else {
			alert('Não conseguimos determinar o endereço a partir dessa localização.');
			return;
		}
	});
}

Pensou que eu ia exibir todo o código sem explicar? Calma, irei comentar trecho por trecho.

A primeira coisa a fazer é criar as variáveis globais, pois elas poderão ser acessadas em qualquer função.

// globals variables
var map, geocoder, marker, autocomplete, props = {};
Note que a global props é um objeto e armazenará os campos do scriptcase.

A função populaCampos é que faz a mágica acontecer, é quando o resultado da consulta no mapa é validado e popula os campos do scriptcase.

// populate form fields
function popularCampos(dados) {
	props.cep.value = typeof dados.cep === 'undefined' ? "" : dados.cep;
	props.estado.value = typeof dados.estado === 'undefined' ? "" : dados.estado;
	props.cidade.value = typeof dados.cidade === 'undefined' ? "" : dados.cidade;
	props.bairro.value = typeof dados.bairro === 'undefined' ? "" : dados.bairro;
	props.logradouro.value = typeof dados.logradouro === 'undefined' ? "" : dados.logradouro;
	props.numero.value = typeof dados.numero === 'undefined' ? "" : dados.numero;
	
	props.lat.value = dados.lat;
	props.lng.value = dados.lng;
}
Todos esse props fazem referência aos campos no formulário no scriptcase, como por exemplo props.cep é referência do campo conveniadoCep, e o atributo value é utilizado quando você quer atribuir um valor ao campo do tipo input.

A função retornaDados é responsável por receber os dados do mapa , traduzir as informações e retornar como um objeto que faça mais sentido para o programador.

/**
 * Método utilizado para traduzir os dados do geocode
 * para um array associativo
 */

function retornaDados(matriz) {
	
    let dados = {};

    for (var i in matriz) {
        switch (matriz[i].types[0]) {
            case 'postal_code':
                dados.cep = matriz[i].long_name;
                console.log('CEP: ', dados.cep);
                break;
             case 'political':
                dados.bairro = matriz[i].long_name;
                console.log('Bairro: ', dados.bairro);
                break;
            case 'street_number':
                dados.numero = matriz[i].short_name;
                console.log('Numero: ', dados.numero);
                break;
            case 'administrative_area_level_1':
                dados.estado = matriz[i].short_name;
                console.log('UF: ', dados.estado);
                break;
            case 'administrative_area_level_2':
                dados.cidade = matriz[i].long_name;
                console.log('Cidade: ', dados.cidade);
                break;
            case 'route':
                dados.logradouro = matriz[i].long_name;
                console.log('Logradouro: ', dados.logradouro);
                break;
        }
    }

    return dados;
}
Note que poderia ser feito direto usando a global props ao invés de dados em parâmetro de retorno, porém  já aconteceu do google maps mudar os atributos dos dados retornados e separar as duas funções a me ajudou a depurar mais facilmente.

Como você pode observar no gif animado do posto anterior, o script tem duas funções de captura de endereço, uma é digitando na barra de endereços do mapa e a outra é arrastando o marcador. Quando arrastamos o marcador é necessário obter os dados de endereço a partir das coordenadas geográficas, e para fazer esse movimento inverso criei a função geocodePosition.

/**
 * Capturar endereço da posição do marcador ao arrastar
 */

function geocodePosition(pos) {
	geocoder.geocode({ latLng: pos }, function(results, status) {
		if (status === 'OK') {
			let dados = retornaDados(results[0].address_components);
			
			dados.lat = pos.lat();
			dados.lng = pos.lng();
			
			popularCampos(dados);
		} else {
			alert('Não conseguimos determinar o endereço a partir dessa localização.');
			return;
		}
	});
}

A função setMarker tem como objetivo setar a posição no mapa quando o endereço é digitado

/**
 * Setar marcador em tempo de execução
 * para chamadas dentro da aplicação
 */

function setMarker(lat, lng) {
	let location = new google.maps.LatLng(lat, lng);
	marker.setPosition(location);
	map.setCenter(location);
	map.setZoom(17);
}

A função setupClickListener restringe a consulta a um subgrupo de POI’s como Estabelecimentos, Endereços e Geocodes.

// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
	var radioButton = document.querySelector(id);
	radioButton.addEventListener('click', function() {
		autocomplete.setTypes(types);
	});
}

E for a função initMap, onde o mapa é inicializado.

function initMap(_arr){
	
	for (var prop in _arr) {
		props[prop] = document.querySelector(_arr[prop]);	
	}
	
	/**
	 * 	Caso latitude e longitude não sejam passados por parâmetro
	 * 	é carregado o padrão "Praça Almeida Couto - Nazaré"
	 */

	props.lat.value = props.lat.value != '' ? props.lat.value : -12.9730401;
	props.lng.value = props.lng.value != '' ? props.lng.value : -38.50230399999998;
	
	var latlng = new google.maps.LatLng(props.lat.value, props.lng.value),
		options = {
		zoom: 14,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	
	map = new google.maps.Map(document.querySelector('#map'), options);
	geocoder = new google.maps.Geocoder();
	
	marker = new google.maps.Marker({
		map: map,
		draggable: true,
	});
	
	marker.setPosition(latlng);
	
	var card = document.querySelector('#pac-card');
	var input = document.querySelector('#pac-input');
        var types = document.querySelector('#type-selector');
        var strictBounds = document.querySelector('#strict-bounds-selector');

    map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
	
    autocomplete = new google.maps.places.Autocomplete(input);

	
    // Bind the map's bounds (viewport) property to the autocomplete object,
    // so that the autocomplete requests use the current map bounds for the
    // bounds option in the request.
	autocomplete.bindTo('bounds', map);

	// Set the data fields to return when the user selects a place.
	autocomplete.setFields(['address_components', 'geometry']);
	
	autocomplete.addListener('place_changed', function() {
		var place = autocomplete.getPlace();
		if (!place.geometry) {
			// User entered the name of a Place that was not suggested and
			// pressed the Enter key, or the Place Details request failed.
			window.alert("Nenhuma informação disponível para o local pesquisado: '" + place.name + "'");
			return;
		}

		// If the place has a geometry, then present it on a map.
		if (place.geometry.viewport) {
			map.fitBounds(place.geometry.viewport);
		} else {
			map.setCenter(place.geometry.location);
		}
		
		marker.setPosition(place.geometry.location);

		if (place) {
			//console.log(place.address_components)
			var dados = retornaDados(place.address_components);

			dados.lat = place.geometry.location.lat();
			dados.lng = place.geometry.location.lng();
			
			popularCampos(dados);
		}
	});
	
	setupClickListener('#changetype-all', []);
	setupClickListener('#changetype-address', ['address']);
	setupClickListener('#changetype-establishment', ['establishment']);
	setupClickListener('#changetype-geocode', ['geocode']);

	document.querySelector('#use-strict-bounds')
	.addEventListener('click', function() {
		console.log('Checkbox clicked! New state=' + this.checked);
		autocomplete.setOptions({strictBounds: this.checked});
	});
	
	google.maps.event.addListener(marker, 'dragend', function() {
		geocodePosition(marker.getPosition());
		map.panTo(marker.getPosition());
	});
}

Alguns comentários precisam ser feitos sobre a função initMap

for (var prop in _arr) {
    props[prop] = document.querySelector(_arr[prop]);   
}

Na iteração acima é onde os ids dos elementos do DOM são passados por parâmetro e incluídos como atributos no objeto props através do document.querySelector() (na inicialização da função initMap fica mais claro).

/**
  * 	Caso latitude e longitude não sejam passados por parâmetro
  * 	é carregado o padrão "Praça Almeida Couto - Nazaré"
  */

	props.lat.value = props.lat.value != '' ? props.lat.value : -12.9730401;
	props.lng.value = props.lng.value != '' ? props.lng.value : -38.50230399999998;

Se houver algum valor nos campos latitude e longitude (aplicação no modo atualização), então as coordenadas armazenadas no banco de dados são carregadas no mapa, caso contrário o marcador é definido pelas coordenadas -12.9730401 e -38.50230399999998 (mude essa localização como desejar, de preferência para a região central de sua cidade).

var latlng = new google.maps.LatLng(props.lat.value, props.lng.value),
    options = {
	zoom: 14,
	center: latlng,
	mapTypeId: google.maps.MapTypeId.ROADMAP
    };
	
map = new google.maps.Map(document.querySelector('#map'), options);
geocoder = new google.maps.Geocoder();
	
marker = new google.maps.Marker({
    map: map,
    draggable: true,
});

marker.setPosition(latlng);
  1. É criado um objeto do tipo google.maps.LatLng com as coordenadas obtidas e armazenadas na variável latlng
  2. Definidas opções de inicialização do mapa na variável options.
  3. O mapa é carregado dentro da div #map e armazenado um objeto do tipo mapa na variável map
  4. Instanciado objeto Geocoder na variável geocoder
  5. Instanciado objeto Marker na variável marker
  6. Seta a posição inicial do marcador passando o objeto latlng como parâmetro
var card = document.querySelector('#pac-card');
var input = document.querySelector('#pac-input');
var types = document.querySelector('#type-selector');
var strictBounds = document.querySelector('#strict-bounds-selector');

map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

Anexando a caixa de diálogo no canto superior esquerdo do mapa.

autocomplete = new google.maps.places.Autocomplete(input);

// Bind the map's bounds (viewport) property to the autocomplete object,
// so that the autocomplete requests use the current map bounds for the
// bounds option in the request.
autocomplete.bindTo('bounds', map);

// Set the data fields to return when the user selects a place.
autocomplete.setFields(['address_components', 'geometry']);
	
autocomplete.addListener('place_changed', function() {
    var place = autocomplete.getPlace();
    if (!place.geometry) {
	// User entered the name of a Place that was not suggested and
	// pressed the Enter key, or the Place Details request failed.
	window.alert("Nenhuma informação disponível para o local pesquisado: '" + place.name + "'");
	return;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
	map.fitBounds(place.geometry.viewport);
    } else {
        map.setCenter(place.geometry.location);
    }
		
    marker.setPosition(place.geometry.location);

    if (place) {
        //console.log(place.address_components)
	var dados = retornaDados(place.address_components);

	dados.lat = place.geometry.location.lat();
	dados.lng = place.geometry.location.lng();
			
	popularCampos(dados);
   }
});
  1. Instancia um objeto do tipo google.maps.places.Autocomplete passando o input como parâmetro.
  2. Adiciona um eventListener ao input autocomplete do tipo place_changed, fazendo com que toda vez que o selecione um novo registro na barra de endereços o marcador com a nova localização seja exibida no mapa
  3. Se existe o local pesquisado, então é executada a função retornaDados passando o atributo address_components do objeto place para traduzir o endereço e gravar nos campos do formulário.
setupClickListener('#changetype-all', []);
setupClickListener('#changetype-address', ['address']);
setupClickListener('#changetype-establishment', ['establishment']);
setupClickListener('#changetype-geocode', ['geocode']);

Adiciona eventListeners de clique elementos de filtro da barra de busca.

document.querySelector('#use-strict-bounds')
    .addEventListener('click', function() {
        console.log('Checkbox clicked! New state=' + this.checked);
        autocomplete.setOptions({strictBounds: this.checked});
    });

Adiciona um eventListener de clique no checkbox #use-strict-bounds. Ao marcar esse checkbox as pesquisas ficarão restritas aos limites da cidade definida pelo marcador na inicialização.

google.maps.event.addListener(marker, 'dragend', function() {
    geocodePosition(marker.getPosition());
    map.panTo(marker.getPosition());
});

Adiciona um eventListener do tipo dragend ao objeto marker (evento exclusivo do Google Maps). Ao soltar o botão esquerdo do mouse depois de arrastar o marcador, a função geocodePosition é executada o endereço é capturado a partir da coordenada definida.

Agora vamos para o grand finale! Fazer com que o mapa abre na aplicação do scriptcase. No evento onLoad adicione execute a função initMap passando um array com a referência dos ids do DOM dos campos que você deseja popular ao manipular o mapa.

<script type="text/javascript">
	$(document).ready(function() {
		let fields = {
			'cep': '#id_sc_field_conveniadocep',
			'numero': '#id_sc_field_conveniadonumero',
			'estado': '#id_sc_field_conveniadouf',
			'cidade': '#id_sc_field_conveniadocidade',
			'bairro': '#id_sc_field_conveniadobairro',
			'logradouro': '#id_sc_field_conveniadologradouro',
			'lat': '#id_sc_field_conveniadolat',
			'lng': '#id_sc_field_conveniadolng'
		};
		
		// Inicializar o mapa
		initMap(fields);
	});
</script>
Substitua os #id_sc_field_ pelos nomes que você deu aos seus campos.

Ao final, o seu mapa deverá estar funcionando adequadamente como no gif abaixo.

Gostou? Então comente, se inscreva na minha newsletter e saiba assim que novos posts saírem do forno.

scriptcaser

18 comments

  • Muito informativo. Eu porém preciso de algo bem mais simples. Como sou iniciante na ferramenta, tenho dificuldade com muito código.
    Criei um campo tipo google maps e coloquei para geocode, coloquei a api, no bd tem os campos: endereço, bairro, cidade, estado, país e cep.
    Ainda assim, o mapa abre em branco.
    Chequei a api, está ativada e liberada para o uso…fiquei sem ideias…poderia me dar alguma luz a esse respeito?

    • Olá Wagner! Quando necessitei utilizar mapas na minha aplicação percebi que o campo do tipo mapa do scriptcase não iria me satisfazer. Partindo do que sei sobre o Google Maps, a primeira coisa que você deverá fazer é gerar sua Chave API no Google Developers Console; depois que você gerar a chave deverá configurá-la, habilitar os módulos que você quer utilizar da API e testar novamente.

  • Hi 🙂

    Do you have a project with this I can download so I can studied? I am very rusted on developing 🙁

    Greeting from Costa Rica

  • Olá, excelente tutorial.
    Bem explicado e nos detalhes.
    Gostaria de tirar algumas dúvidas:
    1. é possível desenvolver isso no formulário (google forms), aqueles usados para pesquisa, etc.?
    2. se sim, seria o mesmo método descrito por você no conteúdo deste post?

    • Infelizmente eu nunca testei mapas no GForms, mas tenho que certeza que mesmo que exista a possibilidade de usar mapas no GForms, muito provavelmente esse código não será compatível.

  • Hi Alexandre Martins, Thank you very much for sharing this topic. I come from Indonesia. I have tried it step by step, but when moving pointing maps it can’t and the message “Address not found” always appears. Maybe you are willing to try to enter the address “Jalan Bakti No.20 Latambaga” Thank you

    • Hi Jalan, the time i did this it was working in scriptcase. It happens that this code needs adjustments to work in scriptcaser newer versions.

  • hai scriptcaser…. i was try step by step… but on draw pointing maps, the field value cannot change…what wrong? can you help me…thanks…

  • Excellent but it doesn’t work for 9.6.005 I’m with this version and your project is just what I need, but I couldn’t get it to work. A shame!

    • Hi Daniel,

      This code may need some changes to run in scriptcaser newer versions. But, in this moment, i can’t do cause i’m in a project.

      • I understand … a shame because your project does exactly what I need in the form, I have been looking for a long time and without success. I’ll have to keep testing to see if I can do something like that.
        Thank you for answering, if possible could you share the module, the table and the external libraries by exporting them as a project? It would be helpful, maybe something is wrong in the tutorial, as I find several different things. Greetings and thank you very much!

  • I really need to implement it but it doesn’t work for me, I follow everything step by step but it gives me errors, could you upload the project with the external libraries please? it would be a great contribution !!!
    Greetings

      • No script de criação da tabela, os campos são em estilo camelo: concordadoCep, mas mais adiante no artigo diz que eles não devem ser capitalizados. Eu fiz o minificador do css e js também testei sem usar o minificador nos arquivos da biblioteca externa, mas também não tive sucesso. Na chamada de map.php também não
        // campo do mapa de inicialização
        {map} = file_get_contents (sc_url_library (“prj”, “ativos”, “boilerplate / map / map.php”));
        Eu tentei várias variantes de caminho sem sucesso, mas se eu colocar o código map.php completo no onLoad ele funciona bem, embora o css não funcione, tentei integrá-lo como uma biblioteca interna também sem sucesso.

        Então, na chamada .js:
        // preencher os campos do formulário
        function popularFields (dice) {
        props.cep.value = typeof dice.cep === ‘indefinido’? “”: dice.cep;

        dados? a mesa tem um namecep acordado. Não entendo por que o script base tem um nome e outros no js.

        Você poderia fazer a gentileza de compartilhar o projeto, a mesa e as bibliotecas externas apenas dessa mesa?
        Muito obrigado!

  • In the table creation script, the fields are in camel style: agreedCep, but later on in the article it says that they should not be capitalized. I made the minifier from the css and js also tested without using the minifier on the external library files, but I was not successful either. In the call of map.php neither does it
    // init map field
    {map} = file_get_contents (sc_url_library (“prj”, “assets”, “boilerplate / map / map.php”));
    I tried several path variants without success, but if I put the complete map.php code in the onLoad it works fine, although the css doesn’t, I tried integrating it as an internal library also without success.

    Then in the .js call:
    // populate form fields
    function popularCampos(dados) {
    props.cep.value = typeof dados.cep === ‘undefined’ ? “” : dados.cep;

    dices? the table has an agreed namecep. I don’t understand why the base script has one name and others in the js.

    Would you be so kind to share the project, the table and the external libraries of only that table please?
    Thanks a lot!

Newsletter

Se inscreva na nossa newsletter
Se increva hoje na nossa lista de e-mail para receber atualizações, tutoriais e ofertas especiais!

Respeitarei sua privacidade. Seu e-mail nunca será compartilhado.