leafletSearchDependencies <- function() {
list(
html_dep_prod("fuse_js", "7.0.0"),
html_dep_prod("lfx-search", "4.0.0", has_style = TRUE, has_binding = TRUE)
)
}
#' Options for search control.
#' @param url url for search by ajax request, ex: `search.php?q=\{s\}`. Can be function that returns string for dynamic parameter setting.
#' @param sourceData function that fill _recordsCache, passed searching text by first param and callback in second.
#' @param jsonpParam jsonp param name for search by jsonp service, ex: "callback".
#' @param propertyLoc field for remapping location, using array: ["latname","lonname"] for select double fields(ex. ["lat","lon"] ) support dotted format: "prop.subprop.title".
#' @param propertyName property in marker.options(or feature.properties for vector layer) trough filter elements in layer,.
#' @param formatData callback for reformat all data from source to indexed data object.
#' @param filterData callback for filtering data from text searched, params: textSearch, allRecords.
#' @param moveToLocation whether to move to the found location.
#' @param zoom zoom to this level when moving to location
#' @param buildTip function that return row tip html node(or html string), receive text tooltip in first param.
#' @param container container id to insert Search Control.
#' @param minLength minimal text length for autocomplete.
#' @param initial search elements only by initial text.
#' @param casesensitive search elements in case sensitive text.
#' @param autoType complete input with first suggested result and select this filled-in text..
#' @param delayType delay while typing for show tooltip.
#' @param tooltipLimit limit max results to show in tooltip. -1 for no limit..
#' @param tipAutoSubmit auto map panTo when click on tooltip.
#' @param firstTipSubmit auto select first result con enter click.
#' @param autoResize autoresize on input change.
#' @param collapsed collapse search control at startup.
#' @param autoCollapse collapse search control after submit(on button or on tips if enabled tipAutoSubmit).
#' @param autoCollapseTime delay for autoclosing alert and collapse after blur.
#' @param textErr 'Location not error message.
#' @param textCancel title in cancel button.
#' @param textPlaceholder placeholder value.
#' @param position "topleft".
#' @param hideMarkerOnCollapse remove circle and marker on search control collapsed.
#' @param marker Let's you set the icon. Can be an icon made by \code{\link[leaflet]{makeIcon}} or \code{\link[leaflet]{makeAwesomeIcon}}
#' @rdname search-options
#' @export
searchOptions <- function(
url = NULL,
sourceData = NULL,
jsonpParam = NULL,
propertyLoc = NULL,
propertyName = NULL,
formatData = NULL,
filterData = NULL,
moveToLocation = TRUE,
zoom = 17,
buildTip = NULL,
container = "",
minLength = 1,
initial = TRUE,
casesensitive = FALSE,
autoType = TRUE,
delayType = 400,
tooltipLimit = -1,
tipAutoSubmit = TRUE,
firstTipSubmit = FALSE,
autoResize = TRUE,
collapsed = TRUE,
autoCollapse = FALSE,
autoCollapseTime = 1200,
textErr = "Location Not Found",
textCancel = "Cancel",
textPlaceholder = "Search...",
position = "topleft",
hideMarkerOnCollapse = FALSE,
marker = list(
icon = NULL,
animate = TRUE,
circle = list(
radius = 10,
weight = 3,
color = "#e03",
stroke = TRUE,
fill = FALSE
)
)) {
leaflet::filterNULL(list(
url = url,
sourceData = sourceData,
jsonpParam = jsonpParam,
propertyLoc = propertyLoc,
propertyName = propertyName,
formatData = formatData,
filterData = filterData,
moveToLocation = moveToLocation,
zoom = zoom,
buildTip = buildTip,
container = container,
minLength = minLength,
initial = initial,
casesensitive = casesensitive,
autoType = autoType,
delayType = delayType,
tooltipLimit = tooltipLimit,
tipAutoSubmit = tipAutoSubmit,
firstTipSubmit = firstTipSubmit,
autoResize = autoResize,
collapsed = collapsed,
autoCollapse = autoCollapse,
autoCollapseTime = autoCollapseTime,
textErr = textErr,
textCancel = textCancel,
textPlaceholder = textPlaceholder,
position = position,
hideMarkerOnCollapse = hideMarkerOnCollapse,
marker = marker
))
}
#' Add a OSM search control to the map.
#'
#' @param map a map widget object
#' @param options Search Options
#' @return modified map
#' @rdname search-geocoding
#' @export
addSearchOSM <- function(map,
options = searchOptions(autoCollapse = TRUE, minLength = 2)) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
result <- makeSearchIcon(map, options)
map <- result$map
options$marker$icon <- result$icon
invokeMethod(
map,
getMapData(map),
"addSearchOSM",
options
)
}
#' Add a OSM search control to the map.
#'
#' @param map a map widget object
#' @param text The search text
#' @return modified map
#' @rdname search-geocoding
#' @export
searchOSMText <- function(map, text = "") {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
NULL,
"searchOSMText",
text
)
}
#' Removes the OSM search control from the map.
#'
#' @return modified map
#' @rdname search-geocoding
#' @export
removeSearchOSM <- function(map) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"removeSearchOSM"
)
}
#' Clears the search marker
#'
#' @return modified map
#' @rdname search-geocoding
#' @export
clearSearchOSM <- function(map) {
invokeMethod(
map,
getMapData(map),
"clearSearchOSM"
)
}
#' @param showSearchLocation Boolean. If TRUE displays a Marker on the searched location's coordinates.
#' @param showBounds Boolean. If TRUE show the bounding box of the found feature.
#' @param showFeature Boolean. If TRUE show the found feature.
#' Depending upon the feature found this can be a marker, a line or a polygon.
#' @param fitBounds Boolean. If TRUE set maps bounds to queried and found location.
#' For this to be effective one of \code{showSearchLocation}, \code{showBounds}, \code{showFeature} shoule also be TRUE.
#' @param displayText Boolean. If TRUE show a text box with found location's name on the map.
#' @param group String. An optional group to hold all the searched locations and their results.
#' @param marker Let's you set the icon. Can be an icon made by \code{\link[leaflet]{makeIcon}} or \code{\link[leaflet]{makeAwesomeIcon}}
#' @param showFeatureOptions A list of styling options for the found feature
#' @param showBoundsOptions A list of styling options for the bounds of the found feature
#' @param showHighlightOptions A list of styling options for the hover effect of a found feature
#' @return modified map
#' @rdname search-geocoding
#' @export
addReverseSearchOSM <- function(
map,
showSearchLocation = TRUE,
showBounds = FALSE,
showFeature = TRUE,
fitBounds = TRUE,
displayText = TRUE,
group = NULL,
marker = list(
icon = NULL
),
showFeatureOptions = list(
weight = 2,
color = "red",
dashArray = "5,10",
fillOpacity = 0.2,
opacity = 0.5
),
showBoundsOptions = list(
weight = 2,
color = "#444444",
dashArray = "5,10",
fillOpacity = 0.2,
opacity = 0.5
),
showHighlightOptions = list(
opacity = 0.8,
fillOpacity = 0.5,
weight = 5
)) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
if (displayText == TRUE) {
map <- map %>%
addControl("Click anywhere on the map to reverse geocode",
position = "topright", layerId = "reverseSearchOSM"
)
}
result <- makeSearchIcon(map, list("marker" = marker))
map <- result$map
marker$icon <- result$icon
invokeMethod(
map,
getMapData(map),
"addReverseSearchOSM",
list(
showSearchLocation = showSearchLocation,
fitBounds = fitBounds,
showBounds = showBounds,
showFeature = showFeature,
marker = marker,
showFeatureOptions = showFeatureOptions,
showBoundsOptions = showBoundsOptions,
showHighlightOptions = showHighlightOptions
),
group
)
}
#' Add a Google search control to the map.
#'
#' @param apikey String. API Key for Google GeoCoding Service.
#' @return modified map
#' @rdname search-geocoding
#' @examples
#' leaflet() %>%
#' addProviderTiles(providers$Esri.WorldStreetMap) %>%
#' addResetMapButton() %>%
#' addSearchGoogle()
#'
#' ## for more examples see
#' # browseURL(system.file("examples/search.R", package = "leaflet.extras"))
#'
#' @export
addSearchGoogle <- function(
map,
apikey = Sys.getenv("GOOGLE_MAP_GEOCODING_KEY"),
options = searchOptions(autoCollapse = TRUE, minLength = 2)) {
url <- "https://maps.googleapis.com/maps/api/js?v=3"
if (is.null(apikey) || apikey == "") {
warning("Google Geocoding works best with an apikey")
} else {
url <- paste0(url, "&key=", apikey)
}
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"addSearchGoogle",
options
) %>%
htmlwidgets::appendContent(htmltools::tags$script(src = url))
}
#' Removes the Google search control from the map.
#'
#' @return modified map
#' @rdname search-geocoding
#' @export
removeSearchGoogle <- function(map) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"removeSearchGoogle"
)
}
#' @return modified map
#' @rdname search-geocoding
#' @export
addReverseSearchGoogle <- function(
map,
apikey = Sys.getenv("GOOGLE_MAP_GEOCODING_KEY"),
showSearchLocation = TRUE,
showBounds = FALSE,
showFeature = TRUE,
fitBounds = TRUE,
displayText = TRUE,
group = NULL) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
url <- "https://maps.googleapis.com/maps/api/js?v=3"
if (is.null(apikey) || apikey == "") {
warning("Google Geocoding works best with an apikey")
} else {
url <- paste0(url, "&key=", apikey)
}
if (displayText == TRUE) {
map <- map %>%
addControl("Click anywhere on the map to reverse geocode",
position = "topright", layerId = "reverseSearchGoogle"
)
}
invokeMethod(
map,
getMapData(map),
"addReverseSearchGoogle",
list(
showSearchLocation = showSearchLocation,
fitBounds = fitBounds,
showBounds = showBounds,
showFeature = showFeature
),
group
) %>%
htmlwidgets::appendContent(htmltools::tags$script(src = url))
}
#' Add a US Census Bureau search control to the map.
#'
#' @return modified map
#' @rdname search-geocoding
#' @export
addSearchUSCensusBureau <- function(
map,
options = searchOptions(autoCollapse = TRUE, minLength = 20)) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"addSearchUSCensusBureau",
options
)
}
#' Removes the US Census Bureau search control from the map.
#'
#' @return modified map
#' @rdname search-geocoding
#' @export
removeSearchUSCensusBureau <- function(map) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"removeSearchUSCensusBureau"
)
}
#' Customized searchOptions for Feature Search
#' @param openPopup whether to open the popup associated with the feature when the feature is searched for
#' @param ... Other options to pass to \code{\link{searchOptions}()} function.
#' @rdname search-options
#' @export
searchFeaturesOptions <- function(
propertyName = "label",
initial = FALSE,
openPopup = FALSE,
...) {
c(
openPopup = openPopup,
searchOptions(
propertyName = propertyName,
initial = initial,
...
)
)
}
#' Add a feature search control to the map.
#'
#' @param map a map widget object
#' @param targetGroups A vector of group names of groups whose features need to be searched.
#' @param options Search Options
#' @return modified map
#' @rdname search-features
#' @export
addSearchFeatures <- function(
map,
targetGroups,
options = searchFeaturesOptions()) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
result <- makeSearchIcon(map, options)
map <- result$map
options$marker$icon <- result$icon
invokeMethod(
map,
getMapData(map),
"addSearchFeatures",
targetGroups,
options
)
}
#' Removes the feature search control from the map.
#'
#' @param clearFeatures Boolean. If TRUE the features that this control searches will be removed too.
#' @return modified map
#' @rdname search-features
#' @export
removeSearchFeatures <- function(map, clearFeatures = FALSE) {
map$dependencies <- c(map$dependencies, leafletSearchDependencies())
invokeMethod(
map,
getMapData(map),
"removeSearchFeatures",
clearFeatures
)
}
#' Clears the search marker
#'
#' @return modified map
#' @rdname search-features
#' @export
clearSearchFeatures <- function(map) {
invokeMethod(
map, NULL, "clearSearchFeatures"
)
}
makeSearchIcon <- function(map, options) {
icon <- options$marker$icon
icon <- if (is.null(icon) || all(is.na(icon)) || isFALSE(icon)) NULL else icon
if (!is.null(icon)) {
if (isTRUE(icon)) {
} else {
if (inherits(icon, "leaflet_awesome_icon")) {
map <- addAwesomeMarkersDependencies(map, icon$library)
icon$awesomemarker <- TRUE
} else {
icon$iconUrl <- b64EncodePackedIcons(packStrings(icon$iconUrl))
icon$iconRetinaUrl <- b64EncodePackedIcons(packStrings(icon$iconRetinaUrl))
icon$shadowUrl <- b64EncodePackedIcons(packStrings(icon$shadowUrl))
icon$shadowRetinaUrl <- b64EncodePackedIcons(packStrings(icon$shadowRetinaUrl))
if (length(icon$iconSize) == 2 && is.numeric(icon$iconSize[[1]]) && is.numeric(icon$iconSize[[2]])) {
icon$iconSize <- list(icon$iconSize)
}
}
icon <- leaflet::filterNULL(icon)
}
}
return(list(map = map, icon = icon))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.