Форум больше не используется. Присоединяйтесь к каналу #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 |