|  | Форум больше не используется. Присоединяйтесь к каналу #community-ru в Slack for TYPO3 community | 
|  25.04.2016, 17:18 | #1 | 
| Senior Member Регистрация: 26.10.2007 
					Сообщений: 108
				 |  GEOPicker(Typo3-7, FLUID, PHP, JS) 
			
			Приветствую коллеги! Пишу сейчас очень большой проект с кучей ништяков и приходится дописывать кучу плагинов своих и модулей и т.д. для typo3 7.6 (на версиях ниже не проверял и не хочу). Возникла задача написать Гео пикер, т.е. нужно с гугла вытаскивать адрес, город, страну и лат\лонг. Есть решения типа экста geopicker, но он делает во всплывающем окошке, что выглядит старомодно, да и нет там нужных мне полей. И так модуль я написал, без окошка но в модальном окне!  Так что кому будет полезно или интересно, прошу читать далее. Итак поехали: 1. создаем FrontEnd plagin (я пользую kickstarter, лени ради). Можно конечно не ФронтЭнд, а сервис.. sic! ext_tables.php и контроллер, модели и репозитории нам ненужны. так что структура у нас такая: Код: Classes -Form --Element ---GeoPickerElement.php // рендерим конфиг для нового элемента --Wizard ---GeoPickerWizard.php // Wizard для нового элемента -Utility --ExtConfiguration.php // Это мой хитрый файл для сбора всех конфигов, опишу ниже может пригодится. Configuration -Backend --AjaxRoutes.php // добавляем ajax handler Resources -Private --Language ---locallang.xlf --Templates ---GeoPickerWizard.html -Public --Css ---geopicker.css --Icons ---icon-blue.png (я использую не дефотный маркер) --JavaScript ---GeoPosition.js ext_icon.gif ext_emconf.php ext_localconf.php ext_conf_template.txt PHP код: 
			Тут все как обычно 1.3 ext_conf_template.txt Настройки плагина, Google MAP API Key (для JS API), дефлотная широта и долгота испоьзуем при инициаизации карты Код: # cat=basic; type=string; label=Google Developers KEY googleKey = # cat=basic; type=string; label=Default Latitude default_lat = # cat=basic; type=string; label=Default Longitude default_long = Тут будем рендерить наш новый элемент GEOPICKER PHP код: 
			Важно! ни каких AjaxHandler, мы юзаем use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; Тут надеюсь все более менее понятно, комментировать особо нечего. PHP код: 
			1.6 Classes\Utility\ExtConfiguration.php Кокретно в этом плагине весь функционал файла неиспоьзуется, но приведу целиком, может быдет полезен. Использую его в основном для вставки полей из ext_template_conf в TCA (например root category uid) или во вспомагательных скриптах для доступа к настройкам плагина. PHP код: 
			Прописываем ajax handler PHP код: 
			Так с северной частью закончили, осталось Language, CSS, Template и JS Забираем их (кроме JS, его напишем) locallang.xlf GeoPickerWizard.html geopicker.css icon-blue.png 1.8 \Resources\Public\JavaScript\GeoPosition.js Заключительная часть кордебалета! Сразу скажу, не занимался ювелирным кодингом на JS...Если сможите написать лучше! Бог в помощь и барабан на шею   Код:  /**
 * Module: ER/ErGeopicker
 * Contains all logic for the googlemap API
 */
define(['jquery', 'TYPO3/CMS/Backend/Modal'], function ($, Modal) {
	/**
	 *
	 * @exports ER/ErGeopicker 
	 */
	var GeoPosition = {
		$trigger: null,
		zoom: 12,
		$map: null,
		$pos:null,
		$image:null,
		latitude:null,
		longitude:null,
		address: null,
		city: null,
		country:null,
		$marker:[],
		$geocoder:null
	};
	Тут у меня микс глобальных и полуглобальных и вообще хз каких переменных. Чтоб были.
	GeoPosition.initializeTrigger = function(lat, long){
		GeoPosition.$pos = { lat: lat, lng: long }; // Дефолтные широта и долгота.. 
		var $triggers = $('.t3js-geopicker-trigger');
		// Remove existing bind function
		$triggers.off('click',  GeoPosition.buttonClick);
		// Bind new function
		$triggers.on('click', GeoPosition.buttonClick);
	}
	// кликалка с защитой от даблклика
	GeoPosition.buttonClick = function(e) {
		e.preventDefault();
		// Prevent double trigger
		if (GeoPosition.$trigger !== $(this)) {
			GeoPosition.$trigger = $(this);
			GeoPosition.show();
		}
	};
	// открываем модальное окошко
	GeoPosition.show = function() {
		GeoPosition.currentModal = Modal.loadUrl(
			GeoPosition.$trigger.data('title'),
			TYPO3.Severity.notice,
			[],
			GeoPosition.$trigger.data('url'),
			GeoPosition.showMap,
			'.modal-content'
		);
		var modalWidth = $(window).width();
		GeoPosition.currentModal.addClass('modal-dark');
		GeoPosition.currentModal.find('.modal-dialog')
			.addClass('modal-geopicker modal-resize')
			.css({width: modalWidth});
		GeoPosition.currentModal.find('.modal-content').css({marginTop:50});
		setTimeout(function() {
			var sidebarWidth = GeoPosition.currentModal.find('.modal-panel-sidebar').outerWidth();
			var bodyWidth = modalWidth-sidebarWidth-2;
			GeoPosition.currentModal.find('.modal-panel-body').css({width:bodyWidth});
		}, 500);
		// Т.к. открытие и погрузка шаблона требует некоторого времени, то лучше все действия делать с небольшой задержкой. 
	};
	//после открытия окна, callback'ом вызываем карту, опять же с задержкой.. без задержки бывает google скрипт не успевает прогружатся.. но это на локальном хосте. 
	GeoPosition.showMap = function(){
		setTimeout(function() {
			GeoPosition.initializeMap();
		}, 300);
	};
	// собственно сама карта, я делал без стилей и т.д. чисто карта как есть.
	GeoPosition.initializeMap = function(){
        $map = new google.maps.Map(GeoPosition.currentModal.find('.gmap')[0], {
		    center: GeoPosition.$pos,
		    zoom: GeoPosition.zoom
		  });
        $geocoder = new google.maps.Geocoder(); // Важно, ваш АПИ код должен быть активирован для использования geocodera
        //  наш не дефолтный маркер
        GeoPosition.$image = {
				// This marker is 64 pixels wide by 64 pixels high.
			    size: new google.maps.Size(64, 64),
			    // The origin for this image is (0, 0).
			    origin: new google.maps.Point(0, 0),
			    // The anchor for this image is the base of the flagpole at (0, 32).
			    anchor: new google.maps.Point(24, 48),
			    scaledSize: new google.maps.Size(48, 48),
			    url: '../typo3conf/ext/er_geopicker/Resources/Public/Icons/map-icons/icon-blue.png',
		}
		// определяем текущее положение пользователя.
		if (navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(
                function( position ){
                   	GeoPosition.$pos = {
				        lat: position.coords.latitude,
				        lng: position.coords.longitude
				    }   
					GeoPosition.findByLatLng(GeoPosition.$pos);
                }
            )
        }
        // Инпут с поиском по адресу, ищем по клику
	  	GeoPosition.currentModal.find('#submit').on('click', function(e){
	  		var address = GeoPosition.currentModal.find('#gsearch').val();
	  		GeoPosition.findByAdress(address);
	  		return false;
	  	});
	  	// Инициализируем Сохранить и Закрыть 
	  	GeoPosition.initializeActions();
	};
	// поиск по адресу
	GeoPosition.findByAdress = function (address) {
		var componentRestrictions = {}; // тут можно вписать ограничения по региону и т.д.
		$geocoder.geocode({'address': address, 'componentRestrictions': componentRestrictions}, function(results, status) {
		    if (status === google.maps.GeocoderStatus.OK) {
		      	$map.setCenter(results[0].geometry.location);
		      	GeoPosition.addMarker(results[0].geometry.location);
		      	GeoPosition.setresult(results);
		    } else {
		      	console.log(status);
		    }
		});
    };
    // поиск по координатам
    GeoPosition.findByLatLng = function(pos){
    	var componentRestrictions = {};
    	$geocoder.geocode({'location': pos, 'componentRestrictions': componentRestrictions}, function(results, status) {
    		if (status === google.maps.GeocoderStatus.OK) {
    			GeoPosition.addMarker(pos);
    			GeoPosition.setresult(results);
    		} else {
		      	console.log(status);
		    }
    	})
    };
    // Создаем маркер, т.к. маркер всегда один на карте то перед созданием обнуляем маркеры на карте и в массиве
     GeoPosition.addMarker = function(position){
    	GeoPosition.setMarkers(null);
		var marker = new google.maps.Marker({
		    map: $map,
		    position: position,
		    icon: GeoPosition.$image,
			draggable: true,
			animation: google.maps.Animation.DROP,
			title: GeoPosition.$trigger.data('title')
		});
		GeoPosition.$marker.push(marker);
		GeoPosition.setMarkers($map);
    };
    //вставляем маркер на карту если map==null то убираем все что есть
    GeoPosition.setMarkers = function(map){
    	for (var i = 0; i < GeoPosition.$marker.length; i++) {
		    GeoPosition.$marker[i].setMap(map);
		    GeoPosition.listner(GeoPosition.$marker[i]);
		}
		if(!map)
			GeoPosition.$marker=[];
    };
    // добавляем слушателей на карту и маркер check - нужен что бы убрать даблклики и т.д. т.к. у гугл есть лимит на обращения к geocoder и не только.
    GeoPosition.listner = function(marker){
    	var check = true;
    	google.maps.event.addListener(marker, 'dragend', function (results) {
    		
    		if(check){
    		 	GeoPosition.findByLatLng(marker.getPosition());
    		 	check = false;
    		}
    		setTimeout(function() {
    			check = true;
    		}, 10000);
             
        });
    	$map.addListener('click', function(event) {
		   if(check){
    		 	GeoPosition.findByLatLng(event.latLng);
    		 	check = false;
    		}
    		setTimeout(function() {
    			check = true;
    		}, 10000);
		});
    };
    // Из гугловского ответа выбираем только город, страну и адрес. Детали и параметры ответа можно узнать у гугла детальнее.
    GeoPosition.setresult = function(results){
    	// default field: country, city, latitude, lonitude, address
    	var modal = GeoPosition.currentModal;
    	var checkLocality = true;
    	var checkRoute = true;
		$.each(results, function(i, val){
			$.each(val['types'], function(k,type){
				if(type === 'locality') {
					if(checkLocality) {
						GeoPosition.city = val.address_components[0].long_name;
						GeoPosition.country = val.address_components[val.address_components.length-1].long_name;
					}
					checkLocality = false;
				}
				if(type === 'route') {
					if(checkRoute) {
						GeoPosition.address = val.formatted_address;
					}
					checkRoute = false;
				}
				
			});
		});
                if(checkRoute)
			GeoPosition.address = ''; // бывает адреса и нет... 
		GeoPosition.latitude = results[0].geometry.location.lat();
		GeoPosition.longitude = results[0].geometry.location.lng();
    	modal.find('#city').text(GeoPosition.city);
    	modal.find('#country').text(GeoPosition.country);
    	modal.find('#longitude').text(GeoPosition.longitude);
    	modal.find('#latitude').text(GeoPosition.latitude);
    	modal.find('#route').text(GeoPosition.address);
    };
    // А вот наши Сохранить и закрыть
	GeoPosition.initializeActions = function() {
		GeoPosition.currentModal.find('[data-method]').click(function(e) {
			e.preventDefault();
			var method = $(this).data('method');
			var options = $(this).data('option') || {};
			if (typeof GeoPosition[method] === 'function') {
				GeoPosition[method](options);
			}
		});
	};
	// Сохраняем, т.е. отправляем данные обатно в нашу форму.
	GeoPosition.save = function(){
    	// default field: country, city, latitude, lonitude, address
    	var formFields =  GeoPosition.$trigger.data('fields');
    	var table = GeoPosition.$trigger.data('table');
    	var	form = GeoPosition.$trigger.closest('form');
    	// если бы не убрали title тот тут бы он и всплыл.. и попытался за заменится на что нибудь.
    	$.each(formFields, function(key, field){
    		var selector = form.find('[data-formengine-input-name*="'+field+'"]');
    		$(selector[0]).val(GeoPosition[key]);
    		TBE_EDITOR.fieldChanged(table, 1, field, $(selector[0]).data('formengine-input-name'));
    	});
    	GeoPosition.dismiss();
	
    };
    // Закрыть окошко
    GeoPosition.dismiss = function() {
		if (GeoPosition.currentModal) {
			GeoPosition.currentModal.modal('hide');
			GeoPosition.currentModal = null;
		}
	};
	return GeoPosition; За основу и в качестве рабочего примера смотрел в плагины t3editor и в ImageManipulationElement 
				__________________ Фанат TYPO! Последний раз редактировалось alexk; 27.04.2016 в 11:34 | 
|   |   | 
| 
 | 
 | 
|  Похожие темы | ||||
| Тема | Автор | Раздел | Ответов | Последнее сообщение | 
| Странные ошибки. | M31 | Установка | 2 | 24.12.2008 12:33 | 
| Включение кода PHP | Костик | Общие вопросы | 2 | 30.10.2008 18:10 | 
| Трабл с загрузкой *.t3x в Extension Manager | Raven2000 | Общие вопросы | 6 | 08.08.2007 18:15 | 
| Проблемы c php 5.2.3 | Archual | Общие вопросы | 4 | 01.07.2007 15:11 | 
| Форма + валидация > php > БД | Artem | Общие вопросы | 3 | 08.01.2007 23:39 |