diff --git a/site/modules/.FieldtypeMapMarker/FieldtypeMapMarker.module b/site/modules/.FieldtypeMapMarker/FieldtypeMapMarker.module deleted file mode 100644 index a3ec707..0000000 --- a/site/modules/.FieldtypeMapMarker/FieldtypeMapMarker.module +++ /dev/null @@ -1,276 +0,0 @@ - 'Map Marker', - 'version' => 209, - 'summary' => 'Field that stores an address with latitude and longitude coordinates and has built-in geocoding capability with Google Maps API.', - 'installs' => 'InputfieldMapMarker', - 'icon' => 'map-marker', - ); - } - - /** - * Include our MapMarker class, which serves as the value for fields of type FieldtypeMapMarker - * - */ - public function __construct() { - require_once(dirname(__FILE__) . '/MapMarker.php'); - } - - /** - * Return the Inputfield required by this Fieldtype - * - * @param Page $page - * @param Field $field - * @return InputfieldMapMarker - * - */ - public function getInputfield(Page $page, Field $field) { - /** @var InputfieldMapMarker $inputfield */ - $inputfield = $this->modules->get('InputfieldMapMarker'); - $inputfield->set('googleApiKey', $this->get('googleApiKey')); - return $inputfield; - } - - /** - * Return all compatible Fieldtypes - * - * @param Field $field - * @return null - * - */ - public function ___getCompatibleFieldtypes(Field $field) { - // there are no other fieldtypes compatible with this one - return null; - } - - /** - * Sanitize value for runtime - * - * @param Page $page - * @param Field $field - * @param MapMarker $value - * @return MapMarker - * - */ - public function sanitizeValue(Page $page, Field $field, $value) { - - // if it's not a MapMarker, then just return a blank MapMarker - if(!$value instanceof MapMarker) $value = $this->getBlankValue($page, $field); - - // if the address changed, tell the $page that this field changed - if($value->isChanged('address')) $page->trackChange($field->name); - - return $value; - } - - /** - * Get a blank value used by this fieldtype - * - * @param Page $page - * @param Field $field - * @return MapMarker - * - */ - public function getBlankValue(Page $page, Field $field) { - return new MapMarker(); - } - - /** - * Given a raw value (value as stored in DB), return the value as it would appear in a Page object - * - * @param Page $page - * @param Field $field - * @param string|int|array $value - * @return string|int|array|object $value - * - */ - public function ___wakeupValue(Page $page, Field $field, $value) { - - // get a blank MapMarker instance - $marker = $this->getBlankValue($page, $field); - - if("$value[lat]" === "0") $value['lat'] = ''; - if("$value[lng]" === "0") $value['lng'] = ''; - - // populate the marker - $marker->address = $value['data']; - $marker->lat = $value['lat']; - $marker->lng = $value['lng']; - $marker->status = $value['status']; - $marker->zoom = $value['zoom']; - $marker->setTrackChanges(true); - - return $marker; - } - - /** - * Given an 'awake' value, as set by wakeupValue, convert the value back to a basic type for storage in DB. - * - * @param Page $page - * @param Field $field - * @param string|int|array|object $value - * @return string|int - * @throws WireException - * - */ - public function ___sleepValue(Page $page, Field $field, $value) { - - $marker = $value; - - if(!$marker instanceof MapMarker) - throw new WireException("Expecting an instance of MapMarker"); - - // if the address was changed, then force it to geocode the new address - if($marker->isChanged('address') && $marker->address && $marker->status != MapMarker::statusNoGeocode) $marker->geocode(); - - $sleepValue = array( - 'data' => $marker->address, - 'lat' => strlen($marker->lat) ? $marker->lat : 0, - 'lng' => strlen($marker->lng) ? $marker->lng : 0, - 'status' => $marker->status, - 'zoom' => $marker->zoom - ); - - return $sleepValue; - } - - - /** - * Return the database schema in specified format - * - * @param Field $field - * @return array - * - */ - public function getDatabaseSchema(Field $field) { - - // get the default schema - $schema = parent::getDatabaseSchema($field); - - $schema['data'] = "VARCHAR(255) NOT NULL DEFAULT ''"; // address (reusing the 'data' field from default schema) - $schema['lat'] = "FLOAT(10,6) NOT NULL DEFAULT 0"; // latitude - $schema['lng'] = "FLOAT(10,6) NOT NULL DEFAULT 0"; // longitude - $schema['status'] = "TINYINT NOT NULL DEFAULT 0"; // geocode status - $schema['zoom'] = "TINYINT NOT NULL DEFAULT 0"; // zoom level (schema v1) - - $schema['keys']['latlng'] = "KEY latlng (lat, lng)"; // keep an index of lat/lng - $schema['keys']['data'] = 'FULLTEXT KEY `data` (`data`)'; - $schema['keys']['zoom'] = "KEY zoom (zoom)"; - - if($field->id) $this->updateDatabaseSchema($field, $schema); - - return $schema; - } - - /** - * Update the DB schema, if necessary - * - * @param Field $field - * @param array $schema - * - */ - protected function updateDatabaseSchema(Field $field, array $schema) { - - $requiredVersion = 1; - $schemaVersion = (int) $field->get('schemaVersion'); - - if($schemaVersion >= $requiredVersion) { - // already up-to-date - return; - } - - if($schemaVersion == 0) { - // update schema to v1: add 'zoom' column - $schemaVersion = 1; - $database = $this->wire('database'); - $table = $database->escapeTable($field->getTable()); - $query = $database->prepare("SHOW TABLES LIKE '$table'"); - $query->execute(); - $row = $query->fetch(\PDO::FETCH_NUM); - $query->closeCursor(); - if(!empty($row)) { - $query = $database->prepare("SHOW COLUMNS FROM `$table` WHERE field='zoom'"); - $query->execute(); - if(!$query->rowCount()) try { - $database->exec("ALTER TABLE `$table` ADD zoom $schema[zoom] AFTER status"); - $this->message("Added 'zoom' column to '$field->table'"); - } catch(Exception $e) { - $this->error($e->getMessage()); - } - } - } - - $field->set('schemaVersion', $schemaVersion); - $field->save(); - } - - /** - * Match values for PageFinder - * - * @param DatabaseQuerySelect $query - * @param string $table - * @param string $subfield - * @param string $operator - * @param string $value - * @return DatabaseQuerySelect - * - */ - public function getMatchQuery($query, $table, $subfield, $operator, $value) { - if(!$subfield || $subfield == 'address') $subfield = 'data'; - if($subfield != 'data' || $this->wire('database')->isOperator($operator)) { - // if dealing with something other than address, or operator is native to SQL, - // then let Fieldtype::getMatchQuery handle it instead - return parent::getMatchQuery($query, $table, $subfield, $operator, $value); - } - // if we get here, then we're performing either %= (LIKE and variations) or *= (FULLTEXT and variations) - $ft = new DatabaseQuerySelectFulltext($query); - $ft->match($table, $subfield, $operator, $value); - return $query; - } - - /** - * Module configuration - * - * @param array $data - * @return InputfieldWrapper - * - */ - public static function getModuleConfigInputfields(array $data) { - $inputfields = new InputfieldWrapper(); - /** @var InputfieldText $f */ - $f = wire('modules')->get('InputfieldText'); - $f->attr('name', 'googleApiKey'); - $f->label = __('Google Maps API Key'); - $f->icon = 'map'; - $f->description = sprintf(__('[Click here](%s) for instructions from Google on how to obtain an API key.'), - 'https://developers.google.com/maps/documentation/javascript/get-api-key'); - $f->attr('value', isset($data['googleApiKey']) ? $data['googleApiKey'] : ''); - $inputfields->add($f); - return $inputfields; - } -} - diff --git a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.css b/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.css deleted file mode 100644 index 8e5cd8d..0000000 --- a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.css +++ /dev/null @@ -1,73 +0,0 @@ -.InputfieldMapMarker input[type=number], -.InputfieldMapMarker input[type=text] { - width: 99.5%; -} - -.InputfieldMapMarkerToggle span { - display: none; -} - -.InputfieldMapMarkerAddress { - float: left; - width: 70%; - padding-right: 2%; -} - -.InputfieldMapMarkerToggle { - float: left; - width: 28%; -} - -.InputfieldMapMarkerLat, -.InputfieldMapMarkerLng { - width: 42%; - float: left; - padding-right: 2%; -} - -.InputfieldMapMarkerZoom { - float: left; - width: 10%; -} - -.InputfieldMapMarker .notes { - clear: both; -} - -.InputfieldMapMarkerMap { - width: 100%; - height: 300px; - clear: left; -} - -@media only screen and (min-width: 768px) { - - .InputfieldMapMarkerAddress { - width: 38%; - padding-right: 1%; - } - - .InputfieldMapMarkerToggle { - width: 2%; - padding-right: 0.5%; - position: relative; - } - - .InputfieldMapMarkerToggle strong { - /* hide geocode label */ - display: none; - } - - .InputfieldMapMarkerLat, - .InputfieldMapMarkerLng { - width: 23%; - padding-right: 1%; - } - - .InputfieldMapMarkerZoom { - float: left; - width: 9.5%; - } - -} - diff --git a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.js b/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.js deleted file mode 100644 index d0724d3..0000000 --- a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Display a Google Map and pinpoint a location for InputfieldMapMarker - * - */ - -var InputfieldMapMarker = { - - options: { - zoom: 12, // mats, previously 5 - draggable: true, // +mats - center: null, - //key: config.InputfieldMapMarker.googleApiKey, - mapTypeId: google.maps.MapTypeId.HYBRID, - scrollwheel: false, - mapTypeControlOptions: { - style: google.maps.MapTypeControlStyle.DROPDOWN_MENU - }, - scaleControl: false - }, - - init: function(mapId, lat, lng, zoom, mapType) { - - var options = InputfieldMapMarker.options; - - if(zoom < 1) zoom = 12; - options.center = new google.maps.LatLng(lat, lng); - options.zoom = parseInt(zoom); - - if(mapType == 'SATELLITE') options.mapTypeId = google.maps.MapTypeId.SATELLITE; - else if(mapType == 'ROADMAP') options.mapTypeId = google.maps.MapTypeId.ROADMAP; - - var map = new google.maps.Map(document.getElementById(mapId), options); - - var marker = new google.maps.Marker({ - position: options.center, - map: map, - draggable: options.draggable - }); - - var $map = $('#' + mapId); - var $lat = $map.siblings(".InputfieldMapMarkerLat").find("input[type=text]"); - var $lng = $map.siblings(".InputfieldMapMarkerLng").find("input[type=text]"); - var $addr = $map.siblings(".InputfieldMapMarkerAddress").find("input[type=text]"); - var $addrJS = $map.siblings(".InputfieldMapMarkerAddress").find("input[type=hidden]"); - var $toggle = $map.siblings(".InputfieldMapMarkerToggle").find("input[type=checkbox]"); - var $zoom = $map.siblings(".InputfieldMapMarkerZoom").find("input[type=number]"); - var $notes = $map.siblings(".notes"); - - $lat.val(marker.getPosition().lat()); - $lng.val(marker.getPosition().lng()); - $zoom.val(map.getZoom()); - - google.maps.event.addListener(marker, 'dragend', function(event) { - var geocoder = new google.maps.Geocoder(); - var position = this.getPosition(); - $lat.val(position.lat()); - $lng.val(position.lng()); - if($toggle.is(":checked")) { - geocoder.geocode({ 'latLng': position }, function(results, status) { - if(status == google.maps.GeocoderStatus.OK && results[0]) { - $addr.val(results[0].formatted_address); - $addrJS.val($addr.val()); - } - $notes.text(status); - }); - } - }); - - google.maps.event.addListener(map, 'zoom_changed', function() { - $zoom.val(map.getZoom()); - }); - - $addr.blur(function() { - if(!$toggle.is(":checked")) return true; - var geocoder = new google.maps.Geocoder(); - geocoder.geocode({ 'address': $(this).val()}, function(results, status) { - if(status == google.maps.GeocoderStatus.OK && results[0]) { - var position = results[0].geometry.location; - map.setCenter(position); - marker.setPosition(position); - $lat.val(position.lat()); - $lng.val(position.lng()); - $addrJS.val($addr.val()); - } - $notes.text(status); - }); - return true; - }); - - $zoom.change(function() { - map.setZoom(parseInt($(this).val())); - }); - - $toggle.click(function() { - if($(this).is(":checked")) { - $notes.text('Geocode ON'); - // google.maps.event.trigger(marker, 'dragend'); - $addr.trigger('blur'); - } else { - $notes.text('Geocode OFF'); - } - return true; - }); - - // added by diogo to solve the problem of maps not rendering correctly in hidden elements - // trigger a resize on the map when either the tab button or the toggle field bar are pressed - - // get the tab element where this map is integrated - var $map = $('#' + mapId); - var $tab = $('#_' + $map.closest('.InputfieldFieldsetTabOpen').attr('id')); - // get the inputfield where this map is integrated and add the tab to the stack - var $inputFields = $map.closest('.Inputfield').find('.InputfieldStateToggle').add($tab); - - $inputFields.on('click',function(){ - // give it time to open - window.setTimeout(function(){ - google.maps.event.trigger(map,'resize'); - map.setCenter(options.center); - }, 200); - }); - - } -}; - -$(document).ready(function() { - $(".InputfieldMapMarkerMap").each(function() { - var $t = $(this); - InputfieldMapMarker.init($t.attr('id'), $t.attr('data-lat'), $t.attr('data-lng'), $t.attr('data-zoom'), $t.attr('data-type')); - }); -}); diff --git a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.module b/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.module deleted file mode 100644 index a0da886..0000000 --- a/site/modules/.FieldtypeMapMarker/InputfieldMapMarker.module +++ /dev/null @@ -1,329 +0,0 @@ - 'Map Marker', - 'version' => 209, - 'summary' => "Provides input for the MapMarker Fieldtype", - 'requires' => 'FieldtypeMapMarker', - 'icon' => 'map-marker', - ); - } - - const defaultAddr = 'Castaway Cay'; - - /** - * Just in case this Inputfield is being used separately from FieldtypeMapmarker, we include the MapMarker class - * - */ - public function __construct() { - require_once(dirname(__FILE__) . '/MapMarker.php'); - $this->set('defaultAddr', self::defaultAddr); - $this->set('defaultZoom', 12); - $this->set('defaultType', 'HYBRID'); - $this->set('defaultLat', ''); - $this->set('defaultLng', ''); - $this->set('height', 300); - $this->set('googleApiKey', ''); - parent::__construct(); - } - - /** - * Set an attribute to this Inputfield - * - * In this case, we just capture the 'value' attribute and make sure it's something valid - * - * @param string $key - * @param mixed $value - * @return $this - * @throws WireException - * - */ - public function setAttribute($key, $value) { - - if($key == 'value' && !$value instanceof MapMarker && !is_null($value)) { - throw new WireException("This input only accepts a MapMarker for it's value"); - } - - return parent::setAttribute($key, $value); - } - - public function isEmpty() { - return (!$this->value || ((float) $this->value->lat) === 0.0); - } - - public function renderReady(Inputfield $parent = null, $renderValueMode = false) { - $url = 'https://maps.google.com/maps/api/js'; - $key = $this->get('googleApiKey'); - if($key) $url .= "?key=$key"; - $this->config->scripts->add($url); - return parent::renderReady($parent, $renderValueMode); - } - - /** - * Render the markup needed to draw the Inputfield - * - * @return string - * - */ - public function ___render() { - - $name = $this->attr('name'); - $id = $this->attr('id'); - $marker = $this->attr('value'); - if($marker->lat == 0.0) $marker->lat = $this->defaultLat; - if($marker->lng == 0.0) $marker->lng = $this->defaultLng; - if(!$marker->zoom) $marker->zoom = $this->defaultZoom; - $address = htmlentities($marker->address, ENT_QUOTES, "UTF-8"); - $toggleChecked = $marker->status != MapMarker::statusNoGeocode ? " checked='checked'" : ''; - $status = $marker->status == MapMarker::statusNoGeocode ? 0 : $marker->status; - $mapType = $this->defaultType; - $height = $this->height ? (int) $this->height : 300; - - $labels = array( - 'addr' => $this->_('Address'), - 'lat' => $this->_('Latitude'), - 'lng' => $this->_('Longitude'), - 'geo' => $this->_('Geocode?'), - 'zoom' => $this->_('Zoom') - ); - - $out = <<< _OUT - - - -

- - -

- -

- -

- -

- -

- -

- -

- -

- -

- - -_OUT; - - $out .= "
" . - "
"; - - $this->notes = $marker->statusString; - - if(!$this->get('googleApiKey')) { - $msg = $this->_('Please setup a Google Maps API key in the FieldtypeMapMarker module settings'); - if($this->wire('user')->isSuperuser()) { - $link = ""; - $msg = "$link$msg"; - $this->warning($msg, Notice::allowMarkup); - } else { - $this->warning($msg); - } - } - - return $out; - } - - /** - * Process the input after a form submission - * - * @param WireInputData $input - * @return $this - * - */ - public function ___processInput(WireInputData $input) { - - $name = $this->attr('name'); - $marker = $this->attr('value'); - - if(!isset($input->$name)) return $this; - - if($input->$name == $this->defaultAddr) { - $marker->set('address', ''); - } else { - $marker->set('address', $input->$name); - } - - $lat = $input["_{$name}_lat"]; - $lng = $input["_{$name}_lng"]; - - $precision = 4; - if( ((string) round($lat, $precision)) != ((string) round($this->defaultLat, $precision)) || - ((string) round($lng, $precision)) != ((string) round($this->defaultLng, $precision))) { - - $marker->set('lat', $lat); - $marker->set('lng', $lng); - } else { - // $this->message("Kept lat/lng at unset value", Notice::debug); - } - - $zoom = $input["_{$name}_zoom"]; - if($zoom > -1 && $zoom < 30) $marker->zoom = (int) $zoom; - - $status = $input["_{$name}_status"]; - if(is_null($status)) $marker->set('status', MapMarker::statusNoGeocode); // disable geocode - else $marker->set('status', (int) $status); - - // if the address changed, then redo the geocoding. - // while we do this in the Fieldtype, we also do it here in case this Inputfield is used on it's own. - // the MapMarker class checks to make sure it doesn't do the same geocode twice. - if($marker->isChanged('address') && $marker->address && $marker->status != MapMarker::statusNoGeocode) { - // double check that the address wasn't already populated by the JS geocoder - // this prevents user-dragged markers that don't geocode to an exact location from getting - // unintentionally moved by the PHP-side geocoder - if($input["_{$name}_js_geocode_address"] == $marker->address) { - // prevent the geocoder from running in the fieldtype - $marker->skipGeocode = true; - $this->message('Skipping geocode (already done by JS geocoder)', Notice::debug); - } else { - $marker->geocode(); - } - } - - return $this; - } - - public function ___getConfigInputfields() { - $inputfields = parent::___getConfigInputfields(); - - /** @var InputfieldText $field */ - $field = $this->modules->get('InputfieldText'); - $field->attr('name', 'defaultAddr'); - $field->label = $this->_('Default Address'); - $field->description = $this->_('This will be geocoded to become the starting point of the map.'); - $field->attr('value', $this->defaultAddr); - $field->notes = $this->_('When modifying the default address, please make the Latitude and Longitude fields below blank, which will force the system to geocode your new address.'); - $inputfields->add($field); - - if(!$this->defaultLat && !$this->defaultLng) { - $m = new MapMarker(); - $m->address = $this->defaultAddr; - $status = $m->geocode(); - if($status > 0) { - $this->defaultLat = $m->lat; - $this->defaultLng = $m->lng; - $this->message($this->_('Geocoded your default address. Please hit save once again to commit the new default latitude and longitude.')); - } - } - - /** @var InputfieldText $field */ - $field = $this->modules->get('InputfieldText'); - $field->attr('name', 'defaultLat'); - $field->label = $this->_('Default Latitude'); - $field->attr('value', $this->defaultLat); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldText $field */ - $field = $this->modules->get('InputfieldText'); - $field->attr('name', 'defaultLng'); - $field->label = $this->_('Default Longitude'); - $field->attr('value', $this->defaultLng); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldRadios $field */ - $field = $this->modules->get('InputfieldRadios'); - $field->attr('name', 'defaultType'); - $field->label = $this->_('Default Map Type'); - $field->addOption('HYBRID', $this->_('Hybrid')); - $field->addOption('ROADMAP', $this->_('Road Map')); - $field->addOption('SATELLITE', $this->_('Satellite')); - $field->attr('value', $this->defaultType); - $field->optionColumns = 1; - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldInteger $field */ - $field = $this->modules->get('InputfieldInteger'); - $field->attr('name', 'height'); - $field->label = $this->_('Map Height (in pixels)'); - $field->attr('value', $this->height); - $field->attr('type', 'number'); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldInteger $field */ - $field = $this->modules->get('InputfieldInteger'); - $field->attr('name', 'defaultZoom'); - $field->label = $this->_('Default Zoom'); - $field->description = $this->_('Enter a value between 1 and 23. The highest zoom level is typically somewhere between 19-23, depending on the location being zoomed and how much data Google has for the location.'); // Zoom level description - $field->attr('value', $this->defaultZoom); - $field->attr('type', 'number'); - $inputfields->add($field); - - /** @var InputfieldMarkup $field */ - $field = $this->modules->get('InputfieldMarkup'); - $field->label = $this->_('API Notes'); - $field->description = $this->_('You can access individual values from this field using the following from your template files:'); - $field->value = - "
" .
-			"\$page->{$this->name}->address\n" . 
-			"\$page->{$this->name}->lat\n" . 
-			"\$page->{$this->name}->lng\n" . 
-			"\$page->{$this->name}->zoom" . 
-			"
"; - - $inputfields->add($field); - - return $inputfields; - } - -} diff --git a/site/modules/.FieldtypeMapMarker/MapMarker.php b/site/modules/.FieldtypeMapMarker/MapMarker.php deleted file mode 100644 index 0e77998..0000000 --- a/site/modules/.FieldtypeMapMarker/MapMarker.php +++ /dev/null @@ -1,126 +0,0 @@ - 'N/A', - 1 => 'OK', - 2 => 'OK_ROOFTOP', - 3 => 'OK_RANGE_INTERPOLATED', - 4 => 'OK_GEOMETRIC_CENTER', - 5 => 'OK_APPROXIMATE', - - -1 => 'UNKNOWN', - -2 => 'ZERO_RESULTS', - -3 => 'OVER_QUERY_LIMIT', - -4 => 'REQUEST_DENIED', - -5 => 'INVALID_REQUEST', - - -100 => 'Geocode OFF', // RCD - - ); - - protected $geocodedAddress = ''; - - public function __construct() { - $this->set('lat', ''); - $this->set('lng', ''); - $this->set('address', ''); - $this->set('status', 0); - $this->set('zoom', 0); - // temporary runtime property to indicate the geocode should be skipped - $this->set('skipGeocode', false); - $this->set('statusString', ''); - } - - public function set($key, $value) { - - if($key == 'lat' || $key == 'lng') { - // if value isn't numeric, then it's not valid: make it blank - if(strpos($value, ',') !== false) $value = str_replace(',', '.', $value); // convert 123,456 to 123.456 - if(!is_numeric($value)) $value = ''; - - } else if($key == 'address') { - $value = wire('sanitizer')->text($value); - - } else if($key == 'status') { - $value = (int) $value; - if(!isset($this->geocodeStatuses[$value])) $value = -1; // -1 = unknown - } else if($key == 'zoom') { - $value = (int) $value; - } - - return parent::set($key, $value); - } - - public function get($key) { - if($key == 'statusString') return str_replace('_', ' ', $this->geocodeStatuses[$this->status]); - return parent::get($key); - } - - public function geocode() { - if($this->skipGeocode) return -100; - - // check if address was already geocoded - if($this->geocodedAddress == $this->address) return $this->status; - $this->geocodedAddress = $this->address; - - $url = "https://maps.googleapis.com/maps/api/geocode/json?address=" . urlencode($this->address); - $apiKey = $this->modules->get('FieldtypeMapMarker')->get('googleApiKey'); - if($apiKey) $url .= "&key=$apiKey"; - $http = new WireHttp(); - $json = $http->getJSON($url, true); - - if(empty($json['status']) || $json['status'] != 'OK') { - $this->error("Error geocoding address"); - if(isset($json['status'])) $this->status = (int) array_search($json['status'], $this->geocodeStatuses); - else $this->status = -1; - $this->lat = 0; - $this->lng = 0; - return $this->status; - } - - $geometry = $json['results'][0]['geometry']; - $location = $geometry['location']; - $locationType = $geometry['location_type']; - - $this->lat = $location['lat']; - $this->lng = $location['lng']; - - $statusString = $json['status'] . '_' . $locationType; - $status = array_search($statusString, $this->geocodeStatuses); - if($status === false) $status = 1; // OK - - $this->status = $status; - $this->message("Geocode {$this->statusString}: '{$this->address}'"); - - return $this->status; - } - - /** - * If accessed as a string, then just output the lat, lng coordinates - * - */ - public function __toString() { - return "$this->address ($this->lat, $this->lng, $this->zoom) [$this->statusString]"; - } - -} - - - diff --git a/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.js b/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.js deleted file mode 100644 index 7a5b1d3..0000000 --- a/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.js +++ /dev/null @@ -1,214 +0,0 @@ -/** - * ProcessWire Map Markup (JS) - * - * Renders maps for the FieldtypeMapMarker module - * - * ProcessWire 2.x - * Copyright (C) 2016 by Ryan Cramer - * Licensed under MPL 2.0 - * - * http://processwire.com - * - * Javascript Usage: - * ================= - * var map = new MarkupGoogleMap(); - * map.setOption('any-google-maps-option', 'value'); - * map.setOption('zoom', 12); // example - * - * // init(container ID, latitude, longitude): - * map.init('#map-div', 26.0936823, -77.5332796); - * - * // addMarker(latitude, longitude, optional URL, optional URL to icon file): - * map.addMarker(26.0936823, -77.5332796, 'en.wikipedia.org/wiki/Castaway_Cay', ''); - * map.addMarker(...you may have as many of these as you want...); - * - * // optionally fit the map to the bounds of the markers you added - * map.fitToMarkers(); - * - */ - -function MarkupGoogleMap() { - - this.map = null; - this.markers = []; - this.numMarkers = 0; - this.icon = ''; - this.iconHover = ''; - this.shadow = ''; - - this.hoverBox = null; - this.hoverBoxOffsetTop = 0; - this.hoverBoxOffsetLeft = 0; - - this.options = { - zoom: 10, - center: null, - mapTypeId: google.maps.MapTypeId.ROADMAP, - scrollwheel: false, - mapTypeControlOptions: { - style: google.maps.MapTypeControlStyle.DROPDOWN_MENU - }, - scaleControl: false, - - // disable points of interest - styles: [{ - featureType: "poi", - stylers: [ { visibility: "off" } ] - }] - }; - - - this._currentURL = ''; - - this.init = function(mapID, lat, lng) { - if(lat != 0) this.options.center = new google.maps.LatLng(lat, lng); - this.map = new google.maps.Map(document.getElementById(mapID), this.options); - } - - this.setOption = function(key, value) { - this.options[key] = value; - } - - this.setIcon = function(url) { - this.icon = url; - } - - this.setIconHover = function(url) { - this.iconHover = url; - } - - this.setShadow = function(url) { - this.shadow = url; - } - - this.setHoverBox = function(markup) { - - if(!markup.length) { - this.hoverBox = null; - return; - } - - this.hoverBox = $(markup); - var $hoverBox = this.hoverBox; - - this.hoverBoxOffsetTop = parseInt($hoverBox.attr('data-top')); - this.hoverBoxOffsetLeft = parseInt($hoverBox.attr('data-left')); - - $("body").append($hoverBox); - - // keep it hidden/out of the way until needed - $hoverBox.css({ - position: 'absolute', - left: 0, - top: '-100px' - }); - - $hoverBox.mouseout(function() { - $hoverBox.hide(); - }).click(function() { - if(this._currentURL.length > 0) window.location.href = this._currentURL; - }); - } - - this.addMarker = function(lat, lng, url, title, icon, shadow) { - if(lat == 0.0) return; - - var latLng = new google.maps.LatLng(lat, lng); - var zIndex = 99999 + this.numMarkers; - - var markerOptions = { - position: latLng, - map: this.map, - linkURL: '', - zIndex: zIndex - }; - - if(typeof icon !== "undefined" && icon.length > 0) markerOptions.icon = icon; - else if(this.icon) markerOptions.icon = this.icon; - - // console.log(markerOptions); - - if(typeof shadow !== "undefined" && shadow.length > 0) markerOptions.shadow = shadow; - else if(this.shadow.length > 0) markerOptions.shadow = this.shadow; - - var marker = new google.maps.Marker(markerOptions); - - if(url.length > 0) marker.linkURL = url; - if(this.hoverBox) marker.hoverBoxTitle = title; - else marker.setTitle(title); - - this.markers[this.numMarkers] = marker; - this.numMarkers++; - - if(marker.linkURL.length > 0) { - google.maps.event.addListener(marker, 'click', function(e) { - window.location.href = marker.linkURL; - }); - } - - if(markerOptions.icon !== "undefined" && this.iconHover) { - var iconHover = this.iconHover; - google.maps.event.addListener(marker, 'mouseover', function(e) { - marker.setIcon(iconHover); - }); - google.maps.event.addListener(marker, 'mouseout', function(e) { - marker.setIcon(markerOptions.icon); - }); - } - - if(this.hoverBox) { - - var $hoverBox = this.hoverBox; - var offsetTop = this.hoverBoxOffsetTop; - var offsetLeft = this.hoverBoxOffsetLeft; - - var mouseMove = function(e) { - $hoverBox.css({ - 'top': e.pageY + offsetTop, - 'left': e.pageX + offsetLeft - }); - }; - - // console.log($hoverBox); - - google.maps.event.addListener(marker, 'mouseover', function(e) { - this._currentURL = url; - $hoverBox.html("" + marker.hoverBoxTitle + "") - .css('top', '0px') - .css('left', '0px') - .css('display', 'block') - .css('width', 'auto') - .css('z-index', 9999); - $hoverBox.show(); - - $(document).mousemove(mouseMove); - }); - - google.maps.event.addListener(marker, 'mouseout', function(e) { - $hoverBox.hide(); - $(document).unbind("mousemove", mouseMove); - }); - - } - } - - this.fitToMarkers = function() { - - var bounds = new google.maps.LatLngBounds(); - var map = this.map; - - for(var i = 0; i < this.numMarkers; i++) { - var latLng = this.markers[i].position; - bounds.extend(latLng); - } - - map.fitBounds(bounds); - - - var listener = google.maps.event.addListener(map, "idle", function() { - if(map.getZoom() < 2) map.setZoom(2); - google.maps.event.removeListener(listener); - }); - } -} - diff --git a/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.module b/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.module deleted file mode 100644 index fc40ab7..0000000 --- a/site/modules/.FieldtypeMapMarker/MarkupGoogleMap.module +++ /dev/null @@ -1,251 +0,0 @@ - tag: - * - * - * - * In the location where you want to output your map, do the following in your template file: - * - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($page, 'map'); // replace 'map' with the name of your FieldtypeMap field - * - * To render a map with multiple markers on it, specify a PageArray rather than a single $page: - * - * $items = $pages->find("template=something, map!='', sort=title"); - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($items, 'map'); - * - * To specify options, provide a 3rd argument with an options array: - * - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($items, 'map', array('height' => '500px')); - * - * - * OPTIONS - * ======= - * Here is a list of all possible options (with defaults shown): - * - * // default width of the map - * 'width' => '100%' - * - * // default height of the map - * 'height' => '300px' - * - * // zoom level - * 'zoom' => 12 (or $field->defaultZoom) - * - * // map type: ROADMAP, HYBRID or SATELLITE - * 'type' => 'HYBRID' or $field->defaultType - * - * // map ID attribute - * 'id' => "mgmap" - * - * // map class attribute - * 'class' => "MarkupGoogleMap" - * - * // center latitude - * 'lat' => $field->defaultLat - * - * // center longitude - * 'lng' => $field->defaultLng - * - * // set to false only if you will style the map
yourself - * 'useStyles' => true - * - * // allows single-marker map to use marker settings rather than map settings - * 'useMarkerSettings' => true - * - * // field to use for the marker link, or blank to not link - * 'markerLinkField' => 'url' - * - * // field to use for the marker title - * 'markerTitleField' => 'title' - * - * // map will automatically adjust to fit to the given markers (when multiple markers) - * 'fitToMarkers' => true - * - * // use hover box? When true, shows a tooltip-type box when you hover the marker, populated with the markerTitleField - * // this is often more useful than the default presentation google maps uses - * 'useHoverBox' => false - * - * // when useHoverBox is true, you can specify the markup used for it. Use the following (which is the default) as your starting point: - * 'hoverBoxMarkup' => "
", - * - * // FUll URL to icon file to use for markers. Blank=use default Google marker icon. - * 'icon' => '', - * - * // Any extra javascript initialization code you want to occur before the map itself is drawn - * 'init' => '', - * - */ - -class MarkupGoogleMap extends WireData implements Module { - - public static function getModuleInfo() { - return array( - 'title' => 'Map Markup (Google Maps)', - 'version' => 101, - 'summary' => 'Renders Google Maps for the MapMarker Fieldtype', - 'requires' => 'FieldtypeMapMarker', - ); - } - - /** - * Include our MapMarker class, which serves as the value for fields of type FieldtypeMapMarker - * - */ - public function init() { - require_once(dirname(__FILE__) . '/MapMarker.php'); - } - - /** - * Get associative array of map options - * - * @param string $fieldName - * @return array - * @throws WireException - * - */ - public function getOptions($fieldName) { - - static $n = 0; - $field = $this->fields->get($fieldName); - if(!$field) throw new WireException("Unknown field: $fieldName"); - - return array( - 'useStyles' => true, - 'fitToMarkers' => true, - 'useMarkerSettings' => true, - 'useHoverBox' => false, - 'hoverBoxMarkup' => "
", - 'markerLinkField' => 'url', - 'markerTitleField' => 'title', - 'width' => '100%', - 'height' => $field->height, - 'zoom' => $field->defaultZoom ? (int) $field->defaultZoom : 12, - 'type' => $field->defaultType ? $field->defaultType : 'HYBRID', - 'id' => "mgmap" . (++$n), - 'class' => "MarkupGoogleMap", - 'lat' => $field->defaultLat, - 'lng' => $field->defaultLng, - 'icon' => '', // url to icon (blank=use default) - 'iconHover' => '', // url to icon when hovered (default=none) - 'shadow' => '', // url to icon shadow (blank=use default) - 'init' => '', // additional javascript code to insert in map initialization - 'n' => $n, - ); - } - - /** - * Get the script tag for loading Google Maps - * - * @return string - * @throws WireException - * - */ - public function getGMapScript() { - $url = 'https://maps.google.com/maps/api/js'; - $key = $this->wire('modules')->get('FieldtypeMapMarker')->get('googleApiKey'); - if($key) $url .= "?key=$key"; - return ""; - } - - /** - * Render map markup - * - * @param PageArray|Page $pageArray Page (or multiple pages in PageArray) containing map field - * @param $fieldName Name of the map field - * @param array $options Options to adjust behavior - * @return string - * @throws WireException - * - */ - public function render($pageArray, $fieldName, array $options = array()) { - - static $n = 0; - $n++; - - $defaultOptions = $this->getOptions($fieldName); - $options = array_merge($defaultOptions, $options); - - if($pageArray instanceof Page) { - $page = $pageArray; - $pageArray = new PageArray(); - $pageArray->add($page); - } - - $height = $options['height']; - $width = $options['width']; - if(empty($height)) $height = 300; - if(ctype_digit("$height")) $height .= "px"; - if(ctype_digit("$width")) $width .= "px"; - - $style = ''; - if($options['useStyles'] && !empty($height) && !empty($width)) { - $style = " style='width: $width; height: $height;'"; - } - - $lat = $options['lat']; - $lng = $options['lng']; - $zoom = $options['zoom'] > 0 ? (int) $options['zoom'] : $defaultOptions['zoom']; - $type = in_array($options['type'], array('ROADMAP', 'SATELLITE', 'HYBRID')) ? $options['type'] : 'HYBRID'; - - if($options['useMarkerSettings'] && (count($pageArray) == 1 || !$lat)) { - // single marker overrides lat, lng and zoom settings - $marker = $pageArray->first()->get($fieldName); - $lat = $marker->lat; - $lng = $marker->lng; - if($marker->zoom > 0) $zoom = (int) $marker->zoom; - } - - $id = $options['id']; - $out = ''; - - if($n === 1) $out .= ""; - - $out .= "
"; - - $out .= ""; - - return $out; - } -} - diff --git a/site/modules/.FieldtypeMapMarker/README.md b/site/modules/.FieldtypeMapMarker/README.md deleted file mode 100644 index 1e57704..0000000 --- a/site/modules/.FieldtypeMapMarker/README.md +++ /dev/null @@ -1,147 +0,0 @@ -# FieldtypeMapMarker Module for ProcessWire - -This Fieldtype for ProcessWire holds an address or location name, and automatically -geocodes the address to latitude/longitude using Google Maps API. The resulting -values may be used to populate any kind of map (whether Google Maps or another). - -This Fieldtype was created to serve as an example of creating a custom Fieldtype and -Inputfield that contains multiple pieces of data. Though the Fieldtype has now gone -far beyond that and is relatively full featured. As a result, it may no longer be -the simplest example of how to implement a Fieldtype/Inputfield, though it is very -effective and useful. - -MapMarker also has a corresponding Inputfield and Markup module, named -InputfieldMapMarker and MarkupGoogleMap. When you install FieldtypeMapMarker, the -Inputfield will also be installed and used for input on the admin side. Installation -of MarkupGoogleMap is optional. It provides a simple way to render Google maps with -the data managed by FieldtypeMapMarker. - -This Fieldtype has a [support forum](http://processwire.com/talk/index.php/topic,752.0.html) - -## Using Map Marker - -### How to install - -1. Copy all of the files for this module into /site/modules/FieldtypeMapMarker/ - -2. In your admin, go to the Modules screen and "check for new modules." Click *install* - for the Map Marker Fieldtype. - -3. In your admin, go to Setup > Fields > Add New Field. Choose MapMarker as the type. - If you are not sure what to name your field, simply "map" is a good one! Once created, - configure the settings on the *input* tab. - -4. Add your new "map" field to one or more templates, as you would any other field. - -### How to use from the page editor - -1. Create or edit a page using one of the templates you added the "map" field to. - -2. Type in a location or address into the "address" box for the map field. Then click - outside of the address, and the Javascript geocoder should automatically populate the - latitude, longitude and map location. The Google geocoder will accept full addresses - or known location names. For instance, you could type in "Disney Land" and it knows - how to find locations like that. - -3. The geocoding also works in reverse. You may drag the map marker wherever you want - and it will populate the address field for you. You may also populate the latitude, - longitude and zoom fields manually if you like. Unchecking the box between address - and latitude disables the geocoder. - -### How to use from the API, in your template files - -In your template files, you can utilize this data for your own Google Maps (or anything -else that you might need latitude/longitude for). - -Lets assume that your field is called 'map'. Here is how you would access the -components of it from the API: -``````````` -echo $page->map->address; // outputs the address you entered -echo $page->map->lat; // outputs the latitude -echo $page->map->lng; // outputs the longitude -echo $page->map->zoom; // outputs the zoom level -````````` - -------------- - -## Markup Google Map - -This package also comes with a module called MarkupGoogleMap. It provides a simple means -of outputting a Google Map based on the data managed by FieldtypeMapMarker. To install, -simply click "install" for the Google Maps (Markup) module. This is a Markup module, -meaning it exists primarily to generate markup for output on the front-end of your site. - -### How to use - -Add this somewhere before your closing `` tag: -````````` - -````````` - -In the location where you want to output your map, place the following in your template file: -````````` -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($page, 'map'); -````````` -In the above, $page is the Page object that has the 'map' field. Rreplace 'map' with the name of -your FieldtypeMap field - -To render a map with multiple markers on it, specify a PageArray rather than a single $page: -````````` -$items = $pages->find("template=something, map!='', sort=title"); -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($items, 'map'); -````````` - -To specify options, provide a 3rd argument with an options array: -````````` -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($items, 'map', array('height' => '500px')); -````````` - -### Options - -Here is a list of all possible options (with defaults shown): - -`width` -Width of the map (type: string; default: 100%). - -`height` -Height of the map (type: string; default: 300px) - -`zoom` -Zoom level 1-25 (type: integer; default: from your field settings) - -`type` -Map type: ROADMAP, HYBRID or SATELLITE (type: string; default: from your field settings) - -`id` -Map ID attribute (type: string; default: mgmap) - -`class` -Map class attribute (type: string; default: MarkupGoogleMap) - -`lat` -Map center latitude (type: string|float; default: from your field settings) - -`lng` -Map center longitude (type: string|float; default: from your field settings) - -`useStyles` -Whether to populate inline styles to the map div for width/height (type: boolean; default: true). -Set to false only if you will style the map div yourself. - -`useMarkerSettings` -Makes single-marker map use marker settings rather than map settings (type: boolean; default: true). - -`markerLinkField` -Page field to use for the marker link, or blank to not link (type: string; default: url). - -`markerTitleField` -Page field to use for the marker title, or blank not to use a marker title (type: string; default: title). - -`fitToMarkers` -When multiple markers are present, set map to automatically adjust to fit to the given markers (type: boolean; default: true). - ---------- - diff --git a/site/modules/FieldtypeMapMarker/FieldtypeMapMarker.module b/site/modules/FieldtypeMapMarker/FieldtypeMapMarker.module deleted file mode 100644 index 8b2dfb6..0000000 --- a/site/modules/FieldtypeMapMarker/FieldtypeMapMarker.module +++ /dev/null @@ -1,299 +0,0 @@ - 'Map Marker', - 'version' => 300, - 'summary' => 'Field that stores an address with latitude and longitude coordinates and has built-in geocoding capability with Google Maps API.', - 'installs' => 'InputfieldMapMarker', - 'icon' => 'map-marker', - ); - } - - /** - * Include our MapMarker class, which serves as the value for fields of type FieldtypeMapMarker - * - */ - public function __construct() { - parent::__construct(); - require_once(dirname(__FILE__) . '/MapMarker.php'); - } - - public function set($key, $value) { - /* - if($key === 'googleApiKey' && strpos($this->wire('config')->httpHost, 'localhost') !== false) { - // disable API key when in localhost environment - if($this->wire('page')->template == 'admin') $value = ''; - } - */ - return parent::set($key, $value); - } - - public function getGoogleMapsURL() { - $url = 'https://maps.google.com/maps/api/js'; - $key = $this->get('googleApiKey'); - if($key) $url .= "?key=$key"; - return $url; - } - - /** - * Return the Inputfield required by this Fieldtype - * - * @param Page $page - * @param Field $field - * @return InputfieldMapMarker - * - */ - public function getInputfield(Page $page, Field $field) { - /** @var InputfieldMapMarker $inputfield */ - $inputfield = $this->wire()->modules->get('InputfieldMapMarker'); - $inputfield->set('googleApiKey', $this->get('googleApiKey')); - return $inputfield; - } - - /** - * Return all compatible Fieldtypes - * - * @param Field $field - * @return null - * - */ - public function ___getCompatibleFieldtypes(Field $field) { - // there are no other fieldtypes compatible with this one - return null; - } - - /** - * Sanitize value for runtime - * - * @param Page $page - * @param Field $field - * @param MapMarker $value - * @return MapMarker - * - */ - public function sanitizeValue(Page $page, Field $field, $value) { - - // if it's not a MapMarker, then just return a blank MapMarker - if(!$value instanceof MapMarker) $value = $this->getBlankValue($page, $field); - - // if the address changed, tell the $page that this field changed - if($value->isChanged('address')) $page->trackChange($field->name); - - return $value; - } - - /** - * Get a blank value used by this fieldtype - * - * @param Page $page - * @param Field $field - * @return MapMarker - * - */ - public function getBlankValue(Page $page, Field $field) { - $value = new MapMarker(); - $this->wire($value); - return $value; - } - - /** - * Given a raw value (value as stored in DB), return the value as it would appear in a Page object - * - * @param Page $page - * @param Field $field - * @param string|int|array $value - * @return MapMarker - * - */ - public function ___wakeupValue(Page $page, Field $field, $value) { - - // get a blank MapMarker instance - $marker = $this->getBlankValue($page, $field); - - if("$value[lat]" === "0") $value['lat'] = ''; - if("$value[lng]" === "0") $value['lng'] = ''; - - // populate the marker - $marker->address = $value['data']; - $marker->lat = $value['lat']; - $marker->lng = $value['lng']; - $marker->status = $value['status']; - $marker->zoom = $value['zoom']; - $marker->setTrackChanges(true); - - return $marker; - } - - /** - * Given an 'awake' value, as set by wakeupValue, convert the value back to a basic type for storage in DB. - * - * @param Page $page - * @param Field $field - * @param string|int|array|object $value - * @return array - * @throws WireException - * - */ - public function ___sleepValue(Page $page, Field $field, $value) { - - $marker = $value; - - if(!$marker instanceof MapMarker) { - throw new WireException("Expecting an instance of MapMarker"); - } - - // if the address was changed, then force it to geocode the new address - if($marker->isChanged('address') && $marker->address && $marker->status != MapMarker::statusNoGeocode) { - $marker->geocode(); - } - - $sleepValue = array( - 'data' => $marker->address, - 'lat' => strlen($marker->lat) ? $marker->lat : 0, - 'lng' => strlen($marker->lng) ? $marker->lng : 0, - 'status' => $marker->status, - 'zoom' => $marker->zoom - ); - - return $sleepValue; - } - - - /** - * Return the database schema in specified format - * - * @param Field $field - * @return array - * - */ - public function getDatabaseSchema(Field $field) { - - // get the default schema - $schema = parent::getDatabaseSchema($field); - - $schema['data'] = "VARCHAR(255) NOT NULL DEFAULT ''"; // address (reusing the 'data' field from default schema) - $schema['lat'] = "FLOAT(10,6) NOT NULL DEFAULT 0"; // latitude - $schema['lng'] = "FLOAT(10,6) NOT NULL DEFAULT 0"; // longitude - $schema['status'] = "TINYINT NOT NULL DEFAULT 0"; // geocode status - $schema['zoom'] = "TINYINT NOT NULL DEFAULT 0"; // zoom level (schema v1) - - $schema['keys']['latlng'] = "KEY latlng (lat, lng)"; // keep an index of lat/lng - $schema['keys']['data'] = 'FULLTEXT KEY `data` (`data`)'; - $schema['keys']['zoom'] = "KEY zoom (zoom)"; - - if($field->id) $this->updateDatabaseSchema($field, $schema); - - return $schema; - } - - /** - * Update the DB schema, if necessary - * - * @param Field $field - * @param array $schema - * - */ - protected function updateDatabaseSchema(Field $field, array $schema) { - - $requiredVersion = 1; - $schemaVersion = (int) $field->get('schemaVersion'); - - if($schemaVersion >= $requiredVersion) { - // already up-to-date - return; - } - - if($schemaVersion == 0) { - // update schema to v1: add 'zoom' column - $schemaVersion = 1; - $database = $this->wire()->database; - $table = $database->escapeTable($field->getTable()); - $query = $database->prepare("SHOW TABLES LIKE '$table'"); - $query->execute(); - $row = $query->fetch(\PDO::FETCH_NUM); - $query->closeCursor(); - if(!empty($row)) { - $query = $database->prepare("SHOW COLUMNS FROM `$table` WHERE field='zoom'"); - $query->execute(); - if(!$query->rowCount()) try { - $database->exec("ALTER TABLE `$table` ADD zoom $schema[zoom] AFTER status"); - $this->message("Added 'zoom' column to '$field->table'"); - } catch(\Exception $e) { - $this->error($e->getMessage()); - } - } - } - - $field->set('schemaVersion', $schemaVersion); - $field->save(); - } - - /** - * Match values for PageFinder - * - * @param PageFinderDatabaseQuerySelect|DatabaseQuerySelect $query - * @param string $table - * @param string $subfield - * @param string $operator - * @param string $value - * @return DatabaseQuerySelect - * - */ - public function getMatchQuery($query, $table, $subfield, $operator, $value) { - if(!$subfield || $subfield == 'address') $subfield = 'data'; - if($subfield != 'data' || $this->wire()->database->isOperator($operator)) { - // if dealing with something other than address, or operator is native to SQL, - // then let Fieldtype::getMatchQuery handle it instead - return parent::getMatchQuery($query, $table, $subfield, $operator, $value); - } - // if we get here, then we're performing either %= (LIKE and variations) or *= (FULLTEXT and variations) - $ft = new DatabaseQuerySelectFulltext($query); - $ft->match($table, $subfield, $operator, $value); - return $query; - } - - /** - * Module configuration - * - * @param array $data - * @return InputfieldWrapper - * - */ - public static function getModuleConfigInputfields(array $data) { - $inputfields = new InputfieldWrapper(); - if(wire()->config->demo) $data['googleApiKey'] = 'Not shown in demo mode'; - /** @var InputfieldText $f */ - $f = wire()->modules->get('InputfieldText'); - $f->attr('name', 'googleApiKey'); - $f->label = __('Google Maps API Key'); - $f->icon = 'map'; - $f->description = sprintf(__('[Click here](%s) for instructions from Google on how to obtain an API key.'), - 'https://developers.google.com/maps/documentation/javascript/get-api-key'); - $f->attr('value', isset($data['googleApiKey']) ? $data['googleApiKey'] : ''); - $inputfields->add($f); - return $inputfields; - } -} \ No newline at end of file diff --git a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.css b/site/modules/FieldtypeMapMarker/InputfieldMapMarker.css deleted file mode 100644 index 8e5cd8d..0000000 --- a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.css +++ /dev/null @@ -1,73 +0,0 @@ -.InputfieldMapMarker input[type=number], -.InputfieldMapMarker input[type=text] { - width: 99.5%; -} - -.InputfieldMapMarkerToggle span { - display: none; -} - -.InputfieldMapMarkerAddress { - float: left; - width: 70%; - padding-right: 2%; -} - -.InputfieldMapMarkerToggle { - float: left; - width: 28%; -} - -.InputfieldMapMarkerLat, -.InputfieldMapMarkerLng { - width: 42%; - float: left; - padding-right: 2%; -} - -.InputfieldMapMarkerZoom { - float: left; - width: 10%; -} - -.InputfieldMapMarker .notes { - clear: both; -} - -.InputfieldMapMarkerMap { - width: 100%; - height: 300px; - clear: left; -} - -@media only screen and (min-width: 768px) { - - .InputfieldMapMarkerAddress { - width: 38%; - padding-right: 1%; - } - - .InputfieldMapMarkerToggle { - width: 2%; - padding-right: 0.5%; - position: relative; - } - - .InputfieldMapMarkerToggle strong { - /* hide geocode label */ - display: none; - } - - .InputfieldMapMarkerLat, - .InputfieldMapMarkerLng { - width: 23%; - padding-right: 1%; - } - - .InputfieldMapMarkerZoom { - float: left; - width: 9.5%; - } - -} - diff --git a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.js b/site/modules/FieldtypeMapMarker/InputfieldMapMarker.js deleted file mode 100644 index d0724d3..0000000 --- a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Display a Google Map and pinpoint a location for InputfieldMapMarker - * - */ - -var InputfieldMapMarker = { - - options: { - zoom: 12, // mats, previously 5 - draggable: true, // +mats - center: null, - //key: config.InputfieldMapMarker.googleApiKey, - mapTypeId: google.maps.MapTypeId.HYBRID, - scrollwheel: false, - mapTypeControlOptions: { - style: google.maps.MapTypeControlStyle.DROPDOWN_MENU - }, - scaleControl: false - }, - - init: function(mapId, lat, lng, zoom, mapType) { - - var options = InputfieldMapMarker.options; - - if(zoom < 1) zoom = 12; - options.center = new google.maps.LatLng(lat, lng); - options.zoom = parseInt(zoom); - - if(mapType == 'SATELLITE') options.mapTypeId = google.maps.MapTypeId.SATELLITE; - else if(mapType == 'ROADMAP') options.mapTypeId = google.maps.MapTypeId.ROADMAP; - - var map = new google.maps.Map(document.getElementById(mapId), options); - - var marker = new google.maps.Marker({ - position: options.center, - map: map, - draggable: options.draggable - }); - - var $map = $('#' + mapId); - var $lat = $map.siblings(".InputfieldMapMarkerLat").find("input[type=text]"); - var $lng = $map.siblings(".InputfieldMapMarkerLng").find("input[type=text]"); - var $addr = $map.siblings(".InputfieldMapMarkerAddress").find("input[type=text]"); - var $addrJS = $map.siblings(".InputfieldMapMarkerAddress").find("input[type=hidden]"); - var $toggle = $map.siblings(".InputfieldMapMarkerToggle").find("input[type=checkbox]"); - var $zoom = $map.siblings(".InputfieldMapMarkerZoom").find("input[type=number]"); - var $notes = $map.siblings(".notes"); - - $lat.val(marker.getPosition().lat()); - $lng.val(marker.getPosition().lng()); - $zoom.val(map.getZoom()); - - google.maps.event.addListener(marker, 'dragend', function(event) { - var geocoder = new google.maps.Geocoder(); - var position = this.getPosition(); - $lat.val(position.lat()); - $lng.val(position.lng()); - if($toggle.is(":checked")) { - geocoder.geocode({ 'latLng': position }, function(results, status) { - if(status == google.maps.GeocoderStatus.OK && results[0]) { - $addr.val(results[0].formatted_address); - $addrJS.val($addr.val()); - } - $notes.text(status); - }); - } - }); - - google.maps.event.addListener(map, 'zoom_changed', function() { - $zoom.val(map.getZoom()); - }); - - $addr.blur(function() { - if(!$toggle.is(":checked")) return true; - var geocoder = new google.maps.Geocoder(); - geocoder.geocode({ 'address': $(this).val()}, function(results, status) { - if(status == google.maps.GeocoderStatus.OK && results[0]) { - var position = results[0].geometry.location; - map.setCenter(position); - marker.setPosition(position); - $lat.val(position.lat()); - $lng.val(position.lng()); - $addrJS.val($addr.val()); - } - $notes.text(status); - }); - return true; - }); - - $zoom.change(function() { - map.setZoom(parseInt($(this).val())); - }); - - $toggle.click(function() { - if($(this).is(":checked")) { - $notes.text('Geocode ON'); - // google.maps.event.trigger(marker, 'dragend'); - $addr.trigger('blur'); - } else { - $notes.text('Geocode OFF'); - } - return true; - }); - - // added by diogo to solve the problem of maps not rendering correctly in hidden elements - // trigger a resize on the map when either the tab button or the toggle field bar are pressed - - // get the tab element where this map is integrated - var $map = $('#' + mapId); - var $tab = $('#_' + $map.closest('.InputfieldFieldsetTabOpen').attr('id')); - // get the inputfield where this map is integrated and add the tab to the stack - var $inputFields = $map.closest('.Inputfield').find('.InputfieldStateToggle').add($tab); - - $inputFields.on('click',function(){ - // give it time to open - window.setTimeout(function(){ - google.maps.event.trigger(map,'resize'); - map.setCenter(options.center); - }, 200); - }); - - } -}; - -$(document).ready(function() { - $(".InputfieldMapMarkerMap").each(function() { - var $t = $(this); - InputfieldMapMarker.init($t.attr('id'), $t.attr('data-lat'), $t.attr('data-lng'), $t.attr('data-zoom'), $t.attr('data-type')); - }); -}); diff --git a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.module b/site/modules/FieldtypeMapMarker/InputfieldMapMarker.module deleted file mode 100644 index 5309d84..0000000 --- a/site/modules/FieldtypeMapMarker/InputfieldMapMarker.module +++ /dev/null @@ -1,377 +0,0 @@ - 'Map Marker', - 'version' => 300, - 'summary' => "Provides input for the MapMarker Fieldtype", - 'requires' => 'FieldtypeMapMarker', - 'icon' => 'map-marker', - ); - } - - const defaultAddr = 'Castaway Cay'; - - /** - * Just in case this Inputfield is being used separately from FieldtypeMapmarker, we include the MapMarker class - * - */ - public function __construct() { - require_once(dirname(__FILE__) . '/MapMarker.php'); - $this->set('defaultAddr', self::defaultAddr); - $this->set('defaultZoom', 12); - $this->set('defaultType', 'HYBRID'); - $this->set('defaultLat', ''); - $this->set('defaultLng', ''); - $this->set('height', 300); - $this->set('googleApiKey', ''); - parent::__construct(); - } - - /** - * Set an attribute to this Inputfield - * - * In this case, we just capture the 'value' attribute and make sure it's something valid - * - * @param string $key - * @param mixed $value - * @return $this - * @throws WireException - * - */ - public function setAttribute($key, $value) { - - if($key == 'value' && !$value instanceof MapMarker && !is_null($value)) { - throw new WireException("This input only accepts a MapMarker for its value"); - } - - return parent::setAttribute($key, $value); - } - - /** - * Is the value empty? - * - * @return bool - * - */ - public function isEmpty() { - return (!$this->value || ((float) $this->value->lat) === 0.0); - } - - /** - * @return FieldtypeMapMarker - * - */ - public function fieldtype() { - /** @var FieldtypeMapMarker $fieldtype */ - $fieldtype = $this->wire()->modules->get('FieldtypeMapMarker'); - return $fieldtype; - } - - public function renderReady(Inputfield $parent = null, $renderValueMode = false) { - /* - $url = 'https://maps.google.com/maps/api/js'; - $key = $this->get('googleApiKey'); - if($key) $url .= "?key=$key"; - */ - $url = $this->fieldtype()->getGoogleMapsURL(); - $this->wire()->config->scripts->add($url); - return parent::renderReady($parent, $renderValueMode); - } - - /** - * Render the markup needed to draw the Inputfield - * - * @return string - * - */ - public function ___render() { - - $sanitizer = $this->wire()->sanitizer; - $adminTheme = $this->wire()->adminTheme; - - $name = $this->attr('name'); - $id = $this->attr('id'); - $marker = $this->attr('value'); - - if($marker->lat == 0.0) $marker->lat = $this->defaultLat; - if($marker->lng == 0.0) $marker->lng = $this->defaultLng; - if(!$marker->zoom) $marker->zoom = $this->defaultZoom; - - $address = $sanitizer->entities($marker->address); - $toggleChecked = $marker->status != MapMarker::statusNoGeocode ? " checked='checked'" : ''; - $status = $marker->status == MapMarker::statusNoGeocode ? 0 : $marker->status; - $mapType = $this->defaultType; - $height = $this->height ? (int) $this->height : 300; - $classes = array('input' => '', 'checkbox' => ''); - - if($adminTheme && method_exists($adminTheme, 'getClass')) { - foreach(array_keys($classes) as $key) { - $classes[$key] = $adminTheme->getClass($key); - } - } - - $labels = array( - 'addr' => $this->_('Address'), - 'lat' => $this->_('Latitude'), - 'lng' => $this->_('Longitude'), - 'geo' => $this->_('Geocode?'), - 'zoom' => $this->_('Zoom') - ); - - foreach($labels as $key => $label) { - $labels[$key] = $sanitizer->entities1($label); - } - - $out = <<< _OUT - - - -

- - -

- -

- -

- -

- -

- -

- -

- -

- -

- - -_OUT; - - $out .= - "
" . - "
"; - - $this->notes = $marker->statusString; - - if(!$this->get('googleApiKey')) { - $config = $this->wire()->config; - $msg = $sanitizer->entities1($this->_('Please setup a Google Maps API key in the FieldtypeMapMarker module settings')); - if($this->wire()->user->isSuperuser()) { - $link = ""; - $msg = "$link$msg"; - $this->warning($msg, Notice::allowMarkup); - } else { - $this->warning($msg); - } - } - - return $out; - } - - /** - * Process the input after a form submission - * - * @param WireInputData $input - * @return $this - * - */ - public function ___processInput(WireInputData $input) { - - $name = $this->attr('name'); - $marker = $this->attr('value'); - - if(!isset($input->$name)) { - return $this; - } - - if($input->$name == $this->defaultAddr) { - $marker->set('address', ''); - } else { - $marker->set('address', $input->$name); - } - - $lat = (float) $input["_{$name}_lat"]; - $lng = (float) $input["_{$name}_lng"]; - $defaultLat = (float) $this->defaultLat; - $defaultLng = (float) $this->defaultLng; - $precision = 4; - - if( ((string) round($lat, $precision)) != ((string) round($defaultLat, $precision)) || - ((string) round($lng, $precision)) != ((string) round($defaultLng, $precision))) { - $marker->set('lat', $lat); - $marker->set('lng', $lng); - } else { - // $this->message("Kept lat/lng at unset value", Notice::debug); - } - - $zoom = $input["_{$name}_zoom"]; - if($zoom > -1 && $zoom < 30) $marker->zoom = (int) $zoom; - - $status = $input["_{$name}_status"]; - if(is_null($status)) { - $marker->set('status', MapMarker::statusNoGeocode); // disable geocode - } else { - $marker->set('status', (int) $status); - } - - // if the address changed, then redo the geocoding. - // while we do this in the Fieldtype, we also do it here in case this Inputfield is used on it's own. - // the MapMarker class checks to make sure it doesn't do the same geocode twice. - if($marker->isChanged('address') && $marker->address && $marker->status != MapMarker::statusNoGeocode) { - // double check that the address wasn't already populated by the JS geocoder - // this prevents user-dragged markers that don't geocode to an exact location from getting - // unintentionally moved by the PHP-side geocoder - if($input["_{$name}_js_geocode_address"] == $marker->address) { - // prevent the geocoder from running in the fieldtype - $marker->skipGeocode = true; - $this->message('Skipping geocode (already done by JS geocoder)', Notice::debug); - } else { - $marker->geocode(); - } - } - - return $this; - } - - /** - * @return InputfieldWrapper - * - */ - public function ___getConfigInputfields() { - $modules = $this->wire()->modules; - $inputfields = parent::___getConfigInputfields(); - - /** @var InputfieldText $field */ - $field = $modules->get('InputfieldText'); - $field->attr('name', 'defaultAddr'); - $field->label = $this->_('Default Address'); - $field->description = $this->_('This will be geocoded to become the starting point of the map.'); - $field->attr('value', $this->defaultAddr); - $field->notes = $this->_('When modifying the default address, please make the Latitude and Longitude fields below blank, which will force the system to geocode your new address.'); - $inputfields->add($field); - - if(!$this->defaultLat && !$this->defaultLng) { - $m = new MapMarker(); - $m->address = $this->defaultAddr; - $status = $m->geocode(); - if($status > 0) { - $this->defaultLat = $m->lat; - $this->defaultLng = $m->lng; - $this->message($this->_('Geocoded your default address. Please hit save once again to commit the new default latitude and longitude.')); - } - } - - /** @var InputfieldText $field */ - $field = $modules->get('InputfieldText'); - $field->attr('name', 'defaultLat'); - $field->label = $this->_('Default Latitude'); - $field->attr('value', $this->defaultLat); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldText $field */ - $field = $modules->get('InputfieldText'); - $field->attr('name', 'defaultLng'); - $field->label = $this->_('Default Longitude'); - $field->attr('value', $this->defaultLng); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldRadios $field */ - $field = $modules->get('InputfieldRadios'); - $field->attr('name', 'defaultType'); - $field->label = $this->_('Default Map Type'); - $field->addOption('HYBRID', $this->_('Hybrid')); - $field->addOption('ROADMAP', $this->_('Road Map')); - $field->addOption('SATELLITE', $this->_('Satellite')); - $field->attr('value', $this->defaultType); - $field->optionColumns = 1; - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldInteger $field */ - $field = $modules->get('InputfieldInteger'); - $field->attr('name', 'height'); - $field->label = $this->_('Map Height (in pixels)'); - $field->attr('value', $this->height); - $field->attr('type', 'number'); - $field->columnWidth = 50; - $inputfields->add($field); - - /** @var InputfieldInteger $field */ - $field = $modules->get('InputfieldInteger'); - $field->attr('name', 'defaultZoom'); - $field->label = $this->_('Default Zoom'); - $field->description = $this->_('Enter a value between 1 and 23. The highest zoom level is typically somewhere between 19-23, depending on the location being zoomed and how much data Google has for the location.'); // Zoom level description - $field->attr('value', $this->defaultZoom); - $field->attr('type', 'number'); - $inputfields->add($field); - - /** @var InputfieldMarkup $field */ - $field = $modules->get('InputfieldMarkup'); - $field->label = $this->_('API Notes'); - $field->description = $this->_('You can access individual values from this field using the following from your template files:'); - $field->value = - "
" .
-			"\$page->{$this->name}->address\n" . 
-			"\$page->{$this->name}->lat\n" . 
-			"\$page->{$this->name}->lng\n" . 
-			"\$page->{$this->name}->zoom" . 
-			"
"; - - $inputfields->add($field); - - return $inputfields; - } - -} \ No newline at end of file diff --git a/site/modules/FieldtypeMapMarker/MapMarker.php b/site/modules/FieldtypeMapMarker/MapMarker.php deleted file mode 100644 index cb1b79a..0000000 --- a/site/modules/FieldtypeMapMarker/MapMarker.php +++ /dev/null @@ -1,126 +0,0 @@ - 'N/A', - 1 => 'OK', - 2 => 'OK_ROOFTOP', - 3 => 'OK_RANGE_INTERPOLATED', - 4 => 'OK_GEOMETRIC_CENTER', - 5 => 'OK_APPROXIMATE', - - -1 => 'UNKNOWN', - -2 => 'ZERO_RESULTS', - -3 => 'OVER_QUERY_LIMIT', - -4 => 'REQUEST_DENIED', - -5 => 'INVALID_REQUEST', - - -100 => 'Geocode OFF', // RCD - ); - - protected $geocodedAddress = ''; - - public function __construct() { - parent::__construct(); - $this->set('lat', ''); - $this->set('lng', ''); - $this->set('address', ''); - $this->set('status', 0); - $this->set('zoom', 0); - // temporary runtime property to indicate the geocode should be skipped - $this->set('skipGeocode', false); - $this->set('statusString', ''); - } - - public function set($key, $value) { - - if($key == 'lat' || $key == 'lng') { - // if value isn't numeric, then it's not valid: make it blank - if(strpos($value, ',') !== false) $value = str_replace(',', '.', $value); // convert 123,456 to 123.456 - if(!is_numeric($value)) $value = ''; - - } else if($key == 'address') { - $value = $this->wire()->sanitizer->text($value); - - } else if($key == 'status') { - $value = (int) $value; - if(!isset($this->geocodeStatuses[$value])) $value = -1; // -1 = unknown - } else if($key == 'zoom') { - $value = (int) $value; - } - - return parent::set($key, $value); - } - - public function get($key) { - if($key == 'statusString') return str_replace('_', ' ', $this->geocodeStatuses[$this->status]); - return parent::get($key); - } - - public function geocode() { - if($this->skipGeocode) return -100; - - // check if address was already geocoded - if($this->geocodedAddress == $this->address) return $this->status; - $this->geocodedAddress = $this->address; - - $url = "https://maps.googleapis.com/maps/api/geocode/json?address=" . urlencode($this->address); - - /** @var FieldtypeMapMarker $fieldtype */ - $fieldtype = $this->modules->get('FieldtypeMapMarker'); - $apiKey = $fieldtype->get('googleApiKey'); - if($apiKey) $url .= "&key=$apiKey"; - $http = new WireHttp(); - $json = $http->getJSON($url, true); - if(empty($json['status'])) $json['status'] = 'No response'; - - if($json['status'] != 'OK') { - $this->error("Error geocoding address: $json[status] ($url)"); - if(isset($json['status'])) $this->status = (int) array_search($json['status'], $this->geocodeStatuses); - else $this->status = -1; - $this->lat = 0; - $this->lng = 0; - return $this->status; - } - - $geometry = $json['results'][0]['geometry']; - $location = $geometry['location']; - $locationType = $geometry['location_type']; - - $this->lat = $location['lat']; - $this->lng = $location['lng']; - - $statusString = $json['status'] . '_' . $locationType; - $status = array_search($statusString, $this->geocodeStatuses); - if($status === false) $status = 1; // OK - - $this->status = $status; - $this->message("Geocode {$this->statusString}: '{$this->address}'"); - - return $this->status; - } - - /** - * If accessed as a string, then just output the lat, lng coordinates - * - */ - public function __toString() { - return "$this->address ($this->lat, $this->lng, $this->zoom) [$this->statusString]"; - } - -} \ No newline at end of file diff --git a/site/modules/FieldtypeMapMarker/MarkupGoogleMap.js b/site/modules/FieldtypeMapMarker/MarkupGoogleMap.js deleted file mode 100644 index 7d89dae..0000000 --- a/site/modules/FieldtypeMapMarker/MarkupGoogleMap.js +++ /dev/null @@ -1,213 +0,0 @@ -/** - * ProcessWire Map Markup (JS) - * - * Renders maps for the FieldtypeMapMarker module - * - * ProcessWire 3.x - * Copyright (C) 2023 by Ryan Cramer - * Licensed under MPL 2.0 - * - * http://processwire.com - * - * Javascript Usage: - * ================= - * var map = new MarkupGoogleMap(); - * map.setOption('any-google-maps-option', 'value'); - * map.setOption('zoom', 12); // example - * - * // init(container ID, latitude, longitude): - * map.init('#map-div', 26.0936823, -77.5332796); - * - * // addMarker(latitude, longitude, optional URL, optional URL to icon file): - * map.addMarker(26.0936823, -77.5332796, 'en.wikipedia.org/wiki/Castaway_Cay', ''); - * map.addMarker(...you may have as many of these as you want...); - * - * // optionally fit the map to the bounds of the markers you added - * map.fitToMarkers(); - * - */ - -function MarkupGoogleMap() { - - this.map = null; - this.markers = []; - this.numMarkers = 0; - this.icon = ''; - this.iconHover = ''; - this.shadow = ''; - - this.hoverBox = null; - this.hoverBoxOffsetTop = 0; - this.hoverBoxOffsetLeft = 0; - - this.options = { - zoom: 10, - center: null, - mapTypeId: google.maps.MapTypeId.ROADMAP, - scrollwheel: false, - mapTypeControlOptions: { - style: google.maps.MapTypeControlStyle.DROPDOWN_MENU - }, - scaleControl: false, - - // disable points of interest - styles: [{ - featureType: "poi", - stylers: [ { visibility: "off" } ] - }] - }; - - - this._currentURL = ''; - - this.init = function(mapID, lat, lng) { - if(lat != 0) this.options.center = new google.maps.LatLng(lat, lng); - this.map = new google.maps.Map(document.getElementById(mapID), this.options); - } - - this.setOption = function(key, value) { - this.options[key] = value; - } - - this.setIcon = function(url) { - this.icon = url; - } - - this.setIconHover = function(url) { - this.iconHover = url; - } - - this.setShadow = function(url) { - this.shadow = url; - } - - this.setHoverBox = function(markup) { - - if(!markup.length) { - this.hoverBox = null; - return; - } - - this.hoverBox = $(markup); - var $hoverBox = this.hoverBox; - - this.hoverBoxOffsetTop = parseInt($hoverBox.attr('data-top')); - this.hoverBoxOffsetLeft = parseInt($hoverBox.attr('data-left')); - - $("body").append($hoverBox); - - // keep it hidden/out of the way until needed - $hoverBox.css({ - position: 'absolute', - left: 0, - top: '-100px' - }); - - $hoverBox.mouseout(function() { - $hoverBox.hide(); - }).click(function() { - if(this._currentURL.length > 0) window.location.href = this._currentURL; - }); - } - - this.addMarker = function(lat, lng, url, title, icon, shadow) { - if(lat == 0.0) return; - - var latLng = new google.maps.LatLng(lat, lng); - var zIndex = 99999 + this.numMarkers; - - var markerOptions = { - position: latLng, - map: this.map, - linkURL: '', - zIndex: zIndex - }; - - if(typeof icon !== "undefined" && icon.length > 0) markerOptions.icon = icon; - else if(this.icon) markerOptions.icon = this.icon; - - // console.log(markerOptions); - - if(typeof shadow !== "undefined" && shadow.length > 0) markerOptions.shadow = shadow; - else if(this.shadow.length > 0) markerOptions.shadow = this.shadow; - - var marker = new google.maps.Marker(markerOptions); - - if(url.length > 0) marker.linkURL = url; - if(this.hoverBox) marker.hoverBoxTitle = title; - else marker.setTitle(title); - - this.markers[this.numMarkers] = marker; - this.numMarkers++; - - if(marker.linkURL.length > 0) { - google.maps.event.addListener(marker, 'click', function(e) { - window.location.href = marker.linkURL; - }); - } - - if(markerOptions.icon !== "undefined" && this.iconHover) { - var iconHover = this.iconHover; - google.maps.event.addListener(marker, 'mouseover', function(e) { - marker.setIcon(iconHover); - }); - google.maps.event.addListener(marker, 'mouseout', function(e) { - marker.setIcon(markerOptions.icon); - }); - } - - if(this.hoverBox) { - - var $hoverBox = this.hoverBox; - var offsetTop = this.hoverBoxOffsetTop; - var offsetLeft = this.hoverBoxOffsetLeft; - - var mouseMove = function(e) { - $hoverBox.css({ - 'top': e.pageY + offsetTop, - 'left': e.pageX + offsetLeft - }); - }; - - // console.log($hoverBox); - - google.maps.event.addListener(marker, 'mouseover', function(e) { - this._currentURL = url; - $hoverBox.html("" + marker.hoverBoxTitle + "") - .css('top', '0px') - .css('left', '0px') - .css('display', 'block') - .css('width', 'auto') - .css('z-index', 9999); - $hoverBox.show(); - - $(document).mousemove(mouseMove); - }); - - google.maps.event.addListener(marker, 'mouseout', function(e) { - $hoverBox.hide(); - $(document).unbind("mousemove", mouseMove); - }); - - } - } - - this.fitToMarkers = function() { - - var bounds = new google.maps.LatLngBounds(); - var map = this.map; - - for(var i = 0; i < this.numMarkers; i++) { - var latLng = this.markers[i].position; - bounds.extend(latLng); - } - - map.fitBounds(bounds); - - - var listener = google.maps.event.addListener(map, "idle", function() { - if(map.getZoom() < 2) map.setZoom(2); - google.maps.event.removeListener(listener); - }); - } -} \ No newline at end of file diff --git a/site/modules/FieldtypeMapMarker/MarkupGoogleMap.module b/site/modules/FieldtypeMapMarker/MarkupGoogleMap.module deleted file mode 100644 index 0f426c9..0000000 --- a/site/modules/FieldtypeMapMarker/MarkupGoogleMap.module +++ /dev/null @@ -1,255 +0,0 @@ - tag: - * - * - * - * In the location where you want to output your map, do the following in your template file: - * - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($page, 'map'); // replace 'map' with the name of your FieldtypeMap field - * - * To render a map with multiple markers on it, specify a PageArray rather than a single $page: - * - * $items = $pages->find("template=something, map!='', sort=title"); - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($items, 'map'); - * - * To specify options, provide a 3rd argument with an options array: - * - * $map = $modules->get('MarkupGoogleMap'); - * echo $map->render($items, 'map', array('height' => '500px')); - * - * - * OPTIONS - * ======= - * Here is a list of all possible options (with defaults shown): - * - * // default width of the map - * 'width' => '100%' - * - * // default height of the map - * 'height' => '300px' - * - * // zoom level - * 'zoom' => 12 (or $field->defaultZoom) - * - * // map type: ROADMAP, HYBRID or SATELLITE - * 'type' => 'HYBRID' or $field->defaultType - * - * // map ID attribute - * 'id' => "mgmap" - * - * // map class attribute - * 'class' => "MarkupGoogleMap" - * - * // center latitude - * 'lat' => $field->defaultLat - * - * // center longitude - * 'lng' => $field->defaultLng - * - * // set to false only if you will style the map
yourself - * 'useStyles' => true - * - * // allows single-marker map to use marker settings rather than map settings - * 'useMarkerSettings' => true - * - * // field to use for the marker link, or blank to not link - * 'markerLinkField' => 'url' - * - * // field to use for the marker title - * 'markerTitleField' => 'title' - * - * // map will automatically adjust to fit to the given markers (when multiple markers) - * 'fitToMarkers' => true - * - * // use hover box? When true, shows a tooltip-type box when you hover the marker, populated with the markerTitleField - * // this is often more useful than the default presentation google maps uses - * 'useHoverBox' => false - * - * // when useHoverBox is true, you can specify the markup used for it. Use the following (which is the default) as your starting point: - * 'hoverBoxMarkup' => "
", - * - * // FUll URL to icon file to use for markers. Blank=use default Google marker icon. - * 'icon' => '', - * - * // Any extra javascript initialization code you want to occur before the map itself is drawn - * 'init' => '', - * - */ - -class MarkupGoogleMap extends WireData implements Module { - - public static function getModuleInfo() { - return array( - 'title' => 'Map Markup (Google Maps)', - 'version' => 300, - 'summary' => 'Renders Google Maps for the MapMarker Fieldtype', - 'requires' => 'FieldtypeMapMarker', - ); - } - - /** - * Include our MapMarker class, which serves as the value for fields of type FieldtypeMapMarker - * - */ - public function init() { - require_once(dirname(__FILE__) . '/MapMarker.php'); - } - - /** - * Get associative array of map options - * - * @param string $fieldName - * @return array - * @throws WireException - * - */ - public function getOptions($fieldName) { - - static $n = 0; - $field = $this->wire()->fields->get($fieldName); - if(!$field) throw new WireException("Unknown field: $fieldName"); - - return array( - 'useStyles' => true, - 'fitToMarkers' => true, - 'useMarkerSettings' => true, - 'useHoverBox' => false, - 'hoverBoxMarkup' => "
", - 'markerLinkField' => 'url', - 'markerTitleField' => 'title', - 'width' => '100%', - 'height' => $field->get('height'), - 'zoom' => $field->get('defaultZoom') ? (int) $field->get('defaultZoom') : 12, - 'type' => $field->get('defaultType') ? $field->get('defaultType') : 'HYBRID', - 'id' => "mgmap" . (++$n), - 'class' => "MarkupGoogleMap", - 'lat' => $field->get('defaultLat'), - 'lng' => $field->get('defaultLng'), - 'icon' => '', // url to icon (blank=use default) - 'iconHover' => '', // url to icon when hovered (default=none) - 'shadow' => '', // url to icon shadow (blank=use default) - 'init' => '', // additional javascript code to insert in map initialization - 'n' => $n, - ); - } - - /** - * Get the script tag for loading Google Maps - * - * @return string - * @throws WireException - * - */ - public function getGMapScript() { - $url = 'https://maps.google.com/maps/api/js'; - $key = $this->wire()->modules->get('FieldtypeMapMarker')->get('googleApiKey'); - if($key) $url .= "?key=$key"; - return ""; - } - - /** - * Render map markup - * - * @param PageArray|Page $pageArray Page (or multiple pages in PageArray) containing map field - * @param string $fieldName Name of the map field - * @param array $options Options to adjust behavior - * @return string - * @throws WireException - * - */ - public function render($pageArray, $fieldName, array $options = array()) { - $config = $this->wire()->config; - - static $n = 0; - $n++; - - $defaultOptions = $this->getOptions($fieldName); - $options = array_merge($defaultOptions, $options); - - if($pageArray instanceof Page) { - $page = $pageArray; - $pageArray = new PageArray(); - $pageArray->add($page); - } - - $height = $options['height']; - $width = $options['width']; - if(empty($height)) $height = 300; - if(ctype_digit("$height")) $height .= "px"; - if(ctype_digit("$width")) $width .= "px"; - - $style = ''; - if($options['useStyles'] && !empty($height) && !empty($width)) { - $style = " style='width: $width; height: $height;'"; - } - - $lat = $options['lat']; - $lng = $options['lng']; - $zoom = $options['zoom'] > 0 ? (int) $options['zoom'] : $defaultOptions['zoom']; - $type = in_array($options['type'], array('ROADMAP', 'SATELLITE', 'HYBRID')) ? $options['type'] : 'HYBRID'; - - if($options['useMarkerSettings'] && (count($pageArray) == 1 || !$lat)) { - // single marker overrides lat, lng and zoom settings - $marker = $pageArray->first()->get($fieldName); - $lat = $marker->lat; - $lng = $marker->lng; - if($marker->zoom > 0) $zoom = (int) $marker->zoom; - } - - $id = $options['id']; - $out = ''; - - if($n === 1) { - $url = $config->urls('MarkupGoogleMap'); - $out .= ""; - } - - $out .= "
"; - - $out .= - ""; - - return $out; - } -} \ No newline at end of file diff --git a/site/modules/FieldtypeMapMarker/README.md b/site/modules/FieldtypeMapMarker/README.md deleted file mode 100644 index 21b9ce7..0000000 --- a/site/modules/FieldtypeMapMarker/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# FieldtypeMapMarker Module for ProcessWire - -This Fieldtype for ProcessWire holds an address or location name, and automatically -geocodes the address to latitude/longitude using Google Maps API. The resulting -values may be used to populate any kind of map (whether Google Maps or another). - -This Fieldtype was created to serve as an example of creating a custom Fieldtype and -Inputfield that contains multiple pieces of data. Though the Fieldtype has now gone -far beyond that and is relatively full featured. As a result, it may no longer be -the simplest example of how to implement a Fieldtype/Inputfield, though it is very -effective and useful. - -MapMarker also has a corresponding Inputfield and Markup module, named -InputfieldMapMarker and MarkupGoogleMap. When you install FieldtypeMapMarker, the -Inputfield will also be installed and used for input on the admin side. Installation -of MarkupGoogleMap is optional. It provides a simple way to render Google maps with -the data managed by FieldtypeMapMarker. - -This Fieldtype has a [support forum](http://processwire.com/talk/index.php/topic,752.0.html) - -## Using Map Marker - -### How to install - -1. Copy all of the files for this module into /site/modules/FieldtypeMapMarker/ - -2. In your admin, go to the Modules screen and "check for new modules." Click *install* - for the Map Marker Fieldtype. - -3. In your admin, go to Setup > Fields > Add New Field. Choose MapMarker as the type. - If you are not sure what to name your field, simply "map" is a good one! Once created, - configure the settings on the *input* tab. - -4. Add your new "map" field to one or more templates, as you would any other field. - -### How to use from the page editor - -1. Create or edit a page using one of the templates you added the "map" field to. - -2. Type in a location or address into the "address" box for the map field. Then click - outside of the address, and the Javascript geocoder should automatically populate the - latitude, longitude and map location. The Google geocoder will accept full addresses - or known location names. For instance, you could type in "Disney Land" and it knows - how to find locations like that. - -3. The geocoding also works in reverse. You may drag the map marker wherever you want - and it will populate the address field for you. You may also populate the latitude, - longitude and zoom fields manually if you like. Unchecking the box between address - and latitude disables the geocoder. - -### How to use from the API, in your template files - -In your template files, you can utilize this data for your own Google Maps (or anything -else that you might need latitude/longitude for). - -Lets assume that your field is called 'map'. Here is how you would access the -components of it from the API: -```php -echo $page->map->address; // outputs the address you entered -echo $page->map->lat; // outputs the latitude -echo $page->map->lng; // outputs the longitude -echo $page->map->zoom; // outputs the zoom level -``` - -------------- - -## Markup Google Map - -This package also comes with a module called MarkupGoogleMap. It provides a simple means -of outputting a Google Map based on the data managed by FieldtypeMapMarker. To install, -simply click "install" for the Google Maps (Markup) module. This is a Markup module, -meaning it exists primarily to generate markup for output on the front-end of your site. - -### How to use - -Add this somewhere before your closing `` tag: -```html - -``` - -In the location where you want to output your map, place the following in your template file: -```php -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($page, 'map'); -``` -In the above, $page is the Page object that has the 'map' field. Replace 'map' with the name of -your map field. - -To render a map with multiple markers on it, specify a PageArray rather than a single $page: -```php -$items = $pages->find("template=something, map!='', sort=title"); -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($items, 'map'); -```` - -To specify options, provide a 3rd argument with an options array: -```php -$map = $modules->get('MarkupGoogleMap'); -echo $map->render($items, 'map', array('height' => '500px')); -``` - -### Options - -Here is a list of all possible options (with defaults shown): - -`width` -Width of the map (type: string; default: 100%). - -`height` -Height of the map (type: string; default: 300px) - -`zoom` -Zoom level 1-25 (type: integer; default: from your field settings) - -`type` -Map type: ROADMAP, HYBRID or SATELLITE (type: string; default: from your field settings) - -`id` -Map ID attribute (type: string; default: mgmap) - -`class` -Map class attribute (type: string; default: MarkupGoogleMap) - -`lat` -Map center latitude (type: string|float; default: from your field settings) - -`lng` -Map center longitude (type: string|float; default: from your field settings) - -`useStyles` -Whether to populate inline styles to the map div for width/height (type: boolean; default: true). -Set to false only if you will style the map div yourself. - -`useMarkerSettings` -Makes single-marker map use marker settings rather than map settings (type: boolean; default: true). - -`markerLinkField` -Page field to use for the marker link, or blank to not link (type: string; default: url). - -`markerTitleField` -Page field to use for the marker title, or blank not to use a marker title (type: string; default: title). - -`fitToMarkers` -When multiple markers are present, set map to automatically adjust to fit to the given markers (type: boolean; default: true). - ---------- \ No newline at end of file