Initial commit

This commit is contained in:
zhongjin 2020-06-13 18:34:34 +08:00
commit 52aaa9f15d
655 changed files with 96796 additions and 0 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Javascript and json files are formated with 2 spaces with ut8 encoding
[*.{js,json}]
charset = utf-8
indent_style = space
indent_size = 2

7
.eslintignore Normal file
View File

@ -0,0 +1,7 @@
/dist
/doc
/docs
/examples
/grunt
/themes
/vendor

14
.eslintrc.json Normal file
View File

@ -0,0 +1,14 @@
{
"extends": "semistandard",
"env": {
"es6": true,
"browser": true,
"jasmine": true
},
"globals": {
"__ENV__": true
},
"rules": {
"no-useless-escape": "off"
}
}

29
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,29 @@
### Context
*Please explain here below what you were doing when the issue happened*
### Steps to Reproduce
*Please break down here below all the needed steps to reproduce the issue*
1.
2.
3.
### Current Result
*Please describe here below the current result you got*
### Expected result
*Please describe here below what should be the expected behaviour*
### Browser and version
*What internet browser (Chrome, Firefox, etc) and version was you using and version*
### Additional info
*Please add any information of interest here below*

53
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,53 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 365
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 14
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
# exemptLabels:
# - pinned
# - security
# - "[Status] Maybe Later"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
unmarkComment: false
# Comment to post when closing a stale Issue or Pull Request.
closeComment: false
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 10
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
.DS_store
.idea/
.grunt
.rvmrc
.tmp
.vscode
*.swp
dist
docs/public
docs/internal
Gemfile.lock
node_modules
npm-debug.log
secrets.json
secrets.v3.json
secrets.v4.json
test/SpecRunner*.html
themes/css/all.css
themes/css/cartodb.ie.css
themes/css/cartodb.css
yarn.lock
.sass-cache

5
.hound.yml Normal file
View File

@ -0,0 +1,5 @@
scss:
enabled: true
config_file: .scss-lint.yml
javascript:
enabled: false

1
.npmrc Normal file
View File

@ -0,0 +1 @@
message = "Bump version to %s"

184
.scss-lint.yml Normal file
View File

@ -0,0 +1,184 @@
scss_files: 'themes/scss/**/*.scss'
exclude:
- 'themes/scss/common/reset.scss'
- 'themes/scss/map/cartodb-map-light.scss'
- 'themes/scss/tooltip/*.scss'
- 'themes/scss/vendor/*.scss'
- 'vendor/**/*.scss'
linters:
BangFormat:
enabled: true
space_before_bang: true
space_after_bang: false
BemDepthf:
enabled: true
max_elements: 3
BorderZero:
enabled: false
convention: zero
ColorKeyword:
enabled: true
severity: warning
ColorVariable:
enabled: false
severity: warning
Comment:
enabled: false
DebugStatement:
enabled: true
DeclarationOrder:
enabled: true
DisableLinterReason:
enabled: false
DuplicateProperty:
enabled: true
ElsePlacement:
enabled: true
style: same_line
EmptyLineBetweenBlocks:
enabled: false
EmptyRule:
enabled: true
FinalNewline:
enabled: true
present: true
HexLength:
enabled: true
style: short
HexNotation:
enabled: true
style: uppercase
HexValidation:
enabled: true
IdSelector:
enabled: true
ImportantRule:
enabled: true
ImportPath:
enabled: true
leading_underscore: false
filename_extension: false
Indentation:
enabled: true
allow_non_nested_indentation: false
character: space
width: 2
severity: warning
LeadingZero:
enabled: true
style: include_zero
MergeableSelector:
enabled: true
force_nesting: false
NameFormat:
enabled: true
# Valid cases
# - hello
# - helloMates
# - hello-buddy
# - hello-buddyOne
convention: '([a-z]*)([A-Z]+[a-z]*)*-{0,2}([a-z]([a-z]*[A-Z]*[a-z]*))(\.[a-z]+-[a-z]*[A-Z]*[a-z]*)?(:.*)*'
NestingDepth:
enabled: true
max_depth: 3
severity: warning
PlaceholderInExtend:
enabled: false
PropertyCount:
enabled: true
include_nested: false
max_properties: 18
severity: warning
PropertySortOrder:
enabled: true
order: smacss
ignore_unspecified: true
severity: warning
separate_groups: false
PropertySpelling:
enabled: true
extra_properties: []
PropertyUnits:
global: ['em', 'rem', '%', 'px', 's', 'ms', 'vh'] # Allow relative units globally
properties:
border: ['px']
line-height: ['px', '']
margin: ['em', 'px', '%']
QualifyingElement:
enabled: true
allow_element_with_attribute: true
allow_element_with_class: false
allow_element_with_id: false
severity: warning
SelectorDepth:
enabled: true
max_depth: 3
severity: warning
SelectorFormat:
enabled: true
# Valid cases
# - 0..100%
# - i | em | strong | div | span | ...
# - CDB-Logo
# - CDB-LogoWadus
# - CDB-Logo--cartofante
# - CDB-LogoWadus--cartofante
# - CDB-Logo--cartofantePleased
# - CDB-Logo--cartofanteURL
# - CDB-Logo-oh
# - CDB-Logo-oh:hover
# - CDB-Logo:after
# - CDB-Logo.is-state
convention: '([0-9]+%)|([a-z]+(:.*)*)|CDB-([A-Z]+[a-z]*)([A-Z]+[a-z]*)*-{0,2}([a-z]([a-z]*[A-Z]*[a-z]*))(\.[a-z]+-[a-z]*[A-Z]*[a-z]*)?(:.*)*'
ignored_types: ['id']
Shorthand:
enabled: true
severity: warning
SingleLinePerProperty:
enabled: true
allow_single_line_rule_sets: false
SingleLinePerSelector:
enabled: true
SpaceAfterComma:
enabled: true
SpaceAfterPropertyColon:
enabled: true
style: one_space
SpaceAfterPropertyName:
enabled: true
SpaceAfterVariableName:
enabled: true
SpaceAroundOperator:
enabled: true
style: one_space
SpaceBeforeBrace:
enabled: true
style: space
allow_single_line_padding: false
SpaceBetweenParens:
enabled: true
spaces: 0
StringQuotes:
enabled: true
style: single_quotes
TrailingSemicolon:
enabled: true
severity: warning
TrailingZero:
enabled: true
UnnecessaryMantissa:
enabled: true
UnnecessaryParentReference:
enabled: true
UrlFormat:
enabled: true
UrlQuotes:
enabled: true
VariableForProperty:
enabled: false
properties: []
VendorPrefixes:
enabled: false
ZeroUnit:
enabled: true
severity: warning

21
.travis.yml Normal file
View File

@ -0,0 +1,21 @@
sudo: false
cache: false
language: node_js
node_js:
- 6.9.2
install:
- npm install
before_script:
- cp secrets.example.json secrets.json
- npm install -g grunt-cli
script:
- npm test
after_success:
- bash scripts/deploy-docs-examples.sh
notifications:
email:
on_success: never
on_failure: change
env:
global:
secure: lcdjTpuv2imFSgcYWMLV4odyZ4jOTjJhyViGg9hOFzggoPGFAjplz6bPgNJsxq20ZsFDw4UN6UlZ8lPGlByIUBhf2OXs0cEJDcNSoYAV7CuTMSdZsLDb+TrWQvjtSZMBEkeVENfJjyfiJo7PCt2/cIQXSVSnhZ5Uiir+Eus5x/s=

199
CHANGELOG.md Normal file
View File

@ -0,0 +1,199 @@
# Changelog
CARTO.js is a JavaScript library that interacts with different CARTO APIs. It is part of the CARTO Engine ecosystem.
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## 4.2 - 2019-12-26
### Added
- Improve Overview guide with npm info [2230](https://github.com/CartoDB/carto.js/issues/2230)
- New dataview filters: circle & polygon [2242](https://github.com/CartoDB/carto.js/pull/2242)
### Fixed
- Support options dead link [2240](https://github.com/CartoDB/carto.js/issues/2240)
- Replace uglify with terser to fix internal build [2242](https://github.com/CartoDB/carto.js/pull/2242)
- Fix scroll in gradient legends [2244](https://github.com/CartoDB/carto.js/issues/2244)
### Changed
- Update eslint [2242](https://github.com/CartoDB/carto.js/pull/2242)
## 4.1.11 - 2019-02-13
### Changed
- Using Google Maps v3.35 on examples [2227](https://github.com/CartoDB/carto.js/pull/2227)
## 4.1.10 - 2019-01-18
### Fixed
- Trigger view update after search [2219](https://github.com/CartoDB/carto.js/pull/2219)
- Filters: parse dates properly in the `between` filter.
## 4.1.9 - 2019-01-09
### Added
- TomTom geocoder service [#2213](https://github.com/CartoDB/carto.js/issues/2213)
### Fixed
- Histogram: fix wrong selection in last bucket.
### Changed
- Improve examples. [#2211](https://github.com/CartoDB/carto.js/pull/2211)
## 4.1.8 - 2018-10-29
### Fixed
- Moved 'browserify-shim' to devDependencies, fixing a potential problem with npm shrinkwrap.
## 4.1.7 - 2018-10-18
### Fixed
- Client: Fix `serverUrl` parameter: `{username}` replacement, validation and documentation.
## 4.1.6 - 2018-09-07
### Fixed
- Source Filters: Fix return in get-object-value that was causing unintended behaviors in parameters validation.
## 4.1.5 - 2018-09-05
### Added
- Source Filters: allow subqueries in `eq`, `notEq` in Category filter, and `lt`, `lte`, `gt`, `gte` in Range Filter.
## 4.1.4 - 2018-09-03
### Added
- Source Filters: allow to filter category columns by subquery. [#2186](https://github.com/CartoDB/carto.js/issues/2186)
- Source Filters: reset filter conditions with .resetFilters(). [#2186](https://github.com/CartoDB/carto.js/issues/2186)
### Fixed
- Source Filters: allow to combine empty filters. [#2186](https://github.com/CartoDB/carto.js/issues/2186)
## 4.1.3 - 2018-08-09
### Fixed
- Fix safari drag problem. [#2184](https://github.com/CartoDB/carto.js/pull/2184)
## 4.1.2 - 2018-07-31
### Fixed
- Fix `Promise is undefined` in IE11. [#2180](https://github.com/CartoDB/carto.js/issues/2180)
## 4.1.1 - 2018-07-17
### Fixed
- Fix popups/featureClick positions when scrolled. [#2179](https://github.com/CartoDB/carto.js/pull/2179)
### Changed
- Improve examples. [#2177](https://github.com/CartoDB/carto.js/pull/2177)
## 4.1.0 - 2018-07-13
### Added
- Docs: Add performance tips guide. [#2168](https://github.com/CartoDB/carto.js/issues/2168)
## 4.0.18 - 2018-07-12
### Added
- Histogram: added `start` and `end` options to modify the histogram range. [#2142](https://github.com/CartoDB/carto.js/issues/2142)
## 4.0.17 - 2018-07-12
### Added
- Layers: added `visible` to options. [#2004](https://github.com/CartoDB/carto.js/issues/2004)
### Changed
- Docs: Update 01-quickstart.md. [#2133](https://github.com/CartoDB/carto.js/pull/2133)
### Fixed
- Fix API key in quickstart example. [#2171](https://github.com/CartoDB/carto.js/pull/2171)
### Removed
- Remove Gemfile (compass). [#1909](https://github.com/CartoDB/carto.js/issues/1909)
## 4.0.16 - 2018-07-10
### Added
- Source filters: added new feature for filtering sources. [#2141](https://github.com/CartoDB/carto.js/issues/2141)
## 4.0.15 - 2018-07-06
### Fixed
- Allow multiple CARTO.js clients using Google Maps. [#2132](https://github.com/CartoDB/carto.js/issues/2132)
## 4.0.14 - 2018-07-06
### Fixed
- Dataviews: fix removeDataview not stopping fetching data [#2119](https://github.com/CartoDB/carto.js/issues/2119)
## 4.0.13 - 2018-07-06
### Added
- Add metrics to map instantiation. [#2139](https://github.com/CartoDB/carto.js/issues/2139)
## 4.0.12 - 2018-07-05
### Changed
- Debounced map instantiation. [#2140](https://github.com/CartoDB/carto.js/issues/2140)
## 4.0.11 - 2018-07-05
### Fixed
- Fix interactivity when only 'cartodb_id' is selected. [#2089](https://github.com/CartoDB/carto.js/issues/2089)
## 4.0.10 - 2018-07-04
### Added
- Dataviews: added century and millennium aggregations. [#2162](https://github.com/CartoDB/carto.js/issues/2162)
- Document new time series aggregations. [#2163](https://github.com/CartoDB/carto.js/issues/2163)
## 4.0.9 - 2018-07-02
### Added
- Add options as input argument to the getLeafletLayer() method. [#2125](https://github.com/CartoDB/carto.js/issues/2125)
- Add hexagon aggregation example. [#2151](https://github.com/CartoDB/carto.js/pull/2151)
- Improve structure of contents. [#2137](https://github.com/CartoDB/carto.js/pull/2137)
### Fixed
- Docs: fix Getting Started links. [#2144](https://github.com/CartoDB/carto.js/pull/2144)
- Docs: replace 'YOUR_API_KEY' with 'default_public' in examples. [#2136](https://github.com/CartoDB/carto.js/pull/2136)
- Docs: update CDN URL in reference documentation. [#2128](https://github.com/CartoDB/carto.js/pull/2128)
## 4.0.8 - 2018-06-04
### Fixed
- Google Maps examples were not working on iOS. [#1995](https://github.com/CartoDB/carto.js/issues/1995)
## 4.0.7 - 2018-06-04
### Changed
- Update gmaps to v3.32 in v4. [#2126](https://github.com/CartoDB/carto.js/pull/2126)
### Fixed
- Remove upper limit on Google Maps dependency.
- Small typo fixes for dev center docs. [#2124](https://github.com/CartoDB/carto.js/pull/2124)
## 4.0.6 - 2018-05-11
### Fixed
- Fix remove layers. [#2116](https://github.com/CartoDB/carto.js/pull/2116)
## 4.0.5 - 2018-05-10
- Internal fixes.
## 4.0.4 - 2018-05-09
- Internal fixes.
## 4.0.3 - 2018-05-04
### Changed
- Update zera version. [#2109](https://github.com/CartoDB/carto.js/pull/2109)
## 4.0.2 - 2018-04-27
### Fixed
- Add missing dependencies to release package. [#2108](https://github.com/CartoDB/carto.js/pull/2108)
- Ugrade zera to fix fractional zoom levels. [#2104](https://github.com/CartoDB/carto.js/pull/2104)
## 4.0.1 - 2018-04-25
### Changed
- Upgrading carto.js to gmaps v3.31. [#2067](https://github.com/CartoDB/carto.js/issues/2067)
## 4.0.0 - 2018-04-17
First public release of CARTO.js library
### Added
- New programmatic API
- New sources: Dataset, SQL
- New styles: CartoCSS
- New layers: Layer (Tile Layer)
- New metadata: Buckets, Categories
- New dataviews: Formula, Category, Histogram, TimeSeries
- New filters: BoundingBox, BoundingBoxLeaflet, BoundingBoxGoogleMaps
- Server aggregation options for layers
- Multiple clients support
- Return native Leaflet and Google Maps layers
- Manage layers interactivity
- Granular error management
- Publish to npm and CDN
- Public documentation within the repo
- Examples and documentation

160
CHANGELOG_INTERNAL.md Normal file
View File

@ -0,0 +1,160 @@
# Changelog internal
This file contains all the changes in the **internal bundle** (used by Builder). Each change corresponds to a **pre-release version**.
All the changes that affects the public bundle should be released as *patch* or *minor* and be included in the main Changelog.
## 4.1.12-1 - 2019-08-06
- Attributions widget: prevent autocollapsing and fix button bug [#2236](https://github.com/CartoDB/carto.js/pull/2236)
## 4.1.12-0 - 2019-08-02
- Change attribution character and toggle widget based on container [#2235](https://github.com/CartoDB/carto.js/pull/2235)
## 4.1.11-0 - 2019-01-22
- Enable search box geocoder provider selection [#2224](https://github.com/CartoDB/carto.js/pull/2224)
## 4.1.10-0 - 2019-01-16
- Change Mapbox geocoder URL to permanent one [#2221](https://github.com/CartoDB/carto.js/pull/2221)
## 4.1.1-0 - 2018-07-13
- Use setView instead of flyTo to improve zoom transitions. [#2178](https://github.com/CartoDB/carto.js/pull/2178)
## 4.0.18-0 - 2018-07-12
- Fix torque layers when analysis are applied. [#2175](https://github.com/CartoDB/carto.js/pull/2175)
## 4.0.11-1 - 2018-07-05
- Transpile ES6 code through Babel in Webpack 4. [#2155](https://github.com/CartoDB/carto.js/pull/2155)
## 4.0.11-0 - 2018-07-05
- Fix gradient legends margin. [#2166](https://github.com/CartoDB/carto.js/pull/2166)
## 4.0.9-2 - 2018-06-29
- Add new CARTO logo. [#2159](https://github.com/CartoDB/carto.js/pull/2159)
## 4.0.9-1 - 2018-06-29
- Fix choropleth legends margin. [#2157](https://github.com/CartoDB/carto.js/pull/2157)
## 4.0.9-0 - 2018-06-19
- Fix margins on legends. [#2143](https://github.com/CartoDB/carto.js/pull/2143)
## 4.0.7-3 - 2018-05-24
- Send empty string when url can not be build. [#2122](https://github.com/CartoDB/carto.js/issues/2122)
## 4.0.7-2 - 2018-05-21
- Avoid problems with cancelled requests in dataviews. [#2118](https://github.com/CartoDB/carto.js/pull/2118)
## 4.0.7-1 - 2018-05-21
- Fix legends paddings / margins. [#2121](https://github.com/CartoDB/carto.js/pull/2121)
## 4.0.7-0 - 2018-05-17
- Rename package to internal-carto.js. [#2120](https://github.com/CartoDB/carto.js/pull/2120)
## 4.0.5 - 2018-05-10
- Add new methods to cartoDB layer. [#2111](https://github.com/CartoDB/carto.js/pull/2111)
## 4.0.4 - 2018-05-09
- Fix layer legends margin. [#2112](https://github.com/CartoDB/carto.js/pull/2112)
## 4.0.1-1 - 2018-04-24
- Better popups with just images on IE and Edge. [#2105](https://github.com/CartoDB/carto.js/pull/2105)
## 4.0.0-2 - 2018-04-24
- Fix embed legends margin
- Enable stale bot
## 4.0.0-beta.41 - 2018-04-17
- Adapt to Auth API errors
- Change API menu GIF.
- Add usage box to CARTO.js examples
## 4.0.0-beta.40 - 2018-04-12
- Minor adjustments to legends style
- V4 docs final review
- add tip about authorization system
- Update README and CHANGELOG
## 4.0.0-beta.39 - 2018-03-28
- Added example for the url server parameter
- Unify engine mock
## 4.0.0-beta.38 - 2018-03-23
- Move template2x decision to leaflet rendering
## 4.0.0-beta.37 - 2018-03-23
- Propagate API keys to dataviews in public API
## 4.0.0-beta.35 - 2018-03-19
- Add hasBeenFetched flag to histogram
## 4.0.0-beta.34 - 2018-03-14
- Re-render legends when layers order is changed
## 4.0.0-beta.33 - 2018-03-05
- Suppress horizontal scroll in legends. Fixes IE11
## 4.0.0-beta.32 - 2018-02-26
- Fix legends
## 4.0.0-beta.31 - 2018-02-23
- Hot size legends are broken.
## 4.0.0-beta.29 - 2018-02-23
- prepare shield-placement-keyword CartoCSS property
## 4.0.0-beta.28 - 2018-02-21
- 2046 move docs
## 4.0.0-beta.27 - 2018-02-21
- Adjust styles mobile view embed maps [WIP]
## 4.0.0-beta.26 - 2018-02-20
- add marker size to layer cartocss props to reinstantiate torque map
## 4.0.0-beta.24 - 2018-02-15
- Freeze GMaps script version
- Warn instead of error if no API key
- Fix popup examples for polygons
- Revert "Hide aggregation from public api" (#2029)
- Added server aggregation validation #2032
- Check parameters when creating bounding box filters. #2003
## 4.0.0-beta.23 - 2018-02-06
- Update all examples to Leaflet1.3.1
- remove unnecessary`sync_on_data_change` #2036
## 4.0.0-beta.22 - 2018-02-01
- Use retina url in high resolution screens
## 4.0.0-beta.21 - 2018-02-01
- Set Leaflet zoomAnimationThreshold to 1000 (internal only)
- Define layers order
## 4.0.0-beta.20 - 2018-02-01
- Remove tangram support
## 4.0.0-beta.19 - 2018-02-01
- Examples feedback
- 2011 autogenerate changelog
## 4.0.0-beta.18 - 2018-01-31
- Override scrollwheel if it's boolean
## 4.0.0-beta.17 - 2018-01-30
- 5067 add mapbox geocoder
## 4.0.0-beta.16 - 2018-01-30
- Append legends view if js-embed-legends is found
## 4.0.0-beta.15 - 2018-01-29
- Remove category value stringify
## 4.0.0-beta.14 - 2018-01-19
- Merge pull request #2017 from CartoDB/11341-add-dblclick-event
- 11341 add dblclick event
## 4.0.0-beta.13 - 2018-01-18
- add layer zoom options (#2002)
- Add aggregation options to layer constructor (#2010)
## 4.0.0-beta.12 - 2018-01-18
- Allow custom IDs in layers (#2000)

155
Gruntfile.js Normal file
View File

@ -0,0 +1,155 @@
var _ = require('underscore');
var jasmineCfg = require('./grunt/tasks/jasmine');
function getTargetDiff () {
// Detect changed files. If no changes return '.' (all files)
var target = require('child_process').execSync('(git diff --name-only --relative || true;)' +
'| grep \'\\.js\\?$\' || true').toString();
if (target.length === 0) {
target = ['.'];
} else {
target = target.split('\n');
target.splice(-1, 1);
}
return target;
}
/**
* Grunfile runner file for CARTO.js
* framework
*
*/
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
var semver = require('semver');
var version = grunt.file.readJSON('package.json').version;
if (!version || !semver.valid(version)) {
grunt.fail.fatal('package.json version is not valid', 1);
}
grunt.initConfig({
secrets: {},
dist: 'dist',
tmp: '.tmp',
version: version,
gitinfo: {},
browserify: require('./grunt/tasks/browserify').task(),
exorcise: require('./grunt/tasks/exorcise').task(),
s3: require('./grunt/tasks/s3').task(version),
fastly: require('./grunt/tasks/fastly').task(),
sass: require('./grunt/tasks/scss').task(),
watch: require('./grunt/tasks/watch').task(),
connect: require('./grunt/tasks/connect').task(),
copy: require('./grunt/tasks/copy').task(),
clean: require('./grunt/tasks/clean').task(),
concat: require('./grunt/tasks/concat').task(),
terser: require('./grunt/tasks/terser').task(),
usebanner: require('./grunt/tasks/usebanner').task(),
cssmin: require('./grunt/tasks/cssmin').task(),
imagemin: require('./grunt/tasks/imagemin').task(),
jasmine: jasmineCfg,
eslint: { target: getTargetDiff() }
});
grunt.registerTask('publish_s3', function (target) {
if (!grunt.file.exists('secrets.json')) {
grunt.fail.fatal('secrets.json file does not exist, copy secrets.example.json and rename it', 1);
}
// Read secrets
grunt.config.set('secrets', grunt.file.readJSON('secrets.json'));
if (!grunt.config('secrets') ||
!grunt.config('secrets').AWS_USER_S3_KEY ||
!grunt.config('secrets').AWS_USER_S3_SECRET ||
!grunt.config('secrets').AWS_S3_BUCKET
) {
grunt.fail.fatal('S3 keys not specified in secrets.json', 1);
}
grunt.task.run([
's3'
]);
});
grunt.registerTask('invalidate', function () {
if (!grunt.file.exists('secrets.json')) {
grunt.fail.fatal('secrets.json file does not exist, copy secrets.example.json and rename it', 1);
}
// Read secrets
grunt.config.set('secrets', grunt.file.readJSON('secrets.json'));
if (!grunt.config('secrets') ||
!grunt.config('secrets').FASTLY_API_KEY ||
!grunt.config('secrets').FASTLY_CARTODB_SERVICE
) {
grunt.fail.fatal('Fastly keys not specified in secrets.json', 1);
}
grunt.task.run([
'fastly'
]);
});
grunt.registerTask('preWatch', function () {
grunt.config('doWatchify', true); // required for browserify to use watch files instead
});
grunt.registerTask('build-jasmine-specrunners', _
.chain(jasmineCfg)
.keys()
.map(function (name) {
return ['jasmine', name, 'build'].join(':');
})
.value());
// Define tasks order for each step as if run in isolation,
// when registering the actual tasks _.uniq is used to discard duplicate tasks from begin run
var allDeps = [
'clean:dist_internal',
'gitinfo',
'copy:fonts'
];
var css = allDeps
.concat([
'sass',
'concat',
'cssmin',
'imagemin'
]);
var js = allDeps
.concat([
'browserify',
'build-jasmine-specrunners'
]);
var buildJS = allDeps
.concat(js)
.concat([
'exorcise',
'terser',
'usebanner'
]);
var devJS = allDeps
.concat('preWatch')
.concat(js);
var watch = [
'connect',
'watch'
];
grunt.registerTask('default', [ 'build' ]);
grunt.registerTask('build', _.uniq(buildJS.concat(css)));
grunt.registerTask('build:js', _.uniq(buildJS));
grunt.registerTask('build:css', _.uniq(css));
grunt.registerTask('test', _.uniq(js.concat([
'eslint',
'jasmine'
])));
grunt.registerTask('dev', _.uniq(css.concat(devJS).concat(watch)));
grunt.registerTask('dev:css', _.uniq(css.concat(watch)));
grunt.registerTask('dev:js', _.uniq(devJS.concat(watch)));
};

29
LICENSE Normal file
View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2018, CARTO
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

105
README.md Normal file
View File

@ -0,0 +1,105 @@
# CARTO.js 4
CARTO.js is a JavaScript library to create custom location intelligence applications that leverage the power of [CARTO](https://carto.com/). It is the library that powers [Builder](https://carto.com/builder/) and it is part of the [Engine](https://carto.com/pricing/engine/) ecosystem.
## Getting Started
The best way to get started is to navigate through the CARTO.js documentation site:
- [Guide](https://carto.com/developers/carto-js/guides/quickstart/) will give you a good overview of the library.
- [API Reference](https://carto.com/developers/carto-js/reference/) will help you use a particular class or method.
- [Examples](https://carto.com/developers/carto-js/examples/) will demo some specific features.
- [Support](https://carto.com/developers/carto-js/support/) might answer some of your questions.
## Versioning
We use [SemVer](http://semver.org/) for versioning.
Please refer to [CHANGELOG.md](CHANGELOG.md) for a list of notables changes for each version of the library.
You can also see the [tags on this repository](https://github.com/CartoDB/carto.js/tags).
## Submitting Contributions
You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here.](https://carto.com/contributions/)
## License
This project is licensed under the BSD 3-clause "New" or "Revised" License - see the [LICENSE.txt](LICENSE.txt) file for details.
## Documentation
### API Reference
Run `npm run docs` to build the API reference documentation from jsdoc annotations.
Once the task is done, you can visit `docs/public/index.html` to check the reference
### General documentation
You can read the general documentation that is published at [https://carto.com/developers/carto-js/](https://carto.com/developers/carto-js/) also in this repo. They are written in Markdown.
Warning: internal links in these documents don't work. They are replaced when the documentation is published in [https://carto.com/](https://carto.com/developers/carto-js/)
#### Guides
The folder `docs/guides` contains general information about the CARTO.js library.
- Quickstart: get started quickly following this tutorial.
- Upgrade considerations: if you have experience with previous versions of CARTO.js, this is the place to learn the differences between the former library and the newest one.
- Glossary: terms that appear throughout the documentation.
#### Examples
In the folder `examples/public` you can find several folders with example for every feature of CARTO.js.
#### Reference topics
The document `docs/reference/topics.md` contains general considerations when working with CARTO.js. It's advisable to read them before diving in the API reference.
#### Support
The folder `docs/support` contains several document with support documentation: support options, FAQs, error messages...
## Development
### Run the tests
```
npm test
```
### Build the library
```
npm run build
```
To watch the files
```
npm run build:watch
```
### Generate the docs
```
npm run docs
```
### Release version
```
npm run bump
```
To publish a release to the `CDN` and `npm`
```
npm run release
```
## Looking for the previous version?
Previous version cartodb.js v3 it's available [here](https://github.com/CartoDB/carto.js/tree/develop)

3
SECURITY-POLICY.md Normal file
View File

@ -0,0 +1,3 @@
Please read [security.txt](https://github.com/CartoDB/carto.js/blob/master/security.txt) to report any security vulnerabilities. We will acknowledge receipt of your vulnerability report and strive to send you regular updates about our progress. If you're curious about the status of your disclosure please feel free to email us again.
Please refrain from requesting compensation for reporting vulnerabilities. If you want we will publicly acknowledge your responsible disclosure, once the issue is fixed.

18
config/jsdoc/index.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CARTO.js</title>
<link type="text/css" rel="stylesheet" href="docs/v4/styles/jsdoc-default.css">
</head>
<body>
<h1 class="page-title">CARTO.js <span style="color:#0095dd;">v4</span></h1>
<ul style="margin:24px;">
<li><h3><a href="docs/v4">API docs</a></h3></li>
<li><h3><a href="docs/v4-internal">Internal docs</a><h3></li>
<li><h3><a href="examples/v4">Examples</a></h3></li>
<li><h3><a href="https://github.com/CartoDB/carto.js/tree/v4">GitHub repository</a><h3></li>
</ul>
<h4 style="margin-left:30px">Version:<span class="name"> %VERSION</span></h4>
</body>
</html>

View File

@ -0,0 +1,20 @@
{
"source": {
"include": [
"src"
]
},
"templates": {
"default": {
"outputSourceFiles": false,
"useLongnameInNav": true
}
},
"plugins": [
"plugins/markdown"
],
"opts": {
"recurse": true,
"destination": "./docs/internal"
}
}

View File

@ -0,0 +1,26 @@
/**
* Define @api tag
*/
exports.defineTags = function (dictionary) {
dictionary.defineTag('api', {
mustHaveValue: false,
canHaveType: false,
canHaveName: false,
onTagged: function (doclet, tag) {
doclet.public = true;
}
});
};
/*
* Only items with @api annotation should be documented
*/
exports.handlers = {
parseComplete: function (e) {
var doclets = e.doclets;
for (var i = 0; i < doclets.length; i++) {
doclets[i].undocumented = !doclets[i].public;
}
}
};

View File

@ -0,0 +1,21 @@
{
"source": {
"include": [
"src"
]
},
"templates": {
"default": {
"outputSourceFiles": false,
"useLongnameInNav": true
}
},
"plugins": [
"plugins/api",
"plugins/markdown"
],
"opts": {
"recurse": true,
"destination": "./docs/public"
}
}

172
docs/guides/01-overview.md Normal file
View File

@ -0,0 +1,172 @@
## Overview
CARTO.js lets you create custom location intelligence applications that leverage the power of the CARTO Platform.
### Audience
This documentation is designed for people familiar with JavaScript programming and object-oriented programming concepts. You should also be familiar with [Leaflet](https://leafletjs.com/) from a developer's point of view.
This conceptual documentation is designed to let you quickly start exploring and developing applications with the CARTO.js library. We also publish the [CARTO.js API Reference]({{site.cartojs_docs}}/reference/).
### Hello, World
The easiest way to start learning about the CARTO.js library is to see a simple example. The following web page displays a map adding a layer over it.
```html
<!DOCTYPE html>
<html>
<head>
<title>Single layer | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="https://libs.cartocdn.com/carto.js/%VERSION%/carto.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link href="https://carto.com/developers/carto-js/examples/maps/public/style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Add a layer</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Add one CARTO layer to your map.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset(`
ne_10m_populated_places_simple
`);
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>
```
[View example]({{site.cartojs_docs}}/examples/#example-add-a-layer).
Even in this simple example, there are a few things to note:
- We declare the application as HTML5 using the `<!DOCTYPE html>` declaration.
- We load the CARTO.js library using a `script` tag.
- We create a `div` element named "map" to hold the map.
- We define the JavaScript that creates a map in the `div`.
These steps are explained below.
### Declaring your application as HTML5
We recommend that you declare a true DOCTYPE within your web application. Within the examples here, we've declared our applications as HTML5 using the simple HTML5 DOCTYPE as shown below:
```html
<!DOCTYPE html>
```
Most current browsers will render content that is declared with this DOCTYPE in "standards mode" which means that your application should be more cross-browser compliant. The DOCTYPE is also designed to degrade gracefully; browsers that don't understand it will ignore it, and use "quirks mode" to display their content.
We add styles to the map through the file `style.css`, declaring:
```css
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
height: 100%;
width: 100%;
z-index: 0;
}
```
This CSS declaration indicates that the map container <div> (with id map) should take up 100% of the height of the HTML body.
### Loading the CARTO.js library
To load the Maps JavaScript API, use a script tag like the one in the following example:
```html
<script src="https://libs.cartocdn.com/carto.js/%VERSION%/carto.min.js"></script>
```
The URL contained in the script tag is the location of a JavaScript file that loads all of the code you need for using the CARTO.js library. This script tag is required. We are using the minified version of the library.
**Tip:** If you have experience with **npm** and a build system in your project (webpack, rollup…), you can install CARTO.js library with `npm install @carto/carto.js`. Then you can import it easily with `import carto from '@carto/carto.js` (or `var carto = require('@carto/carto.js')`, depending on your module system).
#### HTTPS or HTTP
We think security on the web is pretty important, and recommend using HTTPS whenever possible. As part of our efforts to make the web more secure, we've made all of the CARTO components available over HTTPS. Using HTTPS encryption makes your site more secure, and more resistant to snooping or tampering.
We recommend loading the CARTO.js library over HTTPS using the `<script>` tag provided above.
### Map DOM Elements
```html
<div id="map"></div>
```
For the map to display on a web page, we must reserve a spot for it. Commonly, we do this by creating a named div element and obtaining a reference to this element in the browser's document object model (DOM).
In the example above, we used CSS to set the height of the map div to "100%". This will expand to fit the size on mobile devices. You may need to adjust the width and height values based on the browser's screensize and padding.
### Map options
In this example, we are using Leaflet to render the map:
```javascript
const map = L.map('map').setView([30, 0], 3);
```
The common options for every map are: `center` and `zoom`. In this case, we are setting these with [Leaflet's setView method](https://leafletjs.com/reference-1.3.0.html#map-setview).
#### Zoom Levels
The initial resolution at which to display the map is set by the zoom property, where zoom 0 corresponds to a map of the Earth fully zoomed out, and larger zoom levels zoom in at a higher resolution. Specify zoom level as an integer. In our case, we are setting up this as **3**.
### Troubleshooting
If your code isn't working:
- Look for typos. Remember that JavaScript is a case-sensitive language.
- Check the basics. Some of the most common problems occur with the initial map creation. Such as:
- Confirm that you've specified the zoom and center properties in your map options.
- Ensure that you have declared a div element in which the map will appear on the screen.
- Ensure that the div element for the map has a height.
- Refer to our [examples]({{site.cartojs_docs}}/examples/) for a reference implementation.
- Use a JavaScript debugger to help identify problems. Chrome Developer Tools is a good one.
- Post questions to the [GIS Stack Exchange using the `CARTO` tag](https://gis.stackexchange.com/questions/tagged/carto). Guidelines on how to post great questions are available on the [support page]({{site.cartojs_docs}}/support/).

View File

@ -0,0 +1,60 @@
## Get API Key
To use the CARTO.js library, you must register your project in your CARTO account and get an API key which you can add to your app or website.
### Quick guide to getting a key
#### Step 1: Get an API Key from your CARTO account
Start creating your API key, [registering a project](https://carto.com/login) in the CARTO Platform.
Notes:
- **Tip**: During development and testing, you can register a project for testing purposes in the CARTO Platform and use a generic, unrestricted API key. When you are ready to move your app or website into production, register a separate project for production, create a restricted API key, and add the key to your application.
- **Enterprise customers**: For production-ready apps, you must use a restricted API key.
For more information, see the [fundamentals about authorization]({{site.fundamental_docs}}/authorization/).
#### Step 2: Add the API key and username to your application
After loading the CARTO.js library, substitute YOUR_API_KEY in the code below with the API key you got from the previous step.
```javascript
var client = new carto.Client({
apiKey: '{YOUR_API_KEY}',
username: '{username}'
});
```
You can get your username following these steps:
- Login into to your CARTO account.
- Go to your account from the left menu.
- Copy the username under the plan information.
#### More about API keys
The API key allows you to control your applications in the CARTO Platform.
If you are a Trial Plan customer, with an API key you have access to all the Engine features.
If you are an Engine Plan customer, you must use an API key to access all the custom features and benefits of your Engine Plan.
#### Detailed guide for users of the CARTO.js library
Follow these steps to get an API key:
- Go to your CARTO account.
- Go to your API Keys dashboard.
- Click "NEW API KEY" to create a new one.
- If you want to manage projects, you can regenerate or delete them.
- On the API key page, configure it giving a name and the APIs and Datasets you want to use.
For more information on using the CARTO Platform, see our [fundamentals]({{site.fundamental_docs}}/).
#### Troubleshooting authorization issues
If your API key is malformed or you supply an invalid username, the CARTO.js library returns an HTTP 403 (Forbidden) error.
CARTO Enterprise customers have access to enterprise-level support through CARTOs support representatives available at enterprise-support@carto.com.

View File

@ -0,0 +1,408 @@
## Quickstart Guide
CARTO.js lets you create custom location intelligence applications that leverage the power of the **[CARTO Engine](https://carto.com/pricing/engine/)** ecosystem.
This document details CARTO.js v4. To update your v3 apps, please consult the [Upgrade Considerations]({{site.cartojs_docs}}/guides/upgrade-considerations/).
### About this Guide
This guide describes how to create a Leaflet map and display data from CARTO over the map. This demonstrates how CARTO.js can be used to
1. Overlay Data from your CARTO account on any Map.
2. Use Dataviews to Create Widgets.
**Tip:** For more advanced documentation, view the [Full Reference API]({{site.cartojs_docs}}/reference/) or browse through some [examples]({{site.cartojs_docs}}/examples/). You can also read the [FAQs]({{site.cartojs_docs}}/support/faq/).
### Audience
This document is intended for website or mobile developers who want to include CARTO.js library within a webpage or mobile application. It provides an introduction to using the library and reference material on the available parameters.
### Requesting an API Key
CARTO.js requires using an API Key. From your CARTO dashboard, click [_Your API keys_](https://carto.com/login) from the avatar drop-down menu to view your uniquely generated API Key for managing data with CARTO Engine.
If you want learn more about authorization and authentication, read the [authorization fundamentals section]({{site.fundamental_docs}}/authorization/).
### Importing Datasets
Before you start working on the map, you need to import a couple of datasets. For this guide, we will use CARTO's Data Library, available from *Your datasets* dashboard, to import and connect public datasets to your account.
Alternatively, click the following links to download datasets from a public CARTO account:
* [European countries (ne_adm0_europe)](https://carto.com/dataset/ne_adm0_europe)
* [Populated places (ne_10m_populated_places_simple)](https://carto.com/dataset/ne_10m_populated_places_simple)
Once downloaded, import the datasets to your CARTO account.
### Setting up the Map
By the end of the lesson, you will have generated an HTML file of a Leaflet Map showing CARTO's Voyager basemap and labels on top.
#### Application Skeleton
Create an HTML file using your preferred text editor and paste the following code to build the application skeleton:
```html
<!DOCTYPE html>
<html>
<head>
<title>Guide | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet" type="text/css">
<style>
* { margin:0; padding:0; }
html { box-sizing:border-box; height:100%; }
body { background:#f2f6f9; height:100%; font-family:"Open sans", Helvetica, Arial, sans-serif; }
#container { display:flex; width:100%; height:100%; }
#map { flex:1; margin:10px; }
#widgets { width:300px; margin:10px 10px 10px 0; }
.widget { background:white; padding:10px; margin-bottom:10px; }
.widget h1 { font-size:1.2em; }
.widget-formula .result { font-size:2em; }
</style>
</head>
<body>
<div id="container">
<div id="map"></div>
<div id="widgets">
<div id="countriesWidget" class="widget">
<h1>European countries</h1>
<select class="js-countries">
<option value="">All</option>
</select>
</div>
<div id="avgPopulationWidget" class="widget widget-formula">
<h1>Average population</h1>
<p><span class="js-average-population result">xxx</span> inhabitants</p>
</div>
</div>
</div>
<script>
// code will go here!
</script>
</body>
</html>
```
The first part of the skeleton loads CARTO.js and Leaflet 1.2.0 assumes Leaflet is loaded in `window.L`. The library checks if the version of Leaflet is compatible. If not, it throws an error.
The app skeleton also loads CARTO.js, adds some necessary elements, and defines a `script` tag. This is where you will write all the JavaScript code to make the example work.
**Note:** While CARTO.js enables you to display data from CARTO on top of Leaflet or Google Maps map, the actual map settings are controlled via the [Leaflet](http://leafletjs.com/) or [Google Maps](https://hpneo.github.io/gmaps/) map options.
#### Creating the Leaflet Map
CARTO.js apps start from a Leaflet or Google Map. Let's use a basic [Leaflet](http://leafletjs.com/) map for this guide:
```javascript
const map = L.map('map').setView([50, 15], 4);
```
#### Adding Basemap and Label Layers
Define the type of basemap to be used for the background of your map. For this guide, let's use [CARTO's Voyager basemap](https://carto.com/location-data-services/basemaps/).
```javascript
// Adding Voyager Basemap
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// Adding Voyager Labels
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', {
maxZoom: 18,
zIndex: 10
}).addTo(map);
```
`L.tileLayer` creates a layer for the basemap and the `zIndex` property defines the basemap labels (that sit on top of the other layers).
### Defining a `carto.Client`
`carto.Client` is the entry point to CARTO.js. It handles the communication between your app and your CARTO account, which is defined by your API Key and your username.
```javascript
var client = new carto.Client({
apiKey: '{API Key}',
username: '{username}'
});
```
**Warning:** Ensure that you modify any placeholder parameters shown in curly brackets with your own credentials. For example, `apiKey: '123abc',` and `username: 'john123'`.
### Displaying Data on the Map
Display data hosted on your CARTO account as map layers.
### Defining Layers
Layers are defined with `carto.layer.Layer` which include the dataset name and basic styling options with CartoCSS.
```javascript
const europeanCountriesDataset = new carto.source.Dataset(`
ne_adm0_europe
`);
const europeanCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #162945;
polygon-opacity: 0.5;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.5;
}
}
`);
const europeanCountries = new carto.layer.Layer(europeanCountriesDataset, europeanCountriesStyle);
```
The first layer defines a `carto.source.Dataset` object that points to the imported dataset named `ne_adm0_europe`. To style the layer, define a `carto.style.CartoCSS` object that describes how polygons will be rendered.
```javascript
const populatedPlacesSource = new carto.source.SQL(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`);
const populatedPlacesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 8;
marker-fill: #FF583E;
marker-fill-opacity: 0.9;
marker-line-width: 0.5;
marker-line-color: #FFFFFF;
marker-line-opacity: 1;
marker-type: ellipse;
marker-allow-overlap: false;
}
`);
const populatedPlaces = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, {
featureOverColumns: ['name']
});
```
The second layer uses a more complex type of data source for the layer. `carto.source.SQL` provides more flexibility for defining the data that you want to display in a layer. For this guide, we are composing a `SELECT` statement that selects populated cities in Europe. (Optionally, you can change this query at runtime).
The `featureOverColumns: ['name']` option we include in the layer creation defines what columns of the datasource will be available in `featureOver` events as we explain below.
#### Adding Layers to the Client
Before you can add layers to the map, the `carto.Client` variable needs to be notified that these layers exist. The client is responsible for grouping layers into a single Leaflet layer.
```javascript
client.addLayers([europeanCountries, populatedPlaces]);
```
#### Adding Layers to the Map
Now that the client recognizes these two layers, this single Leaflet layer can be added to the map.
```javascript
client.getLeafletLayer().addTo(map);
```
As a result, your map should display polygons for each European country and red points represent populated cities.
**Tip:** In order to change the order of layers, flip the order from `([A, B]);` to `(B, A);`
### Setting up Tooltips
Tooltips give map viewers information about the underlying data as they interact with the map by clicking or hovering over data. CARTO.js provides a simple mechanism to detect some of these interactions and use the data associated to them. For this guide, let's display a mouse hover tooltip showing the name of a city.
#### Showing the Tooltip when User Mouses Over a City
Layers trigger `featureOver` events when the map viewer hovers the mouse over a feature. The event includes data about the feature, such as the latitude and longitude, as well as specified column values defined in `featureOverColumns`.
```javascript
const popup = L.popup({ closeButton: false });
populatedPlaces.on(carto.layer.events.FEATURE_OVER, featureEvent => {
popup.setLatLng(featureEvent.latLng);
if (!popup.isOpen()) {
popup.setContent(featureEvent.data.name);
popup.openOn(map);
}
});
```
In this snippet, we are defining a `L.popup` and listening to the `featureOver` event. When the event is triggered, the pop-up is positioned, populated with the name of the city, and added to the map.
#### Hiding the Tooltip
Similarly, layers trigger `featureOut` events when the map viewer is no longer moving the mouse over a feature. Use this event to hide the pop-up.
```javascript
populatedPlaces.on(carto.layer.events.FEATURE_OUT, featureEvent => {
popup.removeFrom(map);
});
```
When `featureOut` is triggered, this code removes the pop-up from the map.
### Creating a Country Selector Widget
This section describes how to get data from a previously defined data source and display a country selector the map. As a result, selecting a country on the map highlights the country and filters by populated places.
#### Defining a Category Dataview
Dataviews are the mechanism CARTO.js uses to access data from a data source (dataset or SQL query) in a particular way (eg: list of categories, result of a formula, etc.). Use the `carto.dataview.Category` dataview to get the names of the European countries in the dataset:
```javascript
const countriesDataview = new carto.dataview.Category(europeanCountriesDataset, 'admin', {
limit: 100
});
```
This type of dataview expects a data source and the name of the column with the categories. By default, results are limited. For this guide, we specified a limit of 100 categories to make sure all country names are returned.
#### Listening to Data Changes on the Dataview
In order to know when a dataview has new data (eg: right after it has been added to the client or when its source has changed), you should listen to the `dataChanged` event. This event gives you an object with all the categories.
```javascript
countriesDataview.on('dataChanged', data => {
const countryNames = data.categories.map(category => category.name).sort();
refreshCountriesWidget(countryNames);
});
function refreshCountriesWidget(adminNames) {
const widgetDom = document.querySelector('#countriesWidget');
const countriesDom = widgetDom.querySelector('.js-countries');
countriesDom.onchange = event => {
const admin = event.target.value;
highlightCountry(admin);
filterPopulatedPlacesByCountry(admin);
};
// Fill in the list of countries
adminNames.forEach(admin => {
const option = document.createElement('option');
option.innerHTML = admin;
option.value = admin;
countriesDom.appendChild(option);
});
}
function highlightCountry(admin) {
let cartoCSS = `
#layer {
polygon-fill: #162945;
polygon-opacity: 0.5;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.5;
}
}
`;
if (admin) {
cartoCSS = `
${cartoCSS}
#layer[admin!='${admin}'] {
polygon-fill: #CDCDCD;
}
`;
}
europeanCountriesStyle.setContent(cartoCSS);
}
function filterPopulatedPlacesByCountry(admin) {
let query = `
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`;
if (admin) {
query = `
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name='${admin}'
`;
}
populatedPlacesSource.setQuery(query);
}
```
This snippet generates the list of country names in alphabetical order from the `dataChanged` parameter and uses the `SELECT` function to populate the list.
When a country is selected, two functions are invoked: `highlightCountry` (highlights the selected country by setting a new CartoCSS to the layer) and `filterPopulatedPlacesByCountry` (filters the cities by changing the SQL query).
#### Adding the Dataview to the Client
The dataview needs to be added to the client in order to fetch data from CARTO.
```javascript
client.addDataview(countriesDataview);
```
### Creating a Formula Widget
Now that you have a working country selector, let's add a widget that will display the average max population of the populated places for the selected country (or display ALL if no country is selected).
#### Defining a Formula Dataview
`carto.dataview.Formula` allows you to execute aggregate functions (count, sum, average, max, min) on a data source:
```javascript
const averagePopulation = new carto.dataview.Formula(populatedPlacesSource, 'pop_max', {
operation: carto.operation.AVG
});
```
The `averagePopulation` dataview triggers a `dataChanged` event every time a new average has been calculated.
#### Listening to Data Changes on the Dataview
The `dataChanged` event allows you to get results of the aggregate function and use it in many ways.
```javascript
averagePopulation.on('dataChanged', data => {
refreshAveragePopulationWidget(data.result);
});
function refreshAveragePopulationWidget(avgPopulation) {
const widgetDom = document.querySelector('#avgPopulationWidget');
const averagePopulationDom = widgetDom.querySelector('.js-average-population');
averagePopulationDom.innerText = Math.floor(avgPopulation);
}
```
This snippet refreshes the averaged population widget every time a new average is available (e.g., when a new country is selected).
#### Adding the dataview to the client
To get a full working dataview, add it to your client:
```javascript
client.addDataview(averagePopulation);
```
### Conclusion
<div class="example-map">
<iframe src="{{site.cartojs_docs}}/guides/quickstart-example.html" width="100%" height="600" frameBorder="0" style="padding-top: 20px;padding-bottom: 0;" class="u-vspace--24"></iframe>
<a href="{{site.cartojs_docs}}/guides/quickstart-example.html" class="buttonLink is-DocsGreen u-vspace--32" target="_blank">
<svg width="8px" height="7px" viewbox="0 0 8 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path class="buttonLink-media" d="M1.52245273,3.04854764 L3.68776506,0.883235307 C3.88225492,0.688745449 3.88821988,0.353713791 3.68525771,0.15075162 C3.4882313,-0.0462747862 3.15435142,-0.053333131 2.95277402,0.148244267 L0.147793654,2.95322464 C0.0109867585,3.09003153 -0.0325396573,3.29637729 0.0243152648,3.47738142 C-0.0325396573,3.65838554 0.0109867585,3.8647313 0.147793654,4.00153819 L2.95277402,6.80651857 C3.15435142,7.00809596 3.4882313,7.00103762 3.68525771,6.80401121 C3.88821988,6.60104904 3.88225492,6.26601738 3.68776506,6.07152753 L1.70421948,4.08798194 L7.99996393,4.08798194 L7.99996393,3.04854764 L1.52245273,3.04854764 Z" id="Combined-Shape" fill="#1FAC06" transform="translate(3.999982, 3.477381) scale(-1, 1) translate(-3.999982, -3.477381) "/>
</g>
</svg>
Click to open map full size
</a>
</div>
### Troubleshooting and support
For more information on using the CARTO.js library, take a look at the [support page]({{site.cartojs_docs}}/support/).
The CARTO.js library may issue an error or warning when something goes wrong. You should check for warnings in particular if you notice that something is missing. It's also a good idea to check for warnings before launching a new application. Note that the warnings may not be immediately apparent because they appear in the HTTP header. For more information, see the guide to [errors messages]({{site.cartojs_docs}}/support/error-messages/).
This guide is just an overview of how to use CARTO.js to overlay data and create widgets. View the [Examples]({{ site.cartojs_docs }}/examples/) section for specific features of CARTO.js in action.

View File

@ -0,0 +1,101 @@
## Performance Tips
As you go through developing your applications with CARTO.js, you might find useful some tips to ease the development and make your application more performant.
### Sources
Sources are the objects to get data from. The source is the entity that points to the data we want to show in our layers or in a widget through a dataview.
When working with sources, you may want to change the actual query to show other data in your visualization or dataviews. The most common case is filtering your data. The layers and dataviews react to changes coming from linked sources, so that you don't have to create another source. Layers and dataviews that are linked to the source reflect the changes in the source.
The way to go is to call `.setQuery` method to update the SQL query when using a `carto.source.SQL`, or use `.setTableName` in a `carto.source.Dataset` source, like in this examples:
``` js
const populationSource = new carto.source.SQL('SELECT * FROM your_dataset');
populationSource.setQuery('SELECT * FROM your_dataset WHERE price < 80');
```
![setQuery diagram](../../img/set_query_diagram.svg)
``` js
const populationDataset = new carto.source.Dataset('your_dataset');
populationDataset.setTableName('another_dataset');
```
![setTableName diagram](../../img/set_table_name_diagram.svg)
That way, the dataviews and visualizations retrieving data from that source will be automatically updated without doing anything else on your part.
### Styles
We need to use CartoCSS whenever we want to change the style of our markers or polygons, among other things. Each CartoCSS instance contains the styles we want to apply to any of our layers.
These style instances work the same way as sources do. It is pretty common to change styles in your map based on certain triggers, so that you can adequate your visualization to what you want to show.
When linked to a layer, it will automatically show the style change when invoking `.setContent` on the style object with a string containing the new style content.
```js
const layerStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 8;
marker-fill: #FF583E;
marker-fill-opacity: 0.9;
marker-allow-overlap: false;
}
`);
layerStyle.setContent(`
#layer {
marker-width: 10;
marker-fill: #FF583E;
marker-allow-overlap: true;
}
`);
```
![setContent diagram](../../img/set_content_diagram.svg)
### Layers
Layers are a fundamental part of your CARTO.js application. They show the data of a source using the style of a CartoCSS.
As stated before, the layer will be automatically updated in the map when any of its properties (source and style) change.
So, let's say that you want to update the table of your visualization which had been created like this:
``` js
const populationSource = new carto.source.SQL('SELECT * FROM your_dataset');
const layerStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 10;
marker-fill: #FF583E;
marker-allow-overlap: true;
}
`);
const layer = new carto.layer.Layer(populationSource, layerStyle);
```
To update the visualization, the only thing you need to do is to invoke `.setQuery` in your source and everything will be refreshed accordingly.
```js
populationSource.setQuery('SELECT * FROM your_dataset WHERE price > 500');
```
### Dataviews
Dataviews are a way to extract data from our source in predefined ways depending on the type of the column (eg: a list of categories, the result of a formula operation, etc...).
Dataviews need a source to extract data from. So when a source is passed to a dataview, it will react to the changes happening to the source, whether changing the query or adding filters.
```js
const populatedPlaces = new carto.source.Dataset('ne_10m_populated_places_simple');
const column = 'adm0name'; // Aggregate the data by country.
const categoryDataview = new carto.dataview.Category(populatedPlaces, column, {
operation: carto.operation.AVG, // Compute the average
operationColumn: 'pop_max' // The name of the column where the operation will be applied.
});
// ...
citiesSource.addFilter(new carto.filter.Category(column, { eq: 'Spain' } ));
```
In the example above, first we set a dataview getting data from a dataset with information about populated places. Then, we add a filter to the source to show only data coming from Spain. As you can see, we've updated the source and since the dataview was created linked to that source, a change on the query makes the dataview to react to that change automatically. There's no need to create another source and then another dataview.

View File

@ -0,0 +1,181 @@
## Upgrade Considerations Guide
This document is intended for existing developers who have used [previous versions]({{site.cartojs_docs}}/reference/#versioning) of CARTO.js.
### About this Guide
This guide describes how the CARTO.js library has changed to support additional functionality. It outlines the basic workflow for creating an application and includes an example of updating an old application using the new library.
**Tip**: The authorization system behaves in a uniform way for any version of CARTO.js. You can read about the [fundamentals of authorization]({{site.fundamental_docs}}/authorization/) or know implementation details of the [Auth API]({{site.authapi_docs}}/) under the hood.
At a high-level, the workflow consists of:
1. Define the client parameters to manage layers and dataviews:
- [`new carto.Client`]({{site.cartojs_docs}}/reference/#cartoclient)
- [`addLayers`]({{site.cartojs_docs}}/reference/#cartoclientaddlayer)
- [`addDataview`]({{site.cartojs_docs}}/reference/#cartoclientadddataview) or [`addDataviews`]({{site.cartojs_docs}}/reference/#cartoclientadddataviews)
- [`getDataviews`]({{site.cartojs_docs}}/reference/#cartoclientgetdataviews)
2. Define the Base data source objects:
- Add dataset as the source [`carto.source.dataset`]({{site.cartojs_docs}}/reference/#cartosourcedataset)
- Add SQL to filter data [`carto.source.sql`]({{site.cartojs_docs}}/reference/#cartosourcesql)
3. Publish the App:
- [`getLayers`]({{site.cartojs_docs}}/reference/#cartoclientgetlayers)
You should understand the following changes in concept before you begin.
#### Dataset Privacy
Since we now have a new authorization system for the entire CARTO platform, directly related to dataset privacy, datasets can be public and private as well. Read the [basics of authorization]({{site.fundamental_docs}}/authorization/) to learn more about this aspect of the CARTO platform.
#### Map Workflow
`new carto.Client` is the main entry point for building your application. This enables you to communicate between your app and your CARTO account by using your API Key. This enhancement clearly identifies client requests separate from visualization requests.
#### `createVis`
The current beta of CARTO.js only includes a JavaScript library, it does not include `creatVis` components to maintain your app. A future enhancement of the library will include functionality for maintaining your core application.
#### `Dataview`
A Dataview enables you to create different views of data stored in a table. CARTO.js uses `Dataviews` to add interactive widgets for viewing and filtering map data.
#### SQL API Integration
CARTO.js no longer includes a client for the SQL API. Developers looking to get data from their CARTO account can query SQL API with AJAX or the new [JS Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)..
## Upgrading an Existing Application
Suppose you have an app that was created with an earlier version of CARTO.js? This guide provides an example of CARTO.js components showing the old code modified with updated code.
The following example shows the application skeleton using version 3.15 of CARTO.js.
```html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" />
<meta charset="utf-8" />
<!-- include CartoDB.js CSS library -->
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" />
<!-- include CartoDB.js library -->
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = L.map('map').setView([30, 0], 3);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
cartodb.createLayer(map, {
user_name: 'YOUR_USER_NAME',
type: 'cartodb',
sublayers: [
{
type: "mapnik",
sql: 'select * from populated_places_spf',
cartocss: '#populated_places_spf[adm0name = "Spain"]{ marker-fill: #fbb4ae; marker-allow-overlap: true;}#populated_places_spf[adm0name = "Portugal"]{ marker-fill: #ccebc5; marker-allow-overlap: true;}#populated_places_spf[adm0name = "France"]{ marker-fill: #b3cde3; marker-allow-overlap: true;}'
}
]
})
.addTo(map);
</script>
</body>
</html>
```
In order to make this example work with version 4 of CARTO.js, modify the code as follows:
```html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" />
<meta charset="utf-8" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = L.map('map').setView([30, 0], 3);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// define client
const client = new carto.Client({
apiKey: 'YOUR_API_KEY',
username: 'YOUR_USER_NAME'
});
// define source of data => dataset of your account
const source = new carto.source.Dataset(`populated_places_spf`);
// define CartoCSS code to style data on map
const style = new carto.style.CartoCSS(`
#layer[adm0name = "Spain"]{
marker-fill: #fbb4ae;
marker-allow-overlap: true;
}
#layer[adm0name = "Portugal"]{
marker-fill: #ccebc5;
marker-allow-overlap: true;
}
#layer[adm0name = "France"]{
marker-fill: #b3cde3;
marker-allow-overlap: true;
}`);
// create CARTO layer from source and style variables
const Cartolayer = new carto.layer.Layer(source, style);
// add CARTO layer to the client
client.addLayer(Cartolayer);
// get tile from client and add them to the map object
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>
```
#### Conclusion
For more details about how to use CARTO.js, [view the examples]({{site.cartojs_docs}}/examples/) section for specific features of CARTO.js in action.

View File

@ -0,0 +1,35 @@
## Glossary
This glossary defines terms that appear throughout the CARTO.js documentation.
### A
#### Ajax
Asynchronous JavaScript + XML, while not a technology in itself, is a term coined in 2005 by Jesse James Garrett, that describes a "new" approach to using a number of existing technologies together, including HTML or XHTML, Cascading Style Sheets, JavaScript, The Document Object Model, XML, XSLT, and most importantly the XMLHttpRequest object. More info about Ajax at [Ajax](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX).
### C
#### Client
Throughout CARTO.js documentation, `client` refers to the object used as an entry point to CARTO.js features.
It's the object used to add your account credentials and to manage layers and dataviews.
More info at [carto.Client]({{site.cartojs_docs}}/reference/#cartoclient)
### L
#### Layer
A layer object is used to visualize geospatial data in CARTO.js. They have a source, where the data comes from, and a style, defining how you want the layer to look like.
They are showed on top of a Leaflet or a Google map.
[Layer reference]({{site.cartojs_docs}}/reference/#cartolayerlayer)
### P
#### Promise
Promise objects are a standard way for handling asynchronous tasks in Javascript. More info about promises at [Using Promises - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).

View File

@ -0,0 +1,203 @@
<!DOCTYPE html>
<html>
<head>
<title>Guide | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
<!-- Fonts -->
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<style>
* { margin:0; padding:0; }
html { box-sizing:border-box; height:100%; }
body { background:#f2f6f9; height:100%; font-family:"Open sans", Helvetica, Arial, sans-serif; }
#container { display:flex; width:100%; height:100%; }
#map { flex:1; margin:10px; }
#widgets { width:300px; margin:10px 10px 10px 0; }
.widget { background:white; padding:10px; margin-bottom:10px; }
.widget h1 { font-size:1.2em; }
.widget-formula .result { font-size:2em; }
</style>
</head>
<body>
<div id="container">
<div id="map"></div>
<div id="widgets">
<div id="countriesWidget" class="widget">
<h1>European countries</h1>
<select class="js-countries">
<option value="">All</option>
</select>
</div>
<div id="avgPopulationWidget" class="widget widget-formula">
<h1>Average population</h1>
<p><span class="js-average-population result">xxx</span> inhabitants</p>
</div>
</div>
</div>
<script>
const map = L.map('map').setView([50, 15], 4);
// Adding Voyager Basemap
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// Adding Voyager Labels
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', {
maxZoom: 18,
zIndex: 10
}).addTo(map);
var client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const europeanCountriesDataset = new carto.source.Dataset(`
ne_adm0_europe
`);
const europeanCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #162945;
polygon-opacity: 0.5;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.5;
}
}
`);
const europeanCountries = new carto.layer.Layer(europeanCountriesDataset, europeanCountriesStyle);
const populatedPlacesSource = new carto.source.SQL(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`);
const populatedPlacesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 8;
marker-fill: #FF583E;
marker-fill-opacity: 0.9;
marker-line-width: 0.5;
marker-line-color: #FFFFFF;
marker-line-opacity: 1;
marker-type: ellipse;
marker-allow-overlap: false;
}
`);
const populatedPlaces = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, {
featureOverColumns: ['name']
});
client.addLayers([europeanCountries, populatedPlaces]);
client.getLeafletLayer().addTo(map);
const popup = L.popup({ closeButton: false });
populatedPlaces.on(carto.layer.events.FEATURE_OVER, featureEvent => {
popup.setLatLng(featureEvent.latLng);
if (!popup.isOpen()) {
popup.setContent(featureEvent.data.name);
popup.openOn(map);
}
});
populatedPlaces.on(carto.layer.events.FEATURE_OUT, featureEvent => {
popup.removeFrom(map);
});
const averagePopulation = new carto.dataview.Formula(populatedPlacesSource, 'pop_max', {
operation: carto.operation.AVG
});
averagePopulation.on('dataChanged', data => {
refreshAveragePopulationWidget(data.result);
});
function refreshAveragePopulationWidget(avgPopulation) {
const widgetDom = document.querySelector('#avgPopulationWidget');
const averagePopulationDom = widgetDom.querySelector('.js-average-population');
averagePopulationDom.innerText = Math.floor(avgPopulation);
}
client.addDataview(averagePopulation);
const countriesDataview = new carto.dataview.Category(europeanCountriesDataset, 'admin', {
limit: 100
});
countriesDataview.on('dataChanged', data => {
const countryNames = data.categories.map(category => category.name).sort();
refreshCountriesWidget(countryNames);
});
function refreshCountriesWidget(adminNames) {
const widgetDom = document.querySelector('#countriesWidget');
const countriesDom = widgetDom.querySelector('.js-countries');
countriesDom.onchange = event => {
const admin = event.target.value;
highlightCountry(admin);
filterPopulatedPlacesByCountry(admin);
};
// Fill in the list of countries
adminNames.forEach(admin => {
const option = document.createElement('option');
option.innerHTML = admin;
option.value = admin;
countriesDom.appendChild(option);
});
}
function highlightCountry(admin) {
let cartoCSS = `
#layer {
polygon-fill: #162945;
polygon-opacity: 0.5;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.5;
}
}
`;
if (admin) {
cartoCSS = `
${cartoCSS}
#layer[admin!='${admin}'] {
polygon-fill: #CDCDCD;
}
`;
}
europeanCountriesStyle.setContent(cartoCSS);
}
function filterPopulatedPlacesByCountry(admin) {
let query = `
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`;
if (admin) {
query = `
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name='${admin}'
`;
}
populatedPlacesSource.setQuery(query);
}
client.addDataview(countriesDataview);
</script>
</body>
</html>

BIN
docs/img/avatar.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,9 @@
## Introduction
CARTO.js is a JavaScript library that interacts with different CARTO APIs. It is part of the [CARTO Engine](https://carto.com/pricing/engine/) ecosystem.
To understand the fundamentals of CARTO.js v4, [read the guides]({{site.cartojs_docs}}/guides/quickstart/). To view the source code, browse the [open-source repository](https://github.com/CartoDB/carto.js) in Github and contribute. Otherwise, view [examples with Leaflet and Google Maps]({{site.cartojs_docs}}/examples/) or find different [support options]({site.cartojs_docs}}/support/support-options/).
If you find any trouble understanding any term written in this reference, please visit our [glossary]({{site.cartojs_docs}}/guides/glossary/)
The contents described in this document are subject to CARTO's [Terms of Service](https://carto.com/legal/)

View File

@ -0,0 +1,16 @@
## Authentication
CARTO.js v4 requires using an API Key. From your CARTO dashboard, click _[Your API keys](https://carto.com/login)_ from the avatar drop-down menu to view your uniquely generated API Key for managing data with CARTO Engine.
![Your API Keys](../img/avatar.gif)
Learn more about the [basics of authorization]({{site.fundamental_docs}}/authorization/), or dig into the details of [Auth API]({{site.authapi_docs}}/), if you want to know more about this part of CARTO platform.
The examples in this documentation include a placeholder for the API Key. Ensure that you modify any placeholder parameters with your own credentials. You will have to supply your unique API Key to a [`carto.Client`](#cartoclient).
```javascript
var client = new carto.Client({
apiKey: 'YOUR_API_KEY_HERE',
username: 'YOUR_USERNAME_HERE'
});
```

View File

@ -0,0 +1,10 @@
## Versioning
CARTO.js uses [Semantic Versioning](http://semver.org/). View our Github repository to find tags for each [release](https://github.com/CartoDB/carto.js/releases).
To get the version number programmatically, use `carto.version`.
```javascript
console.log(carto.version);
// returns the version of the library
```

View File

@ -0,0 +1,20 @@
## Loading the Library
CARTO.js is hosted on a CDN for easy loading. You can load the full source "carto.js" file or the minified version "carto.min.js". Once the script is loaded, you will have a global `carto` namespace.
CARTO.js is hosted in NPM as well. You can require it as a dependency in your custom apps.
```html
<!-- CDN: load the latest CARTO.js version -->
<script src="https://libs.cartocdn.com/carto.js/%CURRENT_VERSION%/carto.min.js"></script>
<!-- CDN: load a specific CARTO.js version-->
<script src="https://libs.cartocdn.com/carto.js/%VERSION%/carto.min.js"></script>
```
```javascript
// NPM: load the latest CARTO.js version
npm install @carto/carto.js
// or
yarn add @carto/carto.js
var carto = require('@carto/carto.js');
```

View File

@ -0,0 +1,20 @@
## Error Handling
Most of the errors fired by the library are handled by the client itself. The client will trigger a `CartoError` every time an error happens.
A cartoError is an object containing a single `message` field with a string explaining the error.
Some methods in CARTO.js are asynchronous. This means that they return a promise that will be fulfilled when the asynchronous work is done or rejected with a `CartoError` when an error occurs.
```javascript
// All errors are passed to the client.
client.on(carto.events.ERROR, cartoError => {
console.error(cartoError.message):
})
// .addLayer() is async.
client.addLayer(newLayer)
.then(successCallback)
.catch(errorCallback);
```

View File

@ -0,0 +1,38 @@
## Support Options
Feeling stuck? There are many ways to find help.
* Ask a question on [GIS StackExchange](https://gis.stackexchange.com/questions/tagged/carto) using the `CARTO` tag.
* [Report an issue](https://github.com/CartoDB/carto.js/issues) in Github.
* Enterprise Plan customers have additional access to enterprise-level support through CARTO's support representatives.
If you just want to describe an issue or share an idea, just <a class="typeform-share" href="https://cartohq.typeform.com/to/mH6RRl" data-mode="popup" target="_blank"> send your feedback</a><script>(function() { var qs,js,q,s,d=document, gi=d.getElementById, ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm_share", b="https://embed.typeform.com/"; if(!gi.call(d,id)){ js=ce.call(d,"script"); js.id=id; js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })() </script>.
### Issues on Github
If you think you may have found a bug, or if you have a feature request that you would like to share with the CARTO.js team, please [open an issue](https://github.com/cartodb/carto.js/issues/new).
Before opening an issue, review the [contributing guidelines](https://github.com/CartoDB/carto.js/blob/develop/CONTRIBUTING.md#filling-a-ticket).
### Community support on GIS Stack Exchange
GIS Stack Exchange is the most popular community in the geospatial industry. This is a collaboratively-edited question and answer site for geospatial programmers and technicians. It is a fantastic resource for asking technical questions about developing and maintaining your application.
Members of the CARTO.js team regularly monitor the `carto` tag. You can look for CARTO topics by adding `carto` or `carto.js` to your search query. You can also add additional tags to your question in order to attract the attention of experts in related technologies.
When posting a new question, please consider the following:
* Read the GIS Stack Exchange [help](https://gis.stackexchange.com/help) and [how to ask](https://gis.stackexchange.com/help/how-to-ask) pages for guidelines and tips about posting questions.
* Be very clear about your question in the subject. A clear explanation helps those trying to answer your question, as well as those who may be looking for information in the future.
* Be informative in your post. Details, code snippets, logs, screenshots, etc. help others to understand your problem.
* Use code that demonstrates the problem. It is very hard to debug errors without sample code to reproduce the problem.
### Enterprise Plan Customers
Enterprise Plan customers have additional support options beyond general community support. As per your account Terms of Service, you have access to enterprise-level support through CARTO's support representatives available at [enterprise-support@carto.com](mailto:enterprise-support@carto.com)
In order to speed up the resolution of your issue, provide as much information as possible (even if it is a link from community support). This allows our engineers to investigate your problem as soon as possible.
If you are not yet CARTO customer, browse our [plans & pricing](https://carto.com/pricing/) and find the right plan for you.

51
docs/support/02-faq.md Normal file
View File

@ -0,0 +1,51 @@
## FAQs
CARTO.js v4 introduces new concepts that in some cases, change the behavior of old components. This section clarifies those changes and describe new functionality.
### Do I need an API Key?
Yes. See the guide _[Get API Key]({{site.cartojs_docs}}/guides/get-api-key/)_ or the [full reference API]({{site.cartojs_docs}}/reference/#authentication) for details.
If you want to learn more about authorization and authentication in the CARTO Platform, read the [fundamentals]({{site.fundamental_docs}}/authorization/) about this topic, or dig into the [Auth API]({{site.authapi_docs}}/) details.
### How do I pay for my API Keys?
All billing is managed through your CARTO account.
The release of the updated CARTO.js library does not impact your plan in any way. There are no changes in terms of costs or payments of your CARTO use.
### What are the main features of this release?
This new library allows you to create custom Location Intelligence applications using Builder capabilities.
Highlights of this release include the ability to:
1. Display data from datasets managed in Builder on a Leaflet map.
2. Manage layers programmatically.
3. Get data from CARTO to create custom UI components using Dataviews.
You can learn more about these main features reading the [final release announcement]({{site.cartojs_docs}}/support/release-announcement/).
### Where's the repository now?
The repo has been renamed and moved to https://github.com/CartoDB/carto.js.
### Does CARTO.js support Named Maps?
No.
Named Maps was a powerful and popular feature yet not easy to understand. Named maps were designed as a workaround for some of the limitations of our API keys. Named maps' purpose might be replicated by the new authorization system.
### Can I still use `cartodb.createVis` and `viz.json` URLs?
No, you cannot.
While `cartodb.createVis` and `viz.json` URLs were convenient and allowed you to prototype a map using CARTO Editor (the former version of Builder) to create a custom app, the functionality of the library has changed.
In CARTO.js v4, we are taking a more programmatic, low-level approach and identifying components that are separate from the front-end tool (CARTO Builder). This will make the API easier to use and more intuitive, giving developers greater flexibility in maintaining their core application.
### Is CartoDB.js v.3.15 still available?
Yes.
Both the [source code](https://github.com/CartoDB/carto.js/tree/v3.15.14) and the [documentation](https://carto.com/docs/carto-engine/carto-js/) are still available.

View File

@ -0,0 +1,372 @@
## Errors
CARTO.js emits error objects when something goes wrong. Errors appear in your developer console if not caught. The error object has a code and a description to help you identify the problem and troubleshoot.
### CARTO.js API Error Codes
If you encounter an error while loading CARTO.js, the following table contains a list of known errors codes and possible solutions.
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">api-key-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">apiKey property is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">api-key-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">apiKey property must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">username-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">username property is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">username-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">username property must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">non-valid-server-url</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">serverUrl is not a valid URL.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">non-matching-server-url</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">serverUrl doesn't match the username.</p>
</td>
</tr>
</tbody>
</table>
### CARTO.js Error Codes
If you find a validation error on Chrome JavaScript Console, Firefox Web Console, or any other equivalent tools in your browser, please reference the tables below to find explanations for the validation errors. Each table gives specific error information for the different components of CARTO.js.
### Dataview
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">source-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Source property is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">column-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Column property is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">column-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Column property must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">empty-column</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Column property must be not empty.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">filter-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Filter property is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">time-series-options-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Options object to create a time series dataview is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">time-series-invalid-aggregation</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Time aggregation must be a valid value. Use carto.dataview.timeAggregation.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">time-series-invalid-offset</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Offset must an integer value between -12 and 14.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">time-series-invalid-uselocaltimezone</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">useLocalTimezone must be a boolean value.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">histogram-options-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Options object to create a histogram dataview is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">histogram-invalid-bins</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Bins must be a positive integer value.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">formula-options-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Formula dataview options are not defined.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">formula-invalid-operation</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Operation for formula dataview is not valid. Use carto.operation.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-options-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Category dataview options are not defined.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-limit-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Limit for category dataview is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-limit-number</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Limit for category dataview must be a number.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-limit-positive</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Limit for category dataview must be greater than 0.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-invalid-operation</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Operation for category dataview is not valid. Use carto.operation.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-operation-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Operation column for category dataview is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-operation-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Operation column for category dataview must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">category-operation-empty</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Operation column for category dataview must be not empty.</p>
</td>
</tr>
</tbody>
</table>
### Filter
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">invalid-bounds-object</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Bounds object is not valid. Use a <code>carto.filter.Bounds object</code>.</p>
</td>
</tr>
</tbody>
</table>
### Layer
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">non-valid-source</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">The given object is not a valid source. See <code>carto.source.Base</code>.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">bad-layer-type</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">The given object is not a layer.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">non-valid-style</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">The given object is not a valid style. See <code>carto.style.Base</code>.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">source-with-different-client</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">A layer can't have a source which belongs to a different client.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">style-with-different-client</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">A layer can't have a style which belongs to a different client.</p>
</td>
</tr>
</tbody>
</table>
### Source
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">query-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">SQL Source must have a SQL query.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">query-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">SQL Query must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">no-dataset-name</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Table name is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">dataset-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Table name must be a string.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">dataset-required</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">Table name must be a string.</p>
</td>
</tr>
</tbody>
</table>
### Style
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">required-css</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">CartoCSS is required.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">css-string</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">CartoCSS must be a string.</p>
</td>
</tr>
</tbody>
</table>
### CARTO.js Platform Error Codes for Developers
If you find an error on Chrome JavaScript Console, Firefox Web Console, or any other equivalent tools on your browsers (regarding platform (aka. backend services)), please reference the table below to find explanations for the error codes.
<table id="errors-table" class="paramsTable u-vspace--24">
<thead>
<tr>
<th class="error"><h5 class="title is-small is-regular">Error Code</h5></th>
<th class="message"><h5 class="title is-small is-regular">Message</h5></th>
<th class="description"><h5 class="title is-small is-regular">Description</h5></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdParams error"><span class="params">over-platform-limits</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">You are over platform's limits.</p>
</td>
<td class="tdParams description">
<p class="text is-small u-tspace--4">In order to guarantee the performance of those APIs for every user of the CARTO platform and prevent abuse, we have set up some general limitations and restrictions on how they work.</p>
       <p class="text is-small u-tspace--4">Learn about fundamentals of [limits]({{site.fundamental_docs}}/limits/) in CARTO.</p>
</td>
</tr>
<tr>
<td class="tdParams error"><span class="params">generic-limit-error</span></td>
<td class="tdParams message">
<p class="text is-small u-tspace--4">The server is taking too long to respond.</p>
</td>
<td class="tdParams description"><p class="text is-small u-tspace--4">Due to poor conectivity or a temporary error with our servers, we cannot handle your request. Please try again soon.</p></td>
</tr>
</tbody>
</table>
### Checking Errors in your Browser
CARTO.js writes error messages to `window.console` if they are not caught. Please check the developer documentation for your browser in order to understand how you can check it.
If any errors occurred when loading CARTO.js, they appear as one or more lines in the console. You can check the [error codes table](#errors above to find te error in the error message. You can also find the details about the error message in the [Full Reference API]({{site.cartojs_docs}}/reference/).
Ensure that you are using a [supported browser]({{site.cartojs_docs}}/support/browsers/).

View File

@ -0,0 +1,15 @@
## Browser Support
CARTO.js works for the last 2 versions in any modern browser and IE11.
### Desktop Browsers
| ![Chrome](https://camo.githubusercontent.com/6bb46f736c023ca3a96263d88cc30ea94a19bd3f/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f617263686976652f6368726f6d655f31322d34382f6368726f6d655f31322d34385f34387834382e706e67) | ![Firefox](https://camo.githubusercontent.com/a2f2aef3a61ac88d31266cc5745c92a0943a51fd/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f617263686976652f66697265666f785f312e352d332f66697265666f785f312e352d335f34387834382e706e67) | ![Edge](https://cdnjs.cloudflare.com/ajax/libs/browser-logos/45.10.0/edge/edge_48x48.png) | ![Opera](https://camo.githubusercontent.com/f8b46198612edbe858c531588c179a9a564690cc/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f6f706572612f6f706572615f34387834382e706e67) | ![Safari](https://camo.githubusercontent.com/bfd047508bfa78a389415ab494cc8dcc04d94e7d/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f7361666172692f7361666172695f34387834382e706e67) | ![IE](https://cdnjs.cloudflare.com/ajax/libs/browser-logos/45.10.0/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png) |
|:-------------:|:-------------:|:-----:|:-------------:|:-----:|:-----:|
| Chrome | Mozilla | Edge | Opera | Safari | IE 11 |
### Mobile Browsers
| ![Chrome](https://camo.githubusercontent.com/6bb46f736c023ca3a96263d88cc30ea94a19bd3f/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f617263686976652f6368726f6d655f31322d34382f6368726f6d655f31322d34385f34387834382e706e67) | ![Safari](https://camo.githubusercontent.com/bfd047508bfa78a389415ab494cc8dcc04d94e7d/68747470733a2f2f63646e6a732e636c6f7564666c6172652e636f6d2f616a61782f6c6962732f62726f777365722d6c6f676f732f33392e332e302f7361666172692f7361666172695f34387834382e706e67) | ![Samsung Internet](https://cdnjs.cloudflare.com/ajax/libs/browser-logos/45.10.0/archive/samsung-internet_5/samsung-internet_5_48x48.png) |
|:-------------:|:-------------:|:-------------:|
| Mobile Chrome | Mobile Safari | Samsung Internet |

View File

@ -0,0 +1,17 @@
## v4 Release Announcement
After several months of hard work, CARTO is very proud to announce the __final release of CARTO.js v4__, which replaces our existing CartoDB.js library. We recognize that you have been anticipating an updated version for some time so before we give you the details, thank you for your patience!
The updated CARTO.js library has been __rebuilt from the ground up__. Case Studies indicated that we could change how we structured the API to make it more intuitive for developers. As a result, we created __a more low-level, programmatic approach__ which makes it easier to use and allows you to create fully customized location intelligence apps.
Some of the key features of the Beta release are:
* __A new way of displaying data__ hosted on your CARTO account, on top of Leaflet and Google Maps maps, in the form of layers.
* __A mechanism for extracting data__ from your CARTO account in predefined ways (eg: a list of categories). This is the same mechanism that Builder uses internally for its powerful widgets. It includes being able to filter this data by a bounding box.
* __A way of getting the metadata__ associated to the styles of a particular layer. For example, you will be able to get the names and colors of the categories for a layer styled using a color scheme.
We know that documentation is critical for any good JS library and used this as an opportunity to begin the redesign of how we provide documentation for all of our CARTO platform. Browse the interactive API documentation for the final release to search for specific CARTO.js methods, arguments, and sample code that can be used to build your applications.
Please use the final release and <a class="typeform-share" href="https://cartohq.typeform.com/to/mH6RRl" data-mode="popup" target="_blank">let us know what you think!</a><script>(function() { var qs,js,q,s,d=document, gi=d.getElementById, ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm_share", b="https://embed.typeform.com/"; if(!gi.call(d,id)){ js=ce.call(d,"script"); js.id=id; js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })() </script> The goal is to gather as much feedback as possible so that we can ensure CARTO.js v4 is rock-solid and super useful for all CARTO users. You can find different [support-options]({{site.cartojs_docs}}/support) if you need help.
__Happy coding!__

View File

@ -0,0 +1,36 @@
## Contribute
CARTO platform is an open-source ecosystem. You can read about the [fundamentals]({{site.fundamental_docs}}/components/) of CARTO architecture and its components.
We are more than happy to receive your contributions to the code and the documentation as well.
## Filling a ticket
If you want to open a new issue in our repository, please follow these instructions:
1. Descriptive title.
2. Write a good description, it always helps.
3. Include your browser, OS and CARTO.js version (it shows up in the browser console).
4. Specify the steps to reproduce the problem.
5. Try to add an example showing the problem (using [JSFiddle](http://jsfiddle.net), [JSBin](http://jsbin.com),...).
## Contributing code
Best part of open source, collaborate in CARTO.js code!. We like hearing from you, so if you have any bug fixed, or a new feature ready to be merged, those are the steps you should follow:
1. Fork the CARTO.js repository.
2. Create a new branch in your forked repository.
3. Commit your changes. Add new tests if it is necessary (```grunt test```), remember to follow ["How to build"](https://github.com/CartoDB/carto.js/blob/master/README.md#how-to-build) steps.
4. Open a pull request.
5. Any of the CARTO.js mantainers will take a look.
6. If everything works, it will merged and released \o/.
If you want more detailed information, this [GitHub guide](https://guides.github.com/activities/contributing-to-open-source/) is a must.
## Completing documentation
CARTO.js documentation is located in ```docs/```. That folder is the content that appears in the [Developer Center](http://carto.com/developer-center/carto-js/).
Just follow the instructions described in [contributing code](#contributing-code) and after accepting your pull request, we will make it appear online :).
## Submitting contributions
You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here](https://carto.com/contributions).

View File

@ -0,0 +1,109 @@
<html>
<head>
<title>Refactoria</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../dist/public/carto.js"></script>
<style>
* {
box-sizing: border-box;
}
body, *{ margin: 0; padding: 0; }
#map {
position: absolute;
height: 400px;
width: 50%;
top: 100px;
z-index: 0;
}
</style>
</head>
<body>
<span>Popups should position correctly even if page is scrolled</span>
<div id="map"></div>
<div style="height: 1200px; width: 3000px;"></div>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const populatedPlacesSource = new carto.source.Dataset(`
ne_10m_populated_places_simple
`);
const populatedPlacesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const populatedPlacesLayer = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, {
featureOverColumns: ['name', 'pop_max', 'pop_min']
});
client.addLayer(populatedPlacesLayer);
client.getLeafletLayer().addTo(map);
const popup = L.popup({ closeButton: false });
function openPopup(featureEvent) {
let content = '<div class="widget">';
if (featureEvent.data.name) {
content += `<h2 class="h2">${featureEvent.data.name}</h2>`;
}
if (featureEvent.data.pop_max || featureEvent.data.pop_min) {
content += `<ul>`;
if (featureEvent.data.pop_max) {
content += `<li><h3>Max:</h3><p class="open-sans">${featureEvent.data.pop_max}</p></li>`;
}
if (featureEvent.data.pop_min) {
content += `<li><h3>Min:</h3><p class="open-sans">${featureEvent.data.pop_min}</p></li>`;
}
content += `</ul>`;
}
content += `</div>`;
popup.setContent(content);
popup.setLatLng(featureEvent.latLng);
if (!popup.isOpen()) {
popup.openOn(map);
}
}
function closePopup(featureEvent) {
popup.removeFrom(map);
}
function setPopupsClick() {
populatedPlacesLayer.off('featureOver');
populatedPlacesLayer.off('featureOut');
populatedPlacesLayer.on('featureClicked', openPopup);
}
setPopupsClick();
</script>
</body>
</html>

View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width">
<!-- Include Carto.js -->
<script src="../../dist/public/carto.js"></script>
<!-- Include Leaflet -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places,visualization,drawing"></script>
</head>
<body>
<button onclick="LAYERS.loadLayer('europe')">Activar capa</button>
<button onclick="LAYERS.removeLayer('europe')">Desactivar capa</button>
<div id="map" style="width: 100%;height: 96vh;"></div>
<script>
const MAP = new google.maps.Map(document.getElementById('map'), {
zoom: 3,
center: { lat: 0, lng: 0 }
});
var LAYERS = {
populatedPlaces: {
loaded: false,
client: new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
}),
source: new carto.source.Dataset('ne_10m_populated_places_simple'),
cartoCSS: new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`),
},
europe: {
loaded: false,
client: new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
}),
source: new carto.source.Dataset('ne_adm0_europe'),
cartoCSS: new carto.style.CartoCSS(`
#layer {
polygon-fill: #826DBA;
polygon-opacity: 0.8;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.8;
}
}
`),
},
loadLayer: function (layerName) {
const dataset = LAYERS[layerName];
const layer = new carto.layer.Layer(dataset.source, dataset.cartoCSS, {});
window.layers = window.layers || {};
window.layers[layerName] = layer;
dataset.client.addLayer(layer)
if (!dataset.loaded) {
MAP.overlayMapTypes.push(dataset.client.getGoogleMapsMapType(MAP));
dataset.loaded = true;
}
},
removeLayer: function (layerName) {
const dataset = LAYERS[layerName];
const layer = dataset.client.getLayers()[0];
dataset.client.removeLayer(layer);
}
};
LAYERS.loadLayer('europe');
LAYERS.loadLayer('populatedPlaces');
</script>
</body>
</html>

268
examples/examples.json Normal file
View File

@ -0,0 +1,268 @@
{
"main": {
"file": {
"leaflet": "public/layers/change-order-leaflet.html",
"gmaps": "public/layers/change-order-gmaps.html"
}
},
"categories": [
{
"title": "Basics",
"samples": [
{
"title": "Add a layer",
"desc": "Add one CARTO layer to your map",
"file": {
"leaflet": "public/layers/single-layer-leaflet.html",
"gmaps": "public/layers/single-layer-gmaps.html"
}
},
{
"title": "Add more layers",
"desc": "Add multiple CARTO layers to your map",
"file": {
"leaflet": "public/layers/multilayer-leaflet.html",
"gmaps": "public/layers/multilayer-gmaps.html"
}
},
{
"title": "Change the source",
"desc": "Update the source of your layers",
"file": {
"leaflet": "public/layers/change-source-leaflet.html",
"gmaps": "public/layers/change-source-gmaps.html"
}
},
{
"title": "Change the style",
"desc": "Update the style of your layers",
"file": {
"leaflet": "public/layers/change-style-leaflet.html",
"gmaps": "public/layers/change-style-gmaps.html"
}
},
{
"title": "Move the layers",
"desc": "Update the order of your layers",
"file": {
"leaflet": "public/layers/change-order-leaflet.html",
"gmaps": "public/layers/change-order-gmaps.html"
}
},
{
"title": "Server tile aggregation",
"desc": "Apply smart backend aggregation",
"file": {
"leaflet": "public/layers/layer-with-aggregation-leaflet.html",
"gmaps": "public/layers/layer-with-aggregation-gmaps.html"
}
},
{
"title": "Server tile aggregation with cluster of points",
"desc": "Apply smart backend aggregation to create a cluster of points",
"file": {
"leaflet": "public/layers/layer-with-aggregation-cluster-leaflet.html",
"gmaps": "public/layers/layer-with-aggregation-cluster-gmaps.html"
}
}
]
},
{
"title": "Interactivity",
"samples": [
{
"title": "Detect feature click",
"desc": "Interact with the features on the click event",
"file": {
"leaflet": "public/layers/feature-click-leaflet.html",
"gmaps": "public/layers/feature-click-gmaps.html"
}
},
{
"title": "Detect feature over/out",
"desc": "Interact with the features on the over/out events",
"file": {
"leaflet": "public/layers/feature-over-out-leaflet.html",
"gmaps": "public/layers/feature-over-out-gmaps.html"
}
},
{
"title": "Change the feature columns",
"desc": "Change the columns returned in the feature event",
"file": {
"leaflet": "public/layers/change-feature-columns-leaflet.html",
"gmaps": "public/layers/change-feature-columns-gmaps.html"
}
}
]
},
{
"title": "Widgets",
"samples": [
{
"title": "Formula widget",
"desc": "Create a widget with the formula dataview",
"file": "public/dataviews/formula.html"
},
{
"title": "Category widget",
"desc": "Create a widget with the category dataview",
"file": "public/dataviews/category.html"
},
{
"title": "Histogram widget",
"desc": "Create a widget with the histogram dataview",
"file": "public/dataviews/histogram.html"
},
{
"title": "Time Series widget",
"desc": "Create a widget with the time series dataview",
"file": "public/dataviews/time-series.html"
},
{
"title": "Bounding Box filter",
"desc": "Apply a map bounding box filter to the widgets",
"file": {
"leaflet": "public/filters/bounding-box-leaflet.html",
"gmaps": "public/filters/bounding-box-gmaps.html"
}
},
{
"title": "Circle filter",
"desc": "Apply a circle filter to the widgets",
"file": "public/filters/circle-filter.html"
},
{
"title": "Polygon filter",
"desc": "Apply a polygon filter to the widgets",
"file": "public/filters/polygon-filter.html"
},
{
"title": "Status and error handling",
"desc": "Manage the status and erros in dataviews",
"file": "public/dataviews/error-handling.html"
}
]
},
{
"title": "Filters",
"samples": [
{
"title": "Category Filter",
"desc": "Create a Category filter with checkbox selectors",
"file": "public/filters/category-filter.html"
},
{
"title": "Range Filter",
"desc": "Create a Range filter with a range slider",
"file": "public/filters/range-filter.html"
},
{
"title": "AND Filter",
"desc": "Apply an AND filter to combine multiple filters",
"file": "public/filters/and-filter.html"
},
{
"title": "Complex Filter",
"desc": "Apply several combined filters to a dataset",
"file": "public/filters/complex-filter.html"
}
]
},
{
"title": "Misc",
"samples": [
{
"title": "Guide",
"desc": "Full reference guide example",
"file": {
"leaflet": "public/misc/guide-leaflet.html",
"gmaps": "public/misc/guide-gmaps.html"
}
},
{
"title": "Pop-Ups",
"desc": "Create pop-up information windows and interact with your map",
"file": {
"leaflet": "public/misc/popups-leaflet.html",
"gmaps": "public/misc/popups-gmaps.html"
}
},
{
"title": "Pop-Ups with embed videos",
"desc": "Create pop-up information windows with embed videos.",
"file": {
"leaflet": "public/misc/popups-video-leaflet.html",
"gmaps": "public/misc/popups-video-gmaps.html"
}
},
{
"title": "Legends",
"desc": "Create dynamic legends",
"file": {
"leaflet": "public/misc/legends-leaflet.html",
"gmaps": "public/misc/legends-gmaps.html"
}
},
{
"title": "Most/less populated places",
"desc": "Filter the 20 most/less populated places in the world",
"file": {
"leaflet": "public/misc/populated-places-leaflet.html",
"gmaps": "public/misc/populated-places-gmaps.html"
}
},
{
"title": "Edit SQL & CartoCSS",
"desc": "Edit manually the SQL query and the CartoCSS style",
"file": {
"leaflet": "public/misc/edit-sql-cartocss-leaflet.html",
"gmaps": "public/misc/edit-sql-cartocss-gmaps.html"
}
},
{
"title": "Error handling",
"desc": "Handle common errors in maps",
"file": {
"leaflet": "public/misc/error-handling-leaflet.html",
"gmaps": "public/misc/error-handling-gmaps.html"
}
},
{
"title": "Hexagon aggregation",
"desc": "Aggregate point data into hexagon grid",
"file": {
"leaflet": "public/misc/hexagon-aggregation-leaflet.html",
"gmaps": "public/misc/hexagon-aggregation-gmaps.html"
}
},
{
"title": "Filter data using drawing tools",
"desc": "Filter data based on a drawn circle",
"file": {
"leaflet": "public/misc/filter-data-map-leaflet.html",
"gmaps": "public/misc/filter-data-map-gmaps.html"
}
},
{
"title": "Dropdown menu with data from CARTO dataset",
"desc": "Look for data within your dataset using dropdown menu.",
"file": {
"leaflet": "public/misc/custom-search-dataset-leaflet.html",
"gmaps": "public/misc/custom-search-dataset-gmaps.html"
}
},
{
"title": "Storymap using CARTO.js and Storymap.js",
"desc": "Create a storytelling map using Storymap.js",
"file": "public/misc/storymap-leaflet.html"
},
{
"title": "Pie Chart Widget using CARTO.js and Vega-Lite",
"desc": "Create a map with a pie chart using Vega Lite and CARTO.js category dataviews.",
"file": "public/misc/piechart-vega.html"
}
]
}
]
}

44
examples/index.html Normal file
View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Examples | CARTO</title>
<link type="text/css" rel="stylesheet" href="../../docs/v4/styles/jsdoc-default.css">
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
<h1 class="page-title">Examples</h1>
<div id="container" style="margin-left:48px;"></div>
<h4 style="margin-left:30px">CDN:<a href="../dist/public/carto.js"> ../dist/public/carto.js</a></h4>
<script>
$(function () {
$.getJSON('./examples.json').done(function(data) {
renderCategories(data.categories);
});
function renderCategories(categories) {
var $container = $('#container');
categories.forEach(function (category) {
const $category = $(`<h2>${category.title}</h2>`);
const $samples = $(`<ul></ul>`);
if (category.samples) {
category.samples.forEach(function (sample) {
let link = ''
if (typeof sample.file === 'string') {
link = `(<a href="${sample.file}">Link</a>)`;
} else {
link = `(<a href="${sample.file.leaflet}">Leaflet</a> | <a href="${sample.file.gmaps}">Google Maps</a>)`;
}
const $sample = $(`<li><h3>${sample.title} <span style="font-size:0.8em;">${link}</span></h3></li>`);
$samples.append($sample);
});
}
$container.append($category);
$container.append($samples);
});
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,351 @@
<!DOCTYPE html>
<html>
<head>
<title>Basemap selector | CARTO</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
html {
font-family: 'Open Sans';
}
html,
body,
#map {
height: 100%;
padding: 0;
margin: 0;
}
#basemapSelector {
background: white;
right: 30px;
top: 30px;
padding: 10px;
position: absolute;
}
#basemapSelector h1 {
font-size: 1.6em;
line-height: 120%;
}
#basemapSelector h2 {
font-size: 1.2em;
line-height: 120%;
}
#basemapSelector ul {
margin: 10px 0;
}
</style>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="map"></div>
<div id="basemapSelector">
<h1>Basemap selector</h1>
<h2>CartoDB</h2>
<ul>
<li>
<a href="#" class="js-basemap" data-basemap-id="cartodb-positron" data-provider="leaflet">Positron</a>
</li>
<li>
<a href="#" class="js-basemap" data-basemap-id="cartodb-dark-matter" data-provider="leaflet">Dark Matter</a>
</li>
</ul>
<h2>Google Maps</h2>
<ul>
<li>
<a href="#" class="js-basemap" data-basemap-id="gmaps-roadmap" data-provider="googlemaps">Roadmap</a>
</li>
<li>
<a href="#" class="js-basemap" data-basemap-id="gmaps-satellite" data-provider="googlemaps">Satellite</a>
</li>
</ul>
</div>
<!-- include google maps library -->
<script type="text/javascript" src="http://www.maps.google.com/maps/api/js?key=AIzaSyCk5gRspKeHNJ0sS6iZotUsQvlAkXsieFg&v=3.32"></script>
<!-- include cartodb.js library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<script>
var BASEMAPS = {
'cartodb-positron': {
'urlTemplate': 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
'attribution': '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
},
'cartodb-dark-matter': {
'urlTemplate': 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png',
'attribution': '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
},
'gmaps-roadmap': {
'baseType': 'roadmap',
'style': '[]'
},
'gmaps-satellite': {
'baseType': 'satellite',
'style': '[]'
}
};
var currentProvider = 'leaflet';
var cartoDBMap;
function replaceBasemap(newProvider, basemapId) {
var basemapAttrs = BASEMAPS[basemapId];
if (!cartoDBMap) throw new Error('map not initialised yet');
if (!basemapAttrs) throw new Error('unknown basemap');
// Remove the current baselayer
cartoDBMap.removeLayerAt(0);
var changingProvider = currentProvider !== newProvider;
var createLayerMethod;
if (newProvider === 'googlemaps') {
createLayerMethod = cartoDBMap.createGMapsBaseLayer;
} else { // leaflet
createLayerMethod = cartoDBMap.createTileLayer;
}
createLayerMethod.call(cartoDBMap, basemapAttrs, {
at: 0,
silent: changingProvider
});
if (changingProvider) {
cartoDBMap.set('provider', newProvider);
currentProvider = newProvider;
}
}
$('.js-basemap').click(function (e) {
e.preventDefault();
replaceBasemap($(this).data('provider'), $(this).data('basemap-id'));
});
function main() {
var vizjson = {
"id": "2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version": "0.1.0",
"title": "european_countries_e 0",
"likes": 0,
"description": null,
"scrollwheel": true,
"legends": true,
"url": null,
"map_provider": "leaflet",
"center": "[52.5897007687178, 52.734375]",
"zoom": 4,
"updated_at": "2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true, // This is sometimes set in the editor,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers": [
{
"options": {
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"visible": true,
"type": "Tiled",
"name": "Positron",
"className": "default positron_rainbow",
"baseType": "positron_rainbow",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only": true,
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains": "abcd",
"category": "CartoDB"
},
"infowindow": null,
"tooltip": null,
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"type": "tiled"
},
{
"id": "923b7812-2d56-41c6-ac15-3ce430db090f",
"type": "CartoDB",
"infowindow": {
"fields": [
{
"name": "name",
"title": true,
"position": 4
}
],
"template": '' +
'<div class="CDB-infowindow CDB-infowindow--custom js-infowindow" style="max-width: 200px;">' +
'<div class="CDB-infowindow-close js-close"></div>' +
'<div class="CDB-infowindow-container">' +
'<div class="CDB-infowindow-header CDB-infowindow-headerBg CDB-infowindow-headerBg--dark">' +
'<div class="CDB-infowindow-list">' +
'<div class="CDB-infowindow-listItem">' +
'<h4 class="CDB-infowindow-title">{{ name }}</h4>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="CDB-hook CDB-hook--white">' +
'<div class="CDB-hook-inner">' +
'</div>' +
'</div>' +
'</div>' +
'</div>',
"alternative_names": {},
"width": 226,
"maxHeight": 180
},
"tooltip": {
"fields": [
{
"name": "name",
"title": true,
"position": 1
}
],
"template_name": "tooltip_light",
"template": ' ' +
'<div class="CDB-Tooltip CDB-Tooltip--isDark js-content">' +
'<ul class="CDB-Tooltip-list">' +
'{{#fields}}' +
'<li class="CDB-Tooltip-listItem">' +
'<h3 class="CDB-Tooltip-listTitle">NAME</h3>' +
'<h4 class="CDB-Tooltip-listText">{{value}}</h4>' +
'</li>' +
'{{/fields}}' +
'</ul>' +
'</div>',
"alternative_names": {},
"maxHeight": 180
},
"legend": {
"type": "choropleth",
"show_title": false,
"title": "",
"template": "",
"items": [
{
"name": "Left label",
"visible": true,
"value": "5592.00",
"type": "text"
},
{
"name": "Right label",
"visible": true,
"value": "1638094.00",
"type": "text"
},
{
"name": "Color",
"visible": true,
"value": "#FFFFB2",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FED976",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FEB24C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FD8D3C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FC4E2A",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#E31A1C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#B10026",
"type": "color"
}
]
},
"order": 1,
"visible": true,
"options": {
"sql": "select * from european_countries_e",
"layer_name": "european_countries_e",
"cartocss": "/** choropleth visualization */\n\n#european_countries_e{\n polygon-fill: #FFFFB2;\n polygon-opacity: 0.8;\n line-color: #FFF;\n line-width: 1;\n line-opacity: 0.5;\n}\n#european_countries_e [ area <= 1638094] {\n polygon-fill: #B10026;\n}\n#european_countries_e [ area <= 55010] {\n polygon-fill: #E31A1C;\n}\n#european_countries_e [ area <= 34895] {\n polygon-fill: #FC4E2A;\n}\n#european_countries_e [ area <= 12890] {\n polygon-fill: #FD8D3C;\n}\n#european_countries_e [ area <= 10025] {\n polygon-fill: #FEB24C;\n}\n#european_countries_e [ area <= 9150] {\n polygon-fill: #FED976;\n}\n#european_countries_e [ area <= 5592] {\n polygon-fill: #FFFFB2;\n}",
"cartocss_version": "2.1.1",
"table_name": "\"\"."
}
}
],
"overlays": [
{
"type": "loader",
"options": {
"display": true,
"x": 20,
"y": 150
}
},
{
"type": "search",
"options": {
"display": true
}
},
{
"type": "zoom",
"options": {
"x": 20,
"y": 20,
"display": true
}
}
],
"prev": null,
"next": null,
"transition_options": {}
};
cartodb.createVis('map', vizjson, {})
.done(function (vis, layers) {
cartoDBMap = vis.map;
})
.error(function (err) {
console.log(err);
});
}
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,596 @@
<!DOCTYPE html>
<html>
<head>
<title>Geometry Editor | CARTO</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
body {
font-family: 'Open Sans';
display: flex;
flex-direction: row;
}
.sidebar-title {
line-height: 2em;
padding: 0 10px;
text-transform: uppercase;
}
.sidebar-title-dark {
background: black;
color: white;
}
#sidebar {
width: 300px;
height: 100%;
display: flex;
flex-direction: column;
}
#map {
height: 100%;
flex: 1;
position: relative;
}
#controls {
padding: 10px;
}
#controls button {
font-size: 14px;
color: blue;
text-decoration: underline;
display: block;
margin-bottom: 10px;
}
#controls button.is-enabled {
color: red;
text-decoration: none;
}
#geojsonViewer {
flex: 1;
padding: 10px;
background: black;
}
#geojsonViewer textarea {
background: black;
font-family: "Lucida Console", Monaco, monospace;
font-size: 12px;
border: none;
color: #CDCDCD;
width: 100%;
height: 100%;
outline: none;
}
h1 {
font-size: 2em;
line-height: 1em;
margin: 10px;
}
</style>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
</head>
<body>
<div id="sidebar">
<h1>Geometry Editor</h1>
<p class="sidebar-title">Tools</p>
<div id="controls">
<button class="js-drawing-control js-draw-point">Draw Point</button>
<button class="js-drawing-control js-draw-line">Draw Polyline</button>
<button class="js-drawing-control js-draw-polygon">Draw Polygon</button>
<br/>
<button class="js-drawing-control js-edit-geometry-point">Edit Point</button>
<button class="js-drawing-control js-edit-geometry-polyline">Edit Polyline</button>
<button class="js-drawing-control js-edit-geometry-polygon">Edit Polygon</button>
<br/>
<button class="js-drawing-control js-edit-geometry-multi-point">Edit MultiPoint</button>
<button class="js-drawing-control js-edit-geometry-multi-polyline">Edit MultiPolyline</button>
<button class="js-drawing-control js-edit-geometry-multi-polygon">Edit MultiPolygon</button>
<br/>
<button class="js-drawing-control js-edit-features">Click & Edit</button>
</div>
<p class="sidebar-title sidebar-title-dark">GeoJSON</p>
<div id="geojsonViewer">
<textarea class="js-geojson-textarea" readonly></textarea>
</div>
</div>
<div id="map"></div>
<!-- include google maps library -->
<script type="text/javascript" src="http://www.maps.google.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- include cartodb.js library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<script>
var vizjson = {
"id": "2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version": "0.1.0",
"title": "european_countries_e 0",
"likes": 0,
"description": null,
"scrollwheel": true,
"legends": true,
"url": null,
"map_provider": "leaflet",
"center": "[52.5897007687178, 52.734375]",
"zoom": 4,
"updated_at": "2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true, // This is sometimes set in the editor,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers": [
{
"options": {
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"visible": true,
"type": "Tiled",
"name": "Positron",
"className": "default positron_rainbow",
"baseType": "positron_rainbow",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only": true,
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains": "abcd",
"category": "CartoDB"
},
"infowindow": null,
"tooltip": null,
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"type": "tiled"
},
{
"id": "923b7812-2d56-41c6-ac15-3ce430db090f",
"type": "CartoDB",
"infowindow": {
"fields": [
{
"name": "name",
"title": true,
"position": 4
}
],
"template": '' +
'<div class="CDB-infowindow CDB-infowindow--custom js-infowindow" style="max-width: 200px;">' +
'<div class="CDB-infowindow-close js-close"></div>' +
'<div class="CDB-infowindow-container">' +
'<div class="CDB-infowindow-header CDB-infowindow-headerBg CDB-infowindow-headerBg--dark">' +
'<div class="CDB-infowindow-list">' +
'<div class="CDB-infowindow-listItem">' +
'<h4 class="CDB-infowindow-title">{{ name }}</h4>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="CDB-hook CDB-hook--white">' +
'<div class="CDB-hook-inner">' +
'</div>' +
'</div>' +
'</div>' +
'</div>',
"alternative_names": {},
"width": 226,
"maxHeight": 180
},
"tooltip": {
"fields": [
{
"name": "name",
"title": true,
"position": 1
}
],
"template_name": "tooltip_light",
"template": ' ' +
'<div class="CDB-Tooltip CDB-Tooltip--isDark js-content">' +
'<ul class="CDB-Tooltip-list">' +
'{{#fields}}' +
'<li class="CDB-Tooltip-listItem">' +
'<h3 class="CDB-Tooltip-listTitle">NAME</h3>' +
'<h4 class="CDB-Tooltip-listText">{{value}}</h4>' +
'</li>' +
'{{/fields}}' +
'</ul>' +
'</div>',
"alternative_names": {},
"maxHeight": 180
},
"legend": {
"type": "choropleth",
"show_title": false,
"title": "",
"template": "",
"items": [
{
"name": "Left label",
"visible": true,
"value": "5592.00",
"type": "text"
},
{
"name": "Right label",
"visible": true,
"value": "1638094.00",
"type": "text"
},
{
"name": "Color",
"visible": true,
"value": "#FFFFB2",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FED976",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FEB24C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FD8D3C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FC4E2A",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#E31A1C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#B10026",
"type": "color"
}
]
},
"order": 1,
"visible": true,
"options": {
"sql": "select * from european_countries_e",
"layer_name": "european_countries_e",
"cartocss": "/** choropleth visualization */\n\n#european_countries_e{\n polygon-fill: #FFFFB2;\n polygon-opacity: 0.8;\n line-color: #FFF;\n line-width: 1;\n line-opacity: 0.5;\n}\n#european_countries_e [ area <= 1638094] {\n polygon-fill: #B10026;\n}\n#european_countries_e [ area <= 55010] {\n polygon-fill: #E31A1C;\n}\n#european_countries_e [ area <= 34895] {\n polygon-fill: #FC4E2A;\n}\n#european_countries_e [ area <= 12890] {\n polygon-fill: #FD8D3C;\n}\n#european_countries_e [ area <= 10025] {\n polygon-fill: #FEB24C;\n}\n#european_countries_e [ area <= 9150] {\n polygon-fill: #FED976;\n}\n#european_countries_e [ area <= 5592] {\n polygon-fill: #FFFFB2;\n}",
"cartocss_version": "2.1.1",
"table_name": "\"\"."
}
}
],
"overlays": [
{
"type": "loader",
"options": {
"display": true,
"x": 20,
"y": 150
}
},
{
"type": "fullscreen",
"options": {
"x": 20,
"y": 140,
"display": true
}
},
{
"type": "search",
"options": {
"display": true
}
},
{
"type": "zoom",
"options": {
"x": 20,
"y": 20,
"display": true
}
}
],
"prev": null,
"next": null,
"transition_options": {}
};
var point = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
-3.779296875,
40.245991504199026
]
}
};
var polygon = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-8.96484375,
41.918628865183045
],
[
-7.84423828125,
43.74728909225908
],
[
-1.69189453125,
43.34914966389313
],
[
3.1091308593749996,
42.35042512243457
],
[
3.1640625,
41.828642001860544
],
[
-1.9555664062500002,
36.94111143010769
],
[
-5.55908203125,
36.00467348670187
],
[
-7.31689453125,
37.3002752813443
],
[
-6.39404296875,
41.74672584176937
],
[
-8.96484375,
41.918628865183045
]
]
]
}
};
var polyline = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-2.021484375,
43.51668853502906
],
[
3.6035156249999996,
42.293564192170095
]
]
}
};
var multiPoint = {
"type": "MultiPoint",
"coordinates": [[100.0, 0.0], [101.0, 1.0]]
};
var multiPolyline = {
"type": "MultiLineString",
"coordinates": [
[[100.0, 0.0], [101.0, 1.0]],
[[102.0, 2.0], [103.0, 3.0]]
]
};
var multiPolygon = {
"type": "MultiPolygon",
"coordinates": [
[
[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]
],
[
[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]
]
]
};
function displayGeoJSON(geometry) {
updateDisplayedGeoJSON(geometry);
geometry.on('change', updateDisplayedGeoJSON);
}
function updateDisplayedGeoJSON(geometry) {
if (geometry.isComplete()) {
$('.js-geojson-textarea').val(JSON.stringify(geometry.toGeoJSON(), null, 2));
}
}
function clearGeoJSON() {
$('.js-geojson-textarea').val('');
}
function drawPoint(vis) {
return drawGeometry(vis, vis.map.drawPoint());
}
function drawPolyline(vis) {
return drawGeometry(vis, vis.map.drawPolyline());
}
function drawPolygon(vis) {
return drawGeometry(vis, vis.map.drawPolygon());
}
function editGeometry(vis, geoJSON) {
var geometry = window.geometry = vis.map.editGeometry(geoJSON);
displayGeoJSON(geometry);
}
function enableClickToEdit(vis) {
vis.map.enableFeatureInteractivity();
vis.map.on('featureClick', fetchFeatureAndEditGeometry, this);
}
function disableClickToEdit(vis) {
vis.map.disableFeatureInteractivity();
vis.map.stopDrawingGeometry();
vis.map.off('featureClick', fetchFeatureAndEditGeometry, this);
}
function fetchFeatureAndEditGeometry(event) {
var featureID = event.feature.cartodb_id;
var tableName = 'european_countries_e';
var sql = new cartodb.SQL({
protocol: 'https',
user: 'documentation',
host: 'cartodb.com'
});
sql.execute("SELECT ST_AsGeoJSON(the_geom) AS geojson FROM {{tableName }} WHERE cartodb_id = {{id}}", { tableName: tableName, id: featureID })
.done(function (data) {
var geoJSON = JSON.parse(data.rows[0].geojson);
editGeometry(vis, geoJSON);
})
.error(function (errors) {
// errors contains a list of errors
console.log("errors:" + errors);
});
}
function drawGeometry(vis, geometry) {
window.geometry = geometry;
clearGeoJSON();
displayGeoJSON(geometry);
return geometry;
}
function enableControls(vis) {
$('.js-drawing-control').click(function () {
var clickedControl = this;
$('.js-drawing-control').each(function (index) {
var isEnabled = false;
if (clickedControl === this) {
isEnabled = !($(this).hasClass('is-enabled'));
}
$(this).toggleClass('is-enabled', isEnabled);
});
vis.map.stopDrawingGeometry();
vis.map.stopEditingGeometry();
});
document.querySelector('.js-draw-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPoint(vis);
}
});
document.querySelector('.js-draw-line').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPolyline(vis);
}
});
document.querySelector('.js-draw-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPolygon(vis);
}
});
document.querySelector('.js-edit-geometry-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, point);
}
});
document.querySelector('.js-edit-geometry-polyline').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, polyline);
}
});
document.querySelector('.js-edit-geometry-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, polygon);
}
});
document.querySelector('.js-edit-geometry-multi-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPoint);
}
});
document.querySelector('.js-edit-geometry-multi-polyline').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPolyline);
}
});
document.querySelector('.js-edit-geometry-multi-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPolygon);
}
});
document.querySelector('.js-edit-features').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
enableClickToEdit(vis);
} else {
disableClickToEdit(vis);
}
});
}
function main() {
cartodb.createVis('map', vizjson, {
legends: false,
gmaps_base_type: 'roadmap'
})
.done(function (vis, layers) {
enableControls(vis);
})
.error(function (err) {
console.log(err);
});
}
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,607 @@
<!DOCTYPE html>
<html>
<head>
<title>Geometry Editor | CARTO</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
}
body {
font-family: 'Open Sans';
display: flex;
flex-direction: row;
}
.sidebar-title {
line-height: 2em;
padding: 0 10px;
text-transform: uppercase;
}
.sidebar-title-dark {
background: black;
color: white;
}
#sidebar {
width: 300px;
height: 100%;
display: flex;
flex-direction: column;
}
#map {
height: 100%;
flex: 1;
position: relative;
}
#controls {
padding: 10px;
}
#controls button {
font-size: 14px;
color: blue;
text-decoration: underline;
display: block;
margin-bottom: 10px;
}
#controls button.is-enabled {
color: red;
text-decoration: none;
}
#geojsonViewer {
flex:1;
padding: 10px;
background: black;
}
#geojsonViewer textarea {
background: black;
font-family: "Lucida Console", Monaco, monospace;
font-size: 12px;
border: none;
color: #CDCDCD;
width: 100%;
height: 100%;
outline: none;
}
h1 {
font-size: 2em;
line-height: 1em;
margin: 10px;
}
</style>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
</head>
<body>
<div id="sidebar">
<h1>Geometry Editor</h1>
<p class="sidebar-title">Tools</p>
<div id="controls">
<button class="js-drawing-control js-draw-point">Draw Point</button>
<button class="js-drawing-control js-draw-line">Draw Polyline</button>
<button class="js-drawing-control js-draw-polygon">Draw Polygon</button>
<br/>
<button class="js-drawing-control js-edit-geometry-point">Edit Point</button>
<button class="js-drawing-control js-edit-geometry-polyline">Edit Polyline</button>
<button class="js-drawing-control js-edit-geometry-polygon">Edit Polygon</button>
<br/>
<button class="js-drawing-control js-edit-geometry-multi-point">Edit MultiPoint</button>
<button class="js-drawing-control js-edit-geometry-multi-polyline">Edit MultiPolyline</button>
<button class="js-drawing-control js-edit-geometry-multi-polygon">Edit MultiPolygon</button>
<br/>
<button class="js-drawing-control js-edit-features">Click & Edit</button>
</div>
<p class="sidebar-title sidebar-title-dark">GeoJSON</p>
<div id="geojsonViewer">
<textarea class="js-geojson-textarea" readonly></textarea>
</div>
</div>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<script>
var vizjson = {
"id":"2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version":"0.1.0",
"title":"european_countries_e 0",
"likes":0,
"description":null,
"scrollwheel":true,
"legends":true,
"url":null,
"map_provider":"leaflet",
"center":"[52.5897007687178, 52.734375]",
"zoom":4,
"updated_at":"2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true, // This is sometimes set in the editor,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers":[
{
"options":{
"id":"0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order":0,
"visible":true,
"type":"Tiled",
"name":"Positron",
"className":"default positron_rainbow",
"baseType":"positron_rainbow",
"urlTemplate":"http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only":true,
"minZoom":"0",
"maxZoom":"18",
"attribution":"&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains":"abcd",
"category":"CartoDB"
},
"infowindow":null,
"tooltip":null,
"id":"0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order":0,
"type":"tiled"
},
{
"id":"923b7812-2d56-41c6-ac15-3ce430db090f",
"type":"CartoDB",
"infowindow":{
"fields":[
{
"name":"name",
"title":true,
"position":4
}
],
"template": '' +
'<div class="CDB-infowindow CDB-infowindow--custom js-infowindow" style="max-width: 200px;">' +
'<div class="CDB-infowindow-close js-close"></div>' +
'<div class="CDB-infowindow-container">' +
'<div class="CDB-infowindow-header CDB-infowindow-headerBg CDB-infowindow-headerBg--dark">' +
'<div class="CDB-infowindow-list">' +
'<div class="CDB-infowindow-listItem">' +
'<h4 class="CDB-infowindow-title">{{ name }}</h4>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="CDB-hook CDB-hook--white">' +
'<div class="CDB-hook-inner">' +
'</div>' +
'</div>' +
'</div>' +
'</div>',
"alternative_names":{},
"width":226,
"maxHeight":180
},
"tooltip":{
"fields": [
{
"name": "name",
"title": true,
"position": 1
}
],
"template_name":"tooltip_light",
"template": ' '+
'<div class="CDB-Tooltip CDB-Tooltip--isDark js-content">'+
'<ul class="CDB-Tooltip-list">'+
'{{#fields}}'+
'<li class="CDB-Tooltip-listItem">'+
'<h3 class="CDB-Tooltip-listTitle">NAME</h3>'+
'<h4 class="CDB-Tooltip-listText">{{value}}</h4>'+
'</li>'+
'{{/fields}}'+
'</ul>'+
'</div>',
"alternative_names":{},
"maxHeight":180
},
"legend":{
"type":"choropleth",
"show_title":false,
"title":"",
"template":"",
"items":[
{
"name":"Left label",
"visible":true,
"value":"5592.00",
"type":"text"
},
{
"name":"Right label",
"visible":true,
"value":"1638094.00",
"type":"text"
},
{
"name":"Color",
"visible":true,
"value":"#FFFFB2",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FED976",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FEB24C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FD8D3C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FC4E2A",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#E31A1C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#B10026",
"type":"color"
}
]
},
"order":1,
"visible":true,
"options":{
"sql":"select * from european_countries_e",
"layer_name":"european_countries_e",
"cartocss":"/** choropleth visualization */\n\n#european_countries_e{\n polygon-fill: #FFFFB2;\n polygon-opacity: 0.8;\n line-color: #FFF;\n line-width: 1;\n line-opacity: 0.5;\n}\n#european_countries_e [ area <= 1638094] {\n polygon-fill: #B10026;\n}\n#european_countries_e [ area <= 55010] {\n polygon-fill: #E31A1C;\n}\n#european_countries_e [ area <= 34895] {\n polygon-fill: #FC4E2A;\n}\n#european_countries_e [ area <= 12890] {\n polygon-fill: #FD8D3C;\n}\n#european_countries_e [ area <= 10025] {\n polygon-fill: #FEB24C;\n}\n#european_countries_e [ area <= 9150] {\n polygon-fill: #FED976;\n}\n#european_countries_e [ area <= 5592] {\n polygon-fill: #FFFFB2;\n}",
"cartocss_version":"2.1.1",
"table_name":"\"\"."
}
},
{
"options": {
"visible": true,
"type": "Tiled",
"default": "true",
"url": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"name": "Positron Labels",
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"className": "httpsbasemapscartocdncomlight_only_labelszxypng",
"order": 3
},
"infowindow": null,
"tooltip": null,
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"order": 3,
"type": "tiled"
}
],
"overlays":[
{
"type":"loader",
"options":{
"display":true,
"x":20,
"y":150
}
},
{
"type":"fullscreen",
"options":{
"x":20,
"y":140,
"display":true
}
},
{
"type":"search",
"options":{
"display":true
}
},
{
"type":"zoom",
"options":{
"x":20,
"y":20,
"display":true
}
}
],
"prev":null,
"next":null,
"transition_options":{}
};
var point = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
-3.779296875,
40.245991504199026
]
}
};
var polygon = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-8.96484375,
41.918628865183045
],
[
-7.84423828125,
43.74728909225908
],
[
-1.69189453125,
43.34914966389313
],
[
3.1091308593749996,
42.35042512243457
],
[
3.1640625,
41.828642001860544
],
[
-1.9555664062500002,
36.94111143010769
],
[
-5.55908203125,
36.00467348670187
],
[
-7.31689453125,
37.3002752813443
],
[
-6.39404296875,
41.74672584176937
],
[
-8.96484375,
41.918628865183045
]
]
]
}
};
var polyline = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-2.021484375,
43.51668853502906
],
[
3.6035156249999996,
42.293564192170095
]
]
}
};
var multiPoint = {
"type": "MultiPoint",
"coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
};
var multiPolyline = {
"type": "MultiLineString",
"coordinates": [
[ [100.0, 0.0], [101.0, 1.0] ],
[ [102.0, 2.0], [103.0, 3.0] ]
]
};
var multiPolygon = {
"type": "MultiPolygon",
"coordinates": [
[
[ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ]
],
[
[ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
]
]
};
function displayGeoJSON (geometry) {
updateDisplayedGeoJSON(geometry);
geometry.on('change', updateDisplayedGeoJSON);
}
function updateDisplayedGeoJSON (geometry) {
if (geometry.isComplete()) {
$('.js-geojson-textarea').val(JSON.stringify(geometry.toGeoJSON(), null, 2));
}
}
function clearGeoJSON () {
$('.js-geojson-textarea').val('');
}
function drawPoint (vis) {
return drawGeometry(vis, vis.map.drawPoint());
}
function drawPolyline (vis) {
return drawGeometry(vis, vis.map.drawPolyline());
}
function drawPolygon (vis) {
return drawGeometry(vis, vis.map.drawPolygon());
}
function editGeometry (vis, geoJSON) {
var geometry = window.geometry = vis.map.editGeometry(geoJSON);
displayGeoJSON(geometry);
}
function enableClickToEdit (vis) {
vis.map.enableFeatureInteractivity();
vis.map.on('featureClick', fetchFeatureAndEditGeometry, this);
}
function disableClickToEdit (vis) {
vis.map.disableFeatureInteractivity();
vis.map.stopDrawingGeometry();
vis.map.off('featureClick', fetchFeatureAndEditGeometry, this);
}
function fetchFeatureAndEditGeometry (event) {
var featureID = event.feature.cartodb_id;
var tableName = 'european_countries_e';
var sql = new cartodb.SQL({
protocol: 'https',
user: 'documentation',
host: 'cartodb.com'
});
sql.execute("SELECT ST_AsGeoJSON(the_geom) AS geojson FROM {{tableName }} WHERE cartodb_id = {{id}}", { tableName: tableName, id: featureID })
.done(function(data) {
var geoJSON = JSON.parse(data.rows[0].geojson);
editGeometry(vis, geoJSON);
})
.error(function(errors) {
// errors contains a list of errors
console.log("errors:" + errors);
});
}
function drawGeometry (vis, geometry) {
window.geometry = geometry;
clearGeoJSON();
displayGeoJSON(geometry);
return geometry;
}
function enableControls (vis) {
$('.js-drawing-control').click(function () {
var clickedControl = this;
$('.js-drawing-control').each(function (index) {
var isEnabled = false;
if (clickedControl === this) {
isEnabled = !($(this).hasClass('is-enabled'));
}
$(this).toggleClass('is-enabled', isEnabled);
});
vis.map.stopDrawingGeometry();
vis.map.stopEditingGeometry();
});
document.querySelector('.js-draw-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPoint(vis);
}
});
document.querySelector('.js-draw-line').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPolyline(vis);
}
});
document.querySelector('.js-draw-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
drawPolygon(vis);
}
});
document.querySelector('.js-edit-geometry-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, point);
}
});
document.querySelector('.js-edit-geometry-polyline').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, polyline);
}
});
document.querySelector('.js-edit-geometry-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, polygon);
}
});
document.querySelector('.js-edit-geometry-multi-point').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPoint);
}
});
document.querySelector('.js-edit-geometry-multi-polyline').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPolyline);
}
});
document.querySelector('.js-edit-geometry-multi-polygon').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
editGeometry(vis, multiPolygon);
}
});
document.querySelector('.js-edit-features').addEventListener('click', function () {
if ($(this).hasClass('is-enabled')) {
enableClickToEdit(vis);
} else {
disableClickToEdit(vis);
}
});
}
function main () {
cartodb.createVis('map', vizjson, {
legends: false
})
.done(function (vis, layers) {
enableControls(vis);
})
.error(function (err) {
console.log(err);
});
}
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,269 @@
<!DOCTYPE html>
<html>
<head>
<title>Easy example | CARTO</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<script>
function main() {
var vizjson = {
"id":"2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version":"0.1.0",
"title":"european_countries_e 0",
"likes":0,
"description":null,
"scrollwheel":true,
"legends":true,
"url":null,
"map_provider":"leaflet",
"center":"[52.5897007687178, 52.734375]",
"zoom":4,
"updated_at":"2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true, // This is sometimes set in the editor,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers":[
{
"options":{
"id":"0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order":0,
"visible":true,
"type":"Tiled",
"name":"Positron",
"className":"default positron_rainbow",
"baseType":"positron_rainbow",
"urlTemplate":"http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only":true,
"minZoom":"0",
"maxZoom":"18",
"attribution":"&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains":"abcd",
"category":"CartoDB"
},
"infowindow":null,
"tooltip":null,
"id":"0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order":0,
"type":"tiled"
},
{
"id":"923b7812-2d56-41c6-ac15-3ce430db090f",
"type":"CartoDB",
"infowindow":{
"fields":[
{
"name":"name",
"title":true,
"position":4
}
],
"template": '' +
'<div class="CDB-infowindow CDB-infowindow--custom js-infowindow" style="max-width: 200px;">' +
'<div class="CDB-infowindow-close js-close"></div>' +
'<div class="CDB-infowindow-container">' +
'<div class="CDB-infowindow-header CDB-infowindow-headerBg CDB-infowindow-headerBg--dark">' +
'<div class="CDB-infowindow-list">' +
'<div class="CDB-infowindow-listItem">' +
'<h4 class="CDB-infowindow-title">{{ name }}</h4>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="CDB-hook CDB-hook--white">' +
'<div class="CDB-hook-inner">' +
'</div>' +
'</div>' +
'</div>' +
'</div>',
"alternative_names":{},
"width":226,
"maxHeight":180
},
"tooltip":{
"fields": [
{
"name": "name",
"title": true,
"position": 1
}
],
"template_name":"tooltip_light",
"template": ' '+
'<div class="CDB-Tooltip CDB-Tooltip--isDark js-content">'+
'<ul class="CDB-Tooltip-list">'+
'{{#fields}}'+
'<li class="CDB-Tooltip-listItem">'+
'<h3 class="CDB-Tooltip-listTitle">NAME</h3>'+
'<h4 class="CDB-Tooltip-listText">{{value}}</h4>'+
'</li>'+
'{{/fields}}'+
'</ul>'+
'</div>',
"alternative_names":{},
"maxHeight":180
},
"legend":{
"type":"choropleth",
"show_title":false,
"title":"",
"template":"",
"items":[
{
"name":"Left label",
"visible":true,
"value":"5592.00",
"type":"text"
},
{
"name":"Right label",
"visible":true,
"value":"1638094.00",
"type":"text"
},
{
"name":"Color",
"visible":true,
"value":"#FFFFB2",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FED976",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FEB24C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FD8D3C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#FC4E2A",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#E31A1C",
"type":"color"
},
{
"name":"Color",
"visible":true,
"value":"#B10026",
"type":"color"
}
]
},
"order":1,
"visible":true,
"options":{
"sql":"select * from european_countries_e",
"layer_name":"european_countries_e",
"cartocss":"/** choropleth visualization */\n\n#european_countries_e{\n polygon-fill: #FFFFB2;\n polygon-opacity: 0.8;\n line-color: #FFF;\n line-width: 1;\n line-opacity: 0.5;\n}\n#european_countries_e [ area <= 1638094] {\n polygon-fill: #B10026;\n}\n#european_countries_e [ area <= 55010] {\n polygon-fill: #E31A1C;\n}\n#european_countries_e [ area <= 34895] {\n polygon-fill: #FC4E2A;\n}\n#european_countries_e [ area <= 12890] {\n polygon-fill: #FD8D3C;\n}\n#european_countries_e [ area <= 10025] {\n polygon-fill: #FEB24C;\n}\n#european_countries_e [ area <= 9150] {\n polygon-fill: #FED976;\n}\n#european_countries_e [ area <= 5592] {\n polygon-fill: #FFFFB2;\n}",
"cartocss_version":"2.1.1",
"table_name":"\"\"."
}
},
{
"options": {
"visible": true,
"type": "Tiled",
"default": "true",
"url": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"name": "Positron Labels",
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"className": "httpsbasemapscartocdncomlight_only_labelszxypng",
"order": 3
},
"infowindow": null,
"tooltip": null,
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"order": 3,
"type": "tiled"
}
],
"overlays":[
{
"type":"loader",
"options":{
"display":true,
"x":20,
"y":150
}
},
{
"type":"fullscreen",
"options":{
"x":20,
"y":140,
"display":true
}
},
{
"type":"search",
"options":{
"display":true
}
},
{
"type":"zoom",
"options":{
"x":20,
"y":20,
"display":true
}
}
],
"prev":null,
"next":null,
"transition_options":{}
};
cartodb.createVis('map', vizjson, {})
.done(function(vis, layers) {
})
.error(function(err) {
console.log(err);
});
}
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Base example | CARTO</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<!--Include carto styles -->
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<!-- Include cartodb.js Library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<!-- Custom Map styles -->
<style>
html,
body,
#map {
font-family: "Open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
height: 100%;
padding: 0;
margin: 0;
background: #162945;
position: relative;
}
</style>
<style>
nav {
padding: 15px;
display: flex;
flex-direction: row;
background: white;
color: #162945;
border-bottom: 1px solid #eee;
font-size: 13px;
}
input {
background: none;
border: none;
}
button {
color: #FFF;
padding: 5px 10px;
background-color: #1785FB;
border-radius: 3px;
}
.CDB-OverlayContainer {
z-index: 999;
}
</style>
<script>
window.mapboxApiKey = 'pk.eyJ1IjoiY2FydG8tdGVhbSIsImEiOiJjamNseTl3ZzQwZnFkMndudnIydnJoMXZxIn0.HycQBkaaV7ZwLkHm5hEmfg';
function loadVizJson(name) {
let url = 'viz/' + name;
fetch(url)
.then(data => data.json())
.then(vizjson => {
cartodb.createVis('map', vizjson)
.done(console.log)
.error(console.error);
});
}
</script>
</head>
<body onload="loadVizJson('003.json')">
<div id="map"></div>
</body>
</html>

View File

@ -0,0 +1,203 @@
{
"id": "2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version": "0.1.0",
"title": "european_countries_e 0",
"likes": 0,
"description": null,
"scrollwheel": true,
"legends": true,
"url": null,
"map_provider": "leaflet",
"center": "[52.5897007687178, 52.734375]",
"zoom": 4,
"updated_at": "2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers": [
{
"options": {
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"visible": true,
"type": "Tiled",
"name": "Positron",
"className": "default positron_rainbow",
"baseType": "positron_rainbow",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only": true,
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains": "abcd",
"category": "CartoDB"
},
"infowindow": null,
"tooltip": null,
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"type": "tiled"
},
{
"id": "923b7812-2d56-41c6-ac15-3ce430db090f",
"type": "CartoDB",
"infowindow": {
"fields": [
{
"name": "name",
"title": true,
"position": 4
}
],
"template": "<div> {{ name }} </div>",
"alternative_names": {},
"width": 226,
"maxHeight": 180
},
"tooltip": {
"fields": [
{
"name": "name",
"title": true,
"position": 1
}
],
"template_name": "tooltip_light",
"template": "<div> TEMPLATE_1 </div>",
"alternative_names": {},
"maxHeight": 180
},
"legend": {
"type": "choropleth",
"show_title": false,
"title": "",
"template": "",
"items": [
{
"name": "Left label",
"visible": true,
"value": "5592.00",
"type": "text"
},
{
"name": "Right label",
"visible": true,
"value": "1638094.00",
"type": "text"
},
{
"name": "Color",
"visible": true,
"value": "#FFFFB2",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FED976",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FEB24C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FD8D3C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#FC4E2A",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#E31A1C",
"type": "color"
},
{
"name": "Color",
"visible": true,
"value": "#B10026",
"type": "color"
}
]
},
"order": 1,
"visible": true,
"options": {
"sql": "select * from european_countries_e",
"layer_name": "european_countries_e",
"cartocss": "/** choropleth visualization */\n\n#european_countries_e{\n polygon-fill: #FFFFB2;\n polygon-opacity: 0.8;\n line-color: #FFF;\n line-width: 1;\n line-opacity: 0.5;\n}\n#european_countries_e [ area <= 1638094] {\n polygon-fill: #B10026;\n}\n#european_countries_e [ area <= 55010] {\n polygon-fill: #E31A1C;\n}\n#european_countries_e [ area <= 34895] {\n polygon-fill: #FC4E2A;\n}\n#european_countries_e [ area <= 12890] {\n polygon-fill: #FD8D3C;\n}\n#european_countries_e [ area <= 10025] {\n polygon-fill: #FEB24C;\n}\n#european_countries_e [ area <= 9150] {\n polygon-fill: #FED976;\n}\n#european_countries_e [ area <= 5592] {\n polygon-fill: #FFFFB2;\n}",
"cartocss_version": "2.1.1",
"table_name": "\"\"."
}
},
{
"options": {
"visible": true,
"type": "Tiled",
"default": "true",
"url": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
"name": "Positron Labels",
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"className": "httpsbasemapscartocdncomlight_only_labelszxypng",
"order": 3
},
"infowindow": null,
"tooltip": null,
"id": "bc054932-1ae8-4d4a-96d6-d49ce4247a59",
"order": 3,
"type": "tiled"
}
],
"overlays": [
{
"type": "loader",
"options": {
"display": true,
"x": 20,
"y": 150
}
},
{
"type": "fullscreen",
"options": {
"x": 20,
"y": 140,
"display": true
}
},
{
"type": "search",
"options": {
"display": true
}
},
{
"type": "zoom",
"options": {
"x": 20,
"y": 20,
"display": true
}
}
],
"prev": null,
"next": null,
"transition_options": {}
}

View File

@ -0,0 +1,170 @@
{
"bounds": [
[
-73.8273,
-179
],
[
83.261,
179
]
],
"center": "[41, -3]",
"datasource": {
"user_name": "cartojs-test",
"maps_api_template": "https://{user}.carto.com:443",
"stat_tag": "3626e3ca-1e40-4e5c-95f8-f83b54131ddc"
},
"description": "<p>Basic test displaying points in red.</p>\n",
"options": {
"dashboard_menu": true,
"layer_selector": false,
"legends": true,
"scrollwheel": true
},
"id": "3626e3ca-1e40-4e5c-95f8-f83b54131ddc",
"layers": [
{
"id": "e7bbdf2c-8e66-49f3-b7b8-793e3a4fd6ea",
"type": "tiled",
"options": {
"default": "true",
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"name": "Voyager",
"className": "voyager_labels",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"labels": {
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png"
},
"urlTemplate": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png"
}
},
{
"id": "b39d9e30-1a03-48d2-8734-4e700632f800",
"legends": [],
"type": "CartoDB",
"infowindow": {
"template_name": "none",
"fields": [],
"maxHeight": 180,
"template": "",
"alternative_names": {},
"width": 226,
"headerColor": {
"color": {
"fixed": "#35AAE5",
"opacity": 1
}
}
},
"tooltip": {
"fields": [],
"template_name": "none",
"template": "",
"template_type": "mustache"
},
"visible": true,
"options": {
"layer_name": "ne_10m_populated_places_simple",
"cartocss": "#layer {\n marker-width: 10;\n marker-fill: #ff0900;\n marker-fill-opacity: 1;\n marker-allow-overlap: true;\n marker-line-width: 1;\n marker-line-color: #FFFFFF;\n marker-line-opacity: 1;\n}",
"cartocss_version": "2.1.1",
"attribution": "",
"source": "a0"
}
},
{
"id": "7a5e026f-d014-43a7-b0c3-403eaabc889d",
"type": "tiled",
"options": {
"default": "true",
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"urlTemplate": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png",
"type": "Tiled",
"name": "Voyager Labels"
}
}
],
"likes": 0,
"map_provider": "leaflet",
"overlays": [
{
"type": "share",
"order": 2,
"options": {
"display": true,
"x": 20,
"y": 20
},
"template": ""
},
{
"type": "search",
"order": 3,
"options": {
"display": true,
"x": 60,
"y": 20
},
"template": ""
},
{
"type": "zoom",
"order": 6,
"options": {
"display": true,
"x": 20,
"y": 20
},
"template": "<a href=\"#zoom_in\" class=\"zoom_in\">+</a> <a href=\"#zoom_out\" class=\"zoom_out\">-</a>"
},
{
"type": "loader",
"order": 8,
"options": {
"display": true,
"x": 20,
"y": 150
},
"template": "<div class=\"loader\" original-title=\"\"></div>"
},
{
"type": "logo",
"order": 9,
"options": {
"display": true,
"x": 10,
"y": 40
},
"template": ""
}
],
"title": "001-Test",
"updated_at": "2017-10-24T11:29:21+00:00",
"user": {
"fullname": "cartojs-test",
"avatar_url": "//cartodb-libs.global.ssl.fastly.net/cartodbui/assets/unversioned/images/avatars/avatar_planet_orange.png",
"profile_url": "https://cartojs-test.carto.com"
},
"version": "3.0.0",
"widgets": [],
"zoom": 7,
"analyses": [
{
"id": "a0",
"type": "source",
"params": {
"query": "SELECT * FROM ne_10m_populated_places_simple"
},
"options": {
"table_name": "ne_10m_populated_places_simple"
}
}
]
}

View File

@ -0,0 +1,262 @@
{
"bounds": [
[
-73.8273,
-179
],
[
83.261,
179
]
],
"center": "[41, -3]",
"datasource": {
"user_name": "cartojs-test",
"maps_api_template": "https://{user}.carto.com:443",
"stat_tag": "b8c116e4-37af-4eee-83d6-79d4c33201e4"
},
"description": "<p>Map to test the different generated legends.</p>\n\n<p>Points to test:</p>\n\n<ul>\n<li>Category legend</li>\n<li>Choropleth legend</li>\n<li>Bubble legend</li>\n</ul>\n\n<p>(Choropleth and bubble share the same layer)</p>\n",
"options": {
"dashboard_menu": true,
"layer_selector": false,
"legends": true,
"scrollwheel": true
},
"id": "b8c116e4-37af-4eee-83d6-79d4c33201e4",
"layers": [
{
"id": "0176d48c-09b1-4bf2-9493-546b93e4df88",
"type": "tiled",
"options": {
"default": "true",
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"name": "Voyager",
"className": "voyager_labels",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"labels": {
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png"
},
"urlTemplate": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png",
"type": "Tiled"
}
},
{
"id": "7c115d5b-6c1e-4390-890f-52d9c12f6cb2",
"legends": [
{
"conf": {
"columns": []
},
"created_at": "2017-10-24T11:52:52+00:00",
"definition": {},
"id": "61c56598-c76e-4b11-952e-7412452e6e29",
"layer_id": "7c115d5b-6c1e-4390-890f-52d9c12f6cb2",
"post_html": "",
"pre_html": "",
"title": "pop_max",
"type": "choropleth",
"updated_at": "2017-10-24T12:02:06+00:00"
},
{
"conf": {
"columns": []
},
"created_at": "2017-10-24T12:01:27+00:00",
"definition": {
"color": "#fef6b5",
"top_label": "",
"bottom_label": ""
},
"id": "6210c946-9ee5-4d8a-ba99-25a8d7c5bc65",
"layer_id": "7c115d5b-6c1e-4390-890f-52d9c12f6cb2",
"post_html": "",
"pre_html": "",
"title": "pop_max",
"type": "bubble",
"updated_at": "2017-10-24T12:02:06+00:00"
}
],
"type": "CartoDB",
"infowindow": {
"template_name": "none",
"maxHeight": 180,
"template": "",
"alternative_names": {},
"fields": null,
"width": 226,
"headerColor": {
"color": {
"fixed": "#35AAE5",
"opacity": 1
}
}
},
"tooltip": {
"template_name": "none",
"template": ""
},
"visible": true,
"options": {
"layer_name": "Layer1",
"cartocss": "#layer {\n marker-width: ramp([pop_max], range(2, 11), quantiles(5));\n marker-fill: ramp([pop_max], (#fef6b5, #ffd08e, #ffa679, #f67b77, #e15383), quantiles);\n marker-fill-opacity: 1;\n marker-allow-overlap: true;\n marker-line-width: 1;\n marker-line-color: #FFFFFF;\n marker-line-opacity: 1;\n}",
"cartocss_version": "2.1.1",
"attribution": "",
"source": "c0"
}
},
{
"id": "97bf19b9-fee0-49fd-ad44-8f4026da6888",
"legends": [
{
"conf": {
"columns": [
"title"
]
},
"created_at": "2017-10-24T11:52:00+00:00",
"definition": {},
"id": "07cc33c9-63c3-4bc6-9c9a-6b3c46ebbda1",
"layer_id": "97bf19b9-fee0-49fd-ad44-8f4026da6888",
"post_html": "",
"pre_html": "",
"title": "Category Legend",
"type": "category",
"updated_at": "2017-10-24T11:59:25+00:00"
}
],
"type": "CartoDB",
"infowindow": {
"template_name": "none",
"maxHeight": 180,
"template": "",
"alternative_names": {},
"fields": null,
"width": 226,
"headerColor": {
"color": {
"fixed": "#35AAE5",
"opacity": 1
}
}
},
"tooltip": {
"template_name": "none",
"template": ""
},
"visible": true,
"options": {
"layer_name": "layer0",
"cartocss": "#layer {\n marker-width: 7;\n marker-fill: ramp([featurecla], (#5F4690, #1D6996, #38A6A5, #0F8554, #73AF48, #EDAD08, #E17C05, #CC503E), (\"Populated place\", \"Admin-1 capital\", \"Admin-0 capital\", \"Admin-1 region capital\", \"Scientific station\", \"Admin-0 region capital\", \"Admin-0 capital alt\", \"Historic place\"), \"=\");\n marker-fill-opacity: 1;\n marker-allow-overlap: true;\n marker-line-width: 0;\n marker-line-color: #FFFFFF;\n marker-line-opacity: 1;\n}",
"cartocss_version": "2.1.1",
"attribution": "",
"source": "b0"
}
},
{
"id": "2669e10c-d1bf-4ed5-8f8e-6518a1afb234",
"type": "tiled",
"options": {
"default": "true",
"url": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png",
"subdomains": "abcd",
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"urlTemplate": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png",
"type": "Tiled",
"name": "Voyager Labels"
}
}
],
"likes": 0,
"map_provider": "leaflet",
"overlays": [
{
"type": "share",
"order": 2,
"options": {
"display": true,
"x": 20,
"y": 20
},
"template": ""
},
{
"type": "search",
"order": 3,
"options": {
"display": true,
"x": 60,
"y": 20
},
"template": ""
},
{
"type": "zoom",
"order": 6,
"options": {
"display": true,
"x": 20,
"y": 20
},
"template": "<a href=\"#zoom_in\" class=\"zoom_in\">+</a> <a href=\"#zoom_out\" class=\"zoom_out\">-</a>"
},
{
"type": "loader",
"order": 8,
"options": {
"display": true,
"x": 20,
"y": 150
},
"template": "<div class=\"loader\" original-title=\"\"></div>"
},
{
"type": "logo",
"order": 9,
"options": {
"display": true,
"x": 10,
"y": 40
},
"template": ""
}
],
"title": "002-Test",
"updated_at": "2017-10-24T12:05:16+00:00",
"user": {
"fullname": "cartojs-test",
"avatar_url": "//cartodb-libs.global.ssl.fastly.net/cartodbui/assets/unversioned/images/avatars/avatar_planet_orange.png",
"profile_url": "https://cartojs-test.carto.com"
},
"version": "3.0.0",
"widgets": [],
"zoom": 7,
"analyses": [
{
"id": "c0",
"type": "source",
"params": {
"query": "SELECT * FROM ne_10m_populated_places_simple"
},
"options": {
"table_name": "ne_10m_populated_places_simple",
"simple_geom": "point"
}
},
{
"id": "b0",
"type": "source",
"params": {
"query": "SELECT * FROM ne_10m_populated_places_simple"
},
"options": {
"table_name": "ne_10m_populated_places_simple",
"simple_geom": "point"
}
}
]
}

View File

@ -0,0 +1,53 @@
{
"id": "2b13c956-e7c1-11e2-806b-5404a6a683d5",
"version": "0.1.0",
"title": "european_countries_e 0",
"likes": 0,
"description": null,
"scrollwheel": true,
"legends": true,
"url": null,
"map_provider": "leaflet",
"center": "[52.5897007687178, 52.734375]",
"zoom": 4,
"updated_at": "2015-03-13T11:24:37+00:00",
"datasource": {
"user_name": "documentation",
"maps_api_template": "http://{user}.cartodb.com:80",
"force_cors": true,
"stat_tag": "84ec6844-4b4b-11e5-9c1d-080027880ca6"
},
"layers": [
{
"options": {
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"visible": true,
"type": "Tiled",
"name": "Positron",
"className": "default positron_rainbow",
"baseType": "positron_rainbow",
"urlTemplate": "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
"read_only": true,
"minZoom": "0",
"maxZoom": "18",
"attribution": "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
"subdomains": "abcd",
"category": "CartoDB"
},
"infowindow": null,
"tooltip": null,
"id": "0a3d9104-99c6-482b-9f8c-7c6134bddcdc",
"order": 0,
"type": "tiled"
}
],
"overlays": [
{
"type": "search",
"options": {
"display": true
}
}
]
}

View File

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Base example | CARTO</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="shortcut icon" href="http://cartodb.com/assets/favicon.ico" />
<!--Include carto styles -->
<link rel="stylesheet" href="../../dist/internal/themes/css/cartodb.css" />
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<!-- Include cartodb.js Library -->
<script src="../../dist/internal/cartodb.uncompressed.js"></script>
<!-- Custom Map styles -->
<style>
html,
body,
#map {
font-family: "Open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
height: 100%;
padding: 0;
margin: 0;
background: #162945;
position: relative;
}
</style>
<style>
#map {
height: calc(100% - 55px);
}
nav {
padding: 15px;
display: flex;
flex-direction: row;
background: white;
color: #162945;
border-bottom: 1px solid #eee;
font-size: 13px;
}
input {
background: none;
border: none;
}
button {
color: #FFF;
padding: 5px 10px;
background-color: #1785FB;
border-radius: 3px;
}
.CDB-OverlayContainer{
z-index: 999;
}
</style>
<script>
function loadVizJson(name) {
let url = 'viz/' + name;
fetch(url)
.then(data => data.json())
.then(vizjson => {
cartodb.createVis('map', vizjson)
.done(console.log)
.error(console.error);
});
}
</script>
</head>
<body>
<nav>
<input list="examples" type="text" name="url" onchange="loadVizJson(document.querySelector('input').value)">
<datalist id="examples">
<option value="000.json" />
<option value="001.json" />
<option value="002.json" />
<option value="003.json" />
</datalist>
<button onclick="loadVizJson(document.querySelector('input').value)" type="button">LOAD VIZ</button>
</nav>
<div id="map"></div>
</body>
</html>

View File

@ -0,0 +1,99 @@
<!DOCTYPE html>
<html>
<head>
<title>Category widget | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body class="bg-gray">
<div class="dataview">
<ul>
<li>
<h2 class="h2">Column</h2>
<input id="column" type="text" value="adm0name" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Limit</h2>
<input id="limit" type="number" value="10" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Operation</h2>
<select id="operation" class="select open-sans">
<option value="sum">SUM</option>
<option value="count">COUNT</option>
<option value="avg">AVG</option>
<option value="max">MAX</option>
<option value="min">MIN</option>
</select>
</li>
<li>
<h2 class="h2">Operation column</h2>
<input id="operationColumn" type="text" value="pop_max" class="input_text open-sans"></input>
</li>
</ul>
<button onclick="applyDataviewChanges()" class="button open-sans">Apply</button>
<pre class="code" id="data"></pre>
</div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Category widget</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Create a widget with the category dataview.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change form values.</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const categoryDataview = new carto.dataview.Category(source, 'adm0name', {
limit: 10,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', data => {
document.getElementById('data').innerHTML = JSON.stringify(data, null, 4);
});
categoryDataview.on('error', error => {
alert(error.message);
});
client.addDataview(categoryDataview);
function applyDataviewChanges() {
const column = document.getElementById('column').value;
const limit = document.getElementById('limit').value;
const operation = document.getElementById('operation').value;
const operationColumn = document.getElementById('operationColumn').value;
categoryDataview.setColumn(column);
categoryDataview.setLimit(parseInt(limit));
categoryDataview.setOperation(operation);
categoryDataview.setOperationColumn(operationColumn);
}
</script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<title>Widgets error handling | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body class="bg-gray">
<div class="dataview">
<ul>
<li>
<h2 class="h2">Column</h2>
<input id="column" type="text" value="pop_max" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Operation</h2>
<select id="operation" class="select">
<option value="count">COUNT</option>
<option value="sum">SUM</option>
<option value="avg">AVG</option>
<option value="max">MAX</option>
<option value="min">MIN</option>
</select>
</li>
</ul>
<button onclick="applyDataviewChanges()" class="button open-sans text-blue"><b>Apply</b></button>
<button onclick="provokeError()" class="button button-error open-sans text-red"><b>Provoke error</b></button>
<pre class="code" id="data"></pre>
</div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Status and error handling</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Manage the status and erros in dataviews.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Apply submits the form. Provoke error sends a wrong column.</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset(`
ne_10m_populated_places_simple
`);
const formulaDataview = new carto.dataview.Formula(source, 'pop_max', {
operation: carto.operation.COUNT
});
let data;
formulaDataview.on('dataChanged', newData => {
data = JSON.stringify(newData, null, 4);
setText(data);
});
formulaDataview.on('error', error => {
setText(error.message);
});
formulaDataview.on('statusChanged', status => {
if (status === carto.dataview.status.LOADING) {
setText('Loading...');
} else if (status === carto.dataview.status.LOADED && data) {
setText(data);
}
});
client.addDataview(formulaDataview);
function applyDataviewChanges() {
const column = document.getElementById('column').value;
const operation = document.getElementById('operation').value;
formulaDataview.setColumn(column);
formulaDataview.setOperation(operation);
}
function provokeError () {
formulaDataview.setColumn('wrongcolumn');
}
function setText (text) {
document.getElementById('data').innerHTML = text;
}
</script>
</body>
</html>

View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<title>Formula widget | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body class="bg-gray">
<div class="dataview">
<ul>
<li>
<h2 class="h2">Column</h2>
<input id="column" type="text" value="pop_max" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Operation</h2>
<select id="operation" class="select open-sans">
<option value="count">COUNT</option>
<option value="sum">SUM</option>
<option value="avg">AVG</option>
<option value="max">MAX</option>
<option value="min">MIN</option>
</select>
</li>
</ul>
<button onclick="applyDataviewChanges()" class="button open-sans">Apply</button>
<pre class="code" id="data"></pre>
</div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Formula widget</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Create a widget with the formula dataview.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change column or operation on the form.</p>
<p class="open-sans">Example columns: rank_max, pop_max, pop_min.</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const formulaDataview = new carto.dataview.Formula(source, 'pop_max', {
operation: carto.operation.COUNT
});
formulaDataview.on('dataChanged', data => {
document.getElementById('data').innerHTML = JSON.stringify(data, null, 4);
});
formulaDataview.on('error', error => {
alert(error.message);
});
client.addDataview(formulaDataview);
function applyDataviewChanges() {
const column = document.getElementById('column').value;
const operation = document.getElementById('operation').value;
formulaDataview.setColumn(column);
formulaDataview.setOperation(operation);
}
</script>
</body>
</html>

View File

@ -0,0 +1,99 @@
<!DOCTYPE html>
<html>
<head>
<title>Histogram widget | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body class="bg-gray">
<div class="dataview">
<ul>
<li>
<h2 class="h2">Column</h2>
<input id="column" type="text" value="price" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Bins</h2>
<input id="bins" type="number" value="5" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Start</h2>
<input id="start" type="number" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">End</h2>
<input id="end" type="number" class="input_text open-sans"></input>
</li>
</ul>
<button onclick="applyDataviewChanges()" class="button open-sans">Apply</button>
<pre class="code" id="data"></pre>
</div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Histogram widget</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Create a widget with the histogram dataview.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change column or bins on the form.</p>
<p class="open-sans">Start and end values must be used together.</p>
<p class="open-sans">Example columns: price, minimum_nights, availability_365.</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.SQL('SELECT * FROM airbnb_listings WHERE price < 150');
const histogramDataview = new carto.dataview.Histogram(source, 'price', {
bins: 5
});
histogramDataview.on('dataChanged', data => {
document.getElementById('data').innerHTML = JSON.stringify(data, null, 4);
});
histogramDataview.on('error', error => {
alert(error.message);
});
client.addDataview(histogramDataview);
function applyDataviewChanges() {
const column = document.getElementById('column').value;
const bins = parseInt(document.getElementById('bins').value);
const startValue = parseFloat(document.getElementById('start').value);
const endValue = parseFloat(document.getElementById('end').value);
const start = Number.isFinite(startValue) ? startValue : null;
const end = Number.isFinite(endValue) ? endValue : null;
try {
histogramDataview.setColumn(column);
histogramDataview.setStartEnd(start, end);
histogramDataview.setBins(bins);
} catch(error) {
alert(error.message);
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<title>Time Series widget | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body class="bg-gray">
<div class="dataview">
<ul>
<li>
<h2 class="h2">Column</h2>
<input id="column" type="text" value="date" class="input_text open-sans"></input>
</li>
<li>
<h2 class="h2">Aggregation</h2>
<select id="aggregation" class="select">
<option value="auto">Auto</option>
<option value="millennium">Millennium</option>
<option value="century">Century</option>
<option value="decade">Decade</option>
<option value="year">Year</option>
<option value="quarter">Quarter</option>
<option value="month">Month</option>
<option value="week">Week</option>
<option value="day">Day</option>
<option value="hour">Hour</option>
<option value="minute">Minute</option>
</select>
</li>
<li>
<h2 class="h2">Offset</h2>
<input id="offset" type="number" value="1" class="input_text open-sans"></input>
</li>
</ul>
<button class="button open-sans" onclick="applyDataviewChanges()">Apply</button>
<pre class="code" id="data"></pre>
</div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Time Series widget</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Create a widget with the time series dataview.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Select different aggregations on the form.</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('railroad_data');
const timeseriesDataview = new carto.dataview.TimeSeries(source, 'date', {
aggregation: carto.dataview.timeAggregation.AUTO,
offset: 1
});
timeseriesDataview.on('dataChanged', data => {
document.getElementById('data').innerHTML = JSON.stringify(data, null, 4);
});
timeseriesDataview.on('error', error => {
alert(error.message);
});
client.addDataview(timeseriesDataview);
function applyDataviewChanges() {
const column = document.getElementById('column').value;
const aggregation = document.getElementById('aggregation').value;
const offset = document.getElementById('offset').value;
timeseriesDataview.setColumn(column);
timeseriesDataview.setAggregation(aggregation);
timeseriesDataview.setOffset(parseInt(offset));
}
</script>
</body>
</html>

View File

@ -0,0 +1,153 @@
<!DOCTYPE html>
<html>
<head>
<title>AND Filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>AND Filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Apply an AND filter to exclude listings that are not within the selected room types and have a higher price than the one we set.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change the selected price range and the selected room types to filter the listings.</p>
</section>
<div id="controls">
<div id="info">
<h3>Room Types</h3>
</div>
<ul>
<li>
<input type="checkbox" name="roomTypes[]" id="entire" value="Entire home/apt" checked>
<label for="entire">Entire home/apt</label>
</li>
<li>
<input type="checkbox" name="roomTypes[]" id="private" value="Private room" checked>
<label for="private">Private Room</label>
</li>
<li>
<input type="checkbox" name="roomTypes[]" id="shared" value="Shared room" checked>
<label for="shared">Shared Room</label>
</li>
</ul>
<div id="info">
<h3>Price</h3>
</div>
<div class="widget">
<p class="open-sans">Showing listings below and equal to <span class="js-price-placeholder">40€</span></p>
</div>
<input type="range" name="price" class="slider" min="1" max="60" value="40" step="1" min-with-suffix="1€" max-with-suffix="60€">
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([40.42252398976147, -3.659729361534119], 12);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const inputRange = document.querySelector('#controls input[type=range]');
inputRange.style.setProperty('--value', (inputRange.value - inputRange.min) / 0.59);
const pricePlaceholder = document.querySelector('#controls .js-price-placeholder');
const roomTypesCheckboxes = document.querySelectorAll('#controls input[type=checkbox]');
function getSelectedRoomTypes () {
const values = [];
roomTypesCheckboxes.forEach(input => input.checked ? values.push(input.value): null);
return values;
}
function applyPriceFilters (e) {
const maximumPrice = parseInt(e.target.value);
pricePlaceholder.innerText = maximumPrice + "€";
priceFilter.setFilters({ lte: maximumPrice });
// or
// priceFilter.set('lte', maximumPrice);
}
function applyRoomFilters () {
roomTypeFilter.setFilters({ in: getSelectedRoomTypes() });
// or
// roomTypeFilter.set('in', getSelectedRoomTypes());
}
function registerListeners () {
inputRange.addEventListener('input', e => {
inputRange.style.setProperty('--value', (inputRange.value - inputRange.min) / 0.59);
});
inputRange.addEventListener('change', e => {
applyPriceFilters(e)
});
roomTypesCheckboxes.forEach(
input => input.addEventListener('click', () => applyRoomFilters())
);
}
const roomTypeFilter = new carto.filter.Category('room_type', { in: getSelectedRoomTypes() });
const priceFilter = new carto.filter.Range('price', { lte: 40 });
const source = new carto.source.SQL('SELECT * FROM airbnb_listings');
// You can apply both filters in two different ways
// 1. Adding both filters to the source
source.addFilters([ priceFilter, roomTypeFilter ]);
// 2. Creating an AND filter to join the two filters and adding it to the source
// const roomAndPriceFilter = new carto.filter.AND([ priceFilter, roomTypeFilter ]);
// source.addFilter(roomAndPriceFilter)
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
marker-fill: ramp([price], (#ffc6c4, #ee919b, #cc607d, #9e3963, #672044), quantiles);
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
registerListeners();
</script>
</body>
</html>

View File

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<title>Bounding Box filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Bounding Box filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Apply a map bounding box filter to dataviews.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Move the map</p>
</section>
<div class="widget category"></div>
<div class="widget formula"></div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
zoomControl: true,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureOverColumns: ['name', 'pop_max']
});
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
const categoryDataview = new carto.dataview.Category(source, 'adm0name', {
limit: 4,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', renderWidgetCategory);
client.addDataview(categoryDataview);
const formulaDataview = new carto.dataview.Formula(source, 'pop_max', {
operation: carto.operation.COUNT,
});
formulaDataview.on('dataChanged', renderWidgetFormula);
client.addDataview(formulaDataview);
const bboxFilter = new carto.filter.BoundingBoxGoogleMaps(map);
categoryDataview.addFilter(bboxFilter);
formulaDataview.addFilter(bboxFilter);
function renderWidgetCategory(data) {
const categories = data.categories.map(category => `
<li>
<h3>${category.name}</h3>
<p class="open-sans">${parseInt(category.value)} <small>inhabitants</small></p>
</li>
`).join('');
const content = `<ul>${categories}</ul>`;
document.querySelector('.widget.category').innerHTML = content;
}
function renderWidgetFormula(data) {
const content = `<h2 class="h2">${data.result} <small>cities</small></h2>`;
document.querySelector('.widget.formula').innerHTML = content;
}
</script>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<title>Bounding Box filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Bounding Box filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Apply a map bounding box filter to dataviews.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Move the map</p>
</section>
<div class="widget category"></div>
<div class="widget formula"></div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureOverColumns: ['name', 'pop_max']
});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
const categoryDataview = new carto.dataview.Category(source, 'adm0name', {
limit: 4,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', renderWidgetCategory);
client.addDataview(categoryDataview);
const formulaDataview = new carto.dataview.Formula(source, 'pop_max', {
operation: carto.operation.COUNT,
});
formulaDataview.on('dataChanged', renderWidgetFormula);
client.addDataview(formulaDataview);
const bboxFilter = new carto.filter.BoundingBoxLeaflet(map);
categoryDataview.addFilter(bboxFilter);
formulaDataview.addFilter(bboxFilter);
function renderWidgetCategory(data) {
const categories = data.categories.map(category => `
<li>
<h3>${category.name}</h3>
<p class="open-sans">${parseInt(category.value)} <small>inhabitants</small></p>
</li>
`).join('');
const content = `<ul>${categories}</ul>`;
document.querySelector('.widget.category').innerHTML = content;
}
function renderWidgetFormula(data) {
const content = `<h2 class="h2">${data.result} <small>cities</small></h2>`;
document.querySelector('.widget.formula').innerHTML = content;
}
</script>
</body>
</html>

View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html>
<head>
<title>Category Filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Category Filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Apply a category filter to the listings shown in the visualization.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change the selected room types to filter the listings.</p>
</section>
<div id="controls">
<div id="info">
<h3>Room Types</h3>
</div>
<ul>
<li>
<input type="checkbox" name="roomTypes[]" id="entire" value="Entire home/apt" checked>
<label for="entire">Entire home/apt</label>
</li>
<li>
<input type="checkbox" name="roomTypes[]" id="private" value="Private room" checked>
<label for="private">Private Room</label>
</li>
<li>
<input type="checkbox" name="roomTypes[]" id="shared" value="Shared room" checked>
<label for="shared">Shared Room</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
function getSelectedRoomTypes () {
const inputControls = document.querySelectorAll('#controls input');
const values = [];
inputControls.forEach(input => input.checked ? values.push(input.value): null);
return values;
}
function applyFilters () {
roomTypeFilter.setFilters({ in: getSelectedRoomTypes() });
// or
// roomTypeFilter.set('in', getSelectedRoomTypes());
}
function registerListeners () {
document.querySelectorAll('#controls input').forEach(
input => input.addEventListener('click', () => applyFilters())
);
}
const map = L.map('map').setView([40.42252398976147, -3.659729361534119], 12);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const roomTypeFilter = new carto.filter.Category('room_type', { in: getSelectedRoomTypes() });
const source = new carto.source.SQL('SELECT * FROM airbnb_listings');
source.addFilter(roomTypeFilter);
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
marker-fill: ramp([room_type], (#88CCEE, #CC6677, #DDCC77), ("Entire home/apt", "Private room", "Shared room"), "=");
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
registerListeners();
</script>
</body>
</html>

View File

@ -0,0 +1,334 @@
<!DOCTYPE html>
<html>
<head>
<title> Filter data on map with Circle | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" rel="stylesheet">
<!-- Include Leaflet Draw plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.13/leaflet.draw.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.13/leaflet.draw.css" />
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
<!-- Include Chart.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<style>
.dataview {
margin-bottom: 0px;
color: gray;
padding-bottom: 3px;
border-bottom: 1px #ddd solid;
}
#railroadWidget {
max-width: 90%;
}
</style>
</head>
<body>
<!-- map element -->
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box" style="max-height:90vh; overflow: auto;">
<header>
<h1>Circle Filter</h1>
<p class="open-sans"><em>Draw a circle to get filtered results</em></p>
</header>
<br />
<div>
<p class="open-sans dataview">Formula dataview</p>
<div class="widget formula">
<!-- To be updated with Formula & Circle filter -->
</div>
<p class="open-sans dataview">Category dataview</p>
<div class="widget category">
<!-- To be updated with Category & Circle filter -->
</div>
<p class="open-sans dataview">Histogram dataview</p>
<div class="widget histogram">
<!-- To be updated with Histogram & Circle filter -->
</div>
</div>
<div>
<p class="open-sans dataview">TimeSeries dataview</p>
<div>
<!-- To be updated with TimeSeries & Circle filter -->
<canvas id="railroadWidget"></canvas>
</div>
</div>
</div>
</aside>
<script>
// basic objects
let map;
let client;
let citiesSource;
let railRoadSource;
let categoryDataview;
let formulaDataview;
let histogramDataview;
let timeSeriesDataview;
let railroadWidget;
let circleFilter;
let drawnItems;
// create basic map and client configuration
function createBasicMap() {
map = L.map('map').setView([40, -80], 7);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// set CARTO client
client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
}
// create a cities layer & source
function prepareCitiesLayer() {
citiesSource = new carto.source.SQL(`
SELECT * FROM ne_10m_populated_places_simple
`);
const style = new carto.style.CartoCSS(`
#layer {
marker-fill: red;
}
`);
const layer = new carto.layer.Layer(citiesSource, style);
client.addLayer(layer);
}
// functions to display filtered dataview results on the panel
// 1. cities --> category
function renderWidgetCategory(data) {
const categories = data.categories.map(category => `
<li>
<h3>${category.name}</h3>
<p class="open-sans">${parseInt(category.value)} <small>inhabitants</small></p>
</li>
`).join('');
const content = `<ul>${categories}</ul>`;
document.querySelector('.widget.category').innerHTML = content;
}
// 2. cities --> formula
function renderWidgetFormula(data) {
const content = `<h2 class="h2">${data.result} <small>cities</small></h2>`;
document.querySelector('.widget.formula').innerHTML = content;
}
// 3. cities --> histogram
function renderWidgetHistogram(data) {
let histogram = '<ul class="open-sans">';
data.bins.forEach(bin => {
const line = '<li>' + bin.start + ' to ' + bin.end + ' interval has ' + bin.freq +
' cities</li>';
if (bin.freq > 0) {
histogram += line;
}
});
histogram += "</ul>";
document.querySelector('.widget.histogram').innerHTML = histogram;
}
// 4. raiload --> timeseries
function initializeWidgetTimeSeries() {
const widgetElement = document.getElementById("railroadWidget");
railroadWidget = new Chart(widgetElement.getContext('2d'), {
type: 'bar',
data: {
datasets: [{
label: 'Railroad accidents',
data: [],
borderWidth: 1,
backgroundColor: 'rgba(0, 255, 0, 0.5)'
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
display: false
}
}]
}
}
});
widgetElement.style.display = 'none';
}
function renderWidgetTimeSeries(data) {
const widget = document.getElementById("railroadWidget");
if (data.totalAmount === 0){
widget.style.display = 'none';
}else{
widget.style.display = 'block';
}
railroadWidget.data.labels = data.bins.map(function (x) {
let dt = new Date(x.start);
return dt.getFullYear() + "/" + (dt.getMonth() + 1) + "/" + dt.getDate();
});
railroadWidget.data.datasets.forEach((dataset) => {
dataset.data = data.bins.map(x => x.freq);
});
railroadWidget.update();
};
// create 3 dataviews on cities (Category, Formula & Histogram).
function createDataviewsOnCities() {
// Category dataview
categoryDataview = new carto.dataview.Category(citiesSource, 'adm1name', {
limit: 4,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', renderWidgetCategory);
client.addDataview(categoryDataview);
// Formula dataview
formulaDataview = new carto.dataview.Formula(citiesSource, 'pop_max', {
operation: carto.operation.COUNT,
});
formulaDataview.on('dataChanged', renderWidgetFormula);
client.addDataview(formulaDataview);
// Histogram dataview
histogramDataview = new carto.dataview.Histogram(citiesSource, 'pop_max', {
bins: 10
});
histogramDataview.on('dataChanged', renderWidgetHistogram);
client.addDataview(histogramDataview);
}
// create a railroad data layer & source
function prepareRailroadLayer() {
railRoadSource = new carto.source.Dataset('railroad_data');
const railroadLayer = new carto.layer.Layer(railRoadSource,
new carto.style.CartoCSS(`
#layer {
marker-width: 5;
marker-fill: #00FF00;
marker-line-color: gray;
marker-line-width: 0.3;
}
`)
);
client.addLayer(railroadLayer);
}
// create 1 dataview on railroad data (TimeSeries)
function createDataviewOnRailroad() {
timeSeriesDataview = new carto.dataview.TimeSeries(railRoadSource, 'date', {
aggregation: carto.dataview.timeAggregation.AUTO,
offset: 1
});
timeSeriesDataview.on('dataChanged', renderWidgetTimeSeries);
client.addDataview(timeSeriesDataview);
}
// create the circle filter and add it to the dataviews
function createAndBindCircleFilter() {
circleFilter = new carto.filter.Circle();
circleFilter.setCircle({
lat: 0,
lng: 0,
radius: 0
});
categoryDataview.addFilter(circleFilter);
formulaDataview.addFilter(circleFilter);
histogramDataview.addFilter(circleFilter);
timeSeriesDataview.addFilter(circleFilter);
}
function prepareCircleDrawing() {
// layer to draw circles
drawnItems = L.featureGroup().addTo(map);
// Control to draw a Circle and use it as the spatial filter
let drawControl = new L.Control.Draw({
draw: {
polygon: false,
polyline: false,
line: false,
marker: false,
rectangle: false,
circle: {
shapeOptions: {
color: 'red',
weight: 0.1,
opacity: 0.5
}
},
circlemarker: false,
},
edit: false
});
map.addControl(drawControl);
// Get radius and center & apply to Circle filter
map.on(L.Draw.Event.CREATED, function (e, d) {
let drawnCircle = e.layer;
drawnItems.clearLayers();
drawnItems.addLayer(drawnCircle);
// get circle data
let radius = drawnCircle.getRadius();
let centerLat = drawnCircle.getLatLng().lat;
let centerLng = drawnCircle.getLatLng().lng;
const circleData = {
lat: centerLat,
lng: centerLng,
radius: radius
};
console.log(circleData);
circleFilter.setCircle(circleData); // updated filter !
});
}
// Run the example
createBasicMap();
prepareCitiesLayer();
prepareRailroadLayer();
client.getLeafletLayer().addTo(map);
createDataviewsOnCities();
createDataviewOnRailroad();
initializeWidgetTimeSeries();
createAndBindCircleFilter();
prepareCircleDrawing();
</script>
</body>
</html>

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<title>Complex Filter Example | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Complex Example</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">This map has applied a filters combination that show listings meeting these conditions:</p>
<ul>
<li class="open-sans">Between 30€ and 40€.</li>
<li class="open-sans">Centro neighbourhood.</li>
<li class="open-sans">Entire home/apartment listings OR listings that have been reviewed after May 2015.</li>
</ul>
<p class="description open-sans">If you want to know more, please go to <a href="https://cartojs-test.carto.com/tables/airbnb_listings/public">Airbnb Listings dataset</a>.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Go to the source code below, and see how filters are applied.</p>
</section>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([40.4175117794419, -3.6971674673259263], 15);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('airbnb_listings');
// or
// const source = new carto.source.SQL('SELECT * FROM airbnb_listings');
const entireHomeFilter = new carto.filter.Category('room_type', { eq: 'Entire home/apt' });
const neighbourhoodFilter = new carto.filter.Category('neighbourhood_group', { in: ['Centro'] });
const reviewsInLastYearFilter = new carto.filter.Range('last_review', { gte: new Date('2015-05-01T00:00:00.000Z') });
const priceFilter = new carto.filter.Range('price', { between: { min: 30, max: 40 } });
const filtersCombination = new carto.filter.AND([
neighbourhoodFilter,
priceFilter,
new carto.filter.OR([ entireHomeFilter, reviewsInLastYearFilter ])
]);
source.addFilter(filtersCombination);
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html>
<head>
<title>Custom Bounding Box filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw-src.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw-src.css" />
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Custom Bounding Box filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Apply a custom bounding box filter to dataviews.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click on the <em>Draw a rectangle</em> button and draw a rectangle</p>
</section>
<div class="widget category"></div>
<div class="widget formula"></div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 20;
marker-fill: #FF583E;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureOverColumns: ['name', 'pop_max']
});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
const categoryDataview = new carto.dataview.Category(source, 'adm0name', {
limit: 4,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', renderWidgetCategory);
client.addDataview(categoryDataview);
const formulaDataview = new carto.dataview.Formula(source, 'pop_max', {
operation: carto.operation.COUNT,
});
formulaDataview.on('dataChanged', renderWidgetFormula);
client.addDataview(formulaDataview);
const bboxFilter = new carto.filter.BoundingBox(map);
categoryDataview.addFilter(bboxFilter);
formulaDataview.addFilter(bboxFilter);
// Setup drawing rectangles to configure custom bounding boxes
let rectangle = null;
const drawnItems = L.featureGroup().addTo(map);
map.addControl(new L.Control.Draw({
draw: {
polyline: false,
polygon: false,
marker: false,
circle: false,
circlemarker: false
}
}));
const el = document.getElementsByClassName('leaflet-draw-draw-rectangle');
el[0].addEventListener('click', () => {
drawnItems.removeLayer(rectangle);
bboxFilter.resetBounds();
});
map.on(L.Draw.Event.CREATED, event => {
rectangle = event.layer;
drawnItems.addLayer(rectangle);
const latLngs = rectangle.getLatLngs();
const bounds = {
west: latLngs[0][1].lng,
south: latLngs[0][3].lat,
east: latLngs[0][3].lng,
north: latLngs[0][1].lat
}
bboxFilter.setBounds(bounds);
});
function renderWidgetCategory(data) {
const categories = data.categories.map(category => `
<li>
<h3>${category.name}</h3>
<p class="open-sans">${parseInt(category.value)} <small>inhabitants</small></p>
</li>
`).join('');
const content = `<ul>${categories}</ul>`;
document.querySelector('.widget.category').innerHTML = content;
}
function renderWidgetFormula(data) {
const content = `<h2 class="h2">${data.result} <small>cities</small></h2>`;
document.querySelector('.widget.formula').innerHTML = content;
}
</script>
</body>
</html>

View File

@ -0,0 +1,332 @@
<!DOCTYPE html>
<html>
<head>
<title> Filter data on map with Polygon | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" rel="stylesheet">
<!-- Include Leaflet Draw plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.13/leaflet.draw.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.13/leaflet.draw.css" />
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
<!-- Include Chart.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<style>
.dataview {
margin-bottom: 0px;
color: gray;
padding-bottom: 3px;
border-bottom: 1px #ddd solid;
}
#railroadWidget {
max-width: 90%;
}
</style>
</head>
<body>
<!-- map element -->
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box" style="max-height:90vh; overflow: auto;">
<header>
<h1>Polygon Filter</h1>
<p class="open-sans"><em>Draw a polygon to get filtered results</em></p>
</header>
<br />
<div>
<p class="open-sans dataview">Formula dataview</p>
<div class="widget formula">
<!-- To be updated with Formula & Circle filter -->
</div>
<p class="open-sans dataview">Category dataview</p>
<div class="widget category">
<!-- To be updated with Category & Circle filter -->
</div>
<p class="open-sans dataview">Histogram dataview</p>
<div class="widget histogram">
<!-- To be updated with Histogram & Circle filter -->
</div>
</div>
<div>
<p class="open-sans dataview">TimeSeries dataview</p>
<div>
<!-- To be updated with TimeSeries & Circle filter -->
<canvas id="railroadWidget"></canvas>
</div>
</div>
</div>
</aside>
<script>
// basic objects
let map;
let client;
let citiesSource;
let railRoadSource;
let categoryDataview;
let formulaDataview;
let histogramDataview;
let timeSeriesDataview;
let railroadWidget;
let polygonFilter;
let drawnItems;
// create basic map and client configuration
function createBasicMap() {
map = L.map('map').setView([40, -80], 7);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// set CARTO client
client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
}
// create a cities layer & source
function prepareCitiesLayer() {
citiesSource = new carto.source.SQL(`
SELECT * FROM ne_10m_populated_places_simple
`);
const style = new carto.style.CartoCSS(`
#layer {
marker-fill: red;
}
`);
const layer = new carto.layer.Layer(citiesSource, style);
client.addLayer(layer);
}
// functions to display filtered dataview results on the panel
// 1. cities --> category
function renderWidgetCategory(data) {
const categories = data.categories.map(category => `
<li>
<h3>${category.name}</h3>
<p class="open-sans">${parseInt(category.value)} <small>inhabitants</small></p>
</li>
`).join('');
const content = `<ul>${categories}</ul>`;
document.querySelector('.widget.category').innerHTML = content;
}
// 2. cities --> formula
function renderWidgetFormula(data) {
const content = `<h2 class="h2">${data.result} <small>cities</small></h2>`;
document.querySelector('.widget.formula').innerHTML = content;
}
// 3. cities --> histogram
function renderWidgetHistogram(data) {
let histogram = '<ul class="open-sans">';
data.bins.forEach(bin => {
const line = '<li>' + bin.start + ' to ' + bin.end + ' interval has ' + bin.freq +
' cities</li>';
if (bin.freq > 0) {
histogram += line;
}
});
histogram += "</ul>";
document.querySelector('.widget.histogram').innerHTML = histogram;
}
// 4. raiload --> timeseries
function initializeWidgetTimeSeries() {
const widgetElement = document.getElementById("railroadWidget");
railroadWidget = new Chart(widgetElement.getContext('2d'), {
type: 'bar',
data: {
datasets: [{
label: 'Railroad accidents',
data: [],
borderWidth: 1,
backgroundColor: 'rgba(0, 255, 0, 0.5)'
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
display: false
}
}]
}
}
});
widgetElement.style.display = 'none';
}
function renderWidgetTimeSeries(data) {
const widget = document.getElementById("railroadWidget");
if (data.totalAmount === 0){
widget.style.display = 'none';
}else{
widget.style.display = 'block';
}
railroadWidget.data.labels = data.bins.map(function (x) {
let dt = new Date(x.start);
return dt.getFullYear() + "/" + (dt.getMonth() + 1) + "/" + dt.getDate();
});
railroadWidget.data.datasets.forEach((dataset) => {
dataset.data = data.bins.map(x => x.freq);
});
railroadWidget.update();
};
// create 3 dataviews on cities (Category, Formula & Histogram).
function createDataviewsOnCities() {
// Category dataview
categoryDataview = new carto.dataview.Category(citiesSource, 'adm1name', {
limit: 4,
operation: carto.operation.SUM,
operationColumn: 'pop_max'
});
categoryDataview.on('dataChanged', renderWidgetCategory);
client.addDataview(categoryDataview);
// Formula dataview
formulaDataview = new carto.dataview.Formula(citiesSource, 'pop_max', {
operation: carto.operation.COUNT,
});
formulaDataview.on('dataChanged', renderWidgetFormula);
client.addDataview(formulaDataview);
// Example to deal with dataview errors
formulaDataview.on('error', cartoError => {
console.error(cartoError.message);
})
// Histogram dataview
histogramDataview = new carto.dataview.Histogram(citiesSource, 'pop_max', {
bins: 10
});
histogramDataview.on('dataChanged', renderWidgetHistogram);
client.addDataview(histogramDataview);
}
// create a railroad data layer & source
function prepareRailroadLayer() {
railRoadSource = new carto.source.Dataset('railroad_data');
const railroadLayer = new carto.layer.Layer(railRoadSource,
new carto.style.CartoCSS(`
#layer {
marker-width: 5;
marker-fill: #00FF00;
marker-line-color: gray;
marker-line-width: 0.3;
}
`)
);
client.addLayer(railroadLayer);
}
// create 1 dataview on railroad data (TimeSeries)
function createDataviewOnRailroad() {
timeSeriesDataview = new carto.dataview.TimeSeries(railRoadSource, 'date', {
aggregation: carto.dataview.timeAggregation.AUTO,
offset: 1
});
timeSeriesDataview.on('dataChanged', renderWidgetTimeSeries);
client.addDataview(timeSeriesDataview);
}
// create the polygon filter and add it to the dataviews
function createAndBindPolygonFilter() {
polygonFilter = new carto.filter.Polygon();
polygonFilter.setPolygon({
type: 'Polygon',
coordinates: []
});
categoryDataview.addFilter(polygonFilter);
formulaDataview.addFilter(polygonFilter);
histogramDataview.addFilter(polygonFilter);
timeSeriesDataview.addFilter(polygonFilter);
}
function preparePolygonDrawing() {
// layer to draw polygons
drawnItems = L.featureGroup().addTo(map);
// Control to draw a Polygon and use it as the spatial filter
let drawControl = new L.Control.Draw({
draw: {
polygon: {
allowIntersection: false,
showArea: true,
shapeOptions: {
color: '#bada55'
}
},
polyline: false,
line: false,
marker: false,
rectangle: false,
circle: false,
circlemarker: false,
},
edit: false
});
map.addControl(drawControl);
// Get radius and center & apply to Polygon filter
map.on(L.Draw.Event.CREATED, function (e, d) {
let drawnPolygon = e.layer;
drawnItems.clearLayers();
drawnItems.addLayer(drawnPolygon);
// get polygon data
let polygonData = drawnPolygon.toGeoJSON()['geometry'];
console.log(polygonData);
polygonFilter.setPolygon(polygonData); // updated filter !
});
}
// Run the example
createBasicMap();
prepareCitiesLayer();
prepareRailroadLayer();
client.getLeafletLayer().addTo(map);
createDataviewsOnCities();
createDataviewOnRailroad();
initializeWidgetTimeSeries();
createAndBindPolygonFilter();
preparePolygonDrawing();
</script>
</body>
</html>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<title>Range Filter | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Range Filter</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Change the price filter to filter the listings shown in the visualization by price.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Change the selected price range to filter the listings.</p>
</section>
<div id="controls">
<div id="info">
<h3>Price</h3>
</div>
<div class="widget">
<p class="open-sans">Showing listings below and equal to <span class="js-price-placeholder">40€</span></p>
</div>
<input type="range" name="price" class="slider" min="1" max="60" value="40" step="1" min-with-suffix="1€" max-with-suffix="60€">
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const inputRange = document.querySelector('#controls input[type=range]');
inputRange.style.setProperty('--value', (inputRange.value - inputRange.min) / 0.59);
const pricePlaceholder = document.querySelector('#controls .js-price-placeholder');
function applyFilters (e) {
const maximumPrice = parseInt(e.target.value);
priceFilter.setFilters({ lte: maximumPrice });
pricePlaceholder.innerText = maximumPrice + "€";
}
function registerListeners () {
inputRange.addEventListener('input', e => {
inputRange.style.setProperty('--value', (inputRange.value - inputRange.min) / 0.59);
});
inputRange.addEventListener('change', e => {
applyFilters(e)
});
}
const map = L.map('map').setView([40.42252398976147, -3.659729361534119], 12);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const priceFilter = new carto.filter.Range('price', { lte: 40 });
const source = new carto.source.SQL('SELECT * FROM airbnb_listings');
source.addFilter(priceFilter);
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
marker-fill: ramp([price], (#ffc6c4, #ee919b, #cc607d, #9e3963, #672044), quantiles);
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
registerListeners();
</script>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<title>Change feature columns | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the feature columns</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Change the columns returned in the feature event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click on the markers</p>
</section>
<div id="controls">
<ul class="actions">
<li>
<input id="red" type="radio" name="style" onclick="setMoreData()">
<label for="red">More data</label>
</li>
<li>
<input id="green" type="radio" name="style" onclick="setLessData()" checked>
<label for="green">Less data</label>
</li>
</ul>
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureClickColumns: ['name']
});
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
layer.on('featureClicked', featureEvent => {
let content = '';
if (featureEvent.data.name) {
content += `<h3>${featureEvent.data.name.toUpperCase()}</h3>`;
}
if (featureEvent.data.pop_max) {
content += `<p class="open-sans">${featureEvent.data.pop_max} <span>max inhabitants</span></p>`;
}
if (featureEvent.data.pop_min) {
content += `<p class="open-sans">${featureEvent.data.pop_min} <span>min inhabitants</span></p>`;
}
document.getElementById('info').innerHTML = content;
});
function setMoreData() {
layer.setFeatureClickColumns(['name', 'pop_max', 'pop_min']);
document.getElementById('info').innerHTML = '';
}
function setLessData() {
layer.setFeatureClickColumns(['name']);
document.getElementById('info').innerHTML = '';
}
</script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<title>Change feature columns | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the feature columns</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Change the columns returned in the feature event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click on the markers</p>
</section>
<div id="controls">
<ul class="actions">
<li>
<input id="red" type="radio" name="style" onclick="setMoreData()">
<label for="red">More data</label>
</li>
<li>
<input id="green" type="radio" name="style" onclick="setLessData()" checked>
<label for="green">Less data</label>
</li>
</ul>
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureClickColumns: ['name']
});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
layer.on('featureClicked', featureEvent => {
let content = '';
if (featureEvent.data.name) {
content += `<h3>${featureEvent.data.name.toUpperCase()}</h3>`;
}
if (featureEvent.data.pop_max) {
content += `<p class="open-sans"><span>${featureEvent.data.pop_max}</span> max inhabitants</p>`;
}
if (featureEvent.data.pop_min) {
content += `<p class="open-sans"><span>${featureEvent.data.pop_min}</span> min inhabitants</p>`;
}
document.getElementById('info').innerHTML = content;
});
function setMoreData() {
layer.setFeatureClickColumns(['name', 'pop_max', 'pop_min']);
document.getElementById('info').innerHTML = '';
}
function setLessData() {
layer.setFeatureClickColumns(['name']);
document.getElementById('info').innerHTML = '';
}
</script>
</body>
</html>

View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html>
<head>
<title>Change order | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Move the layers</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the order of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click to move countries layer to&nbsp;front/back</p>
</section>
<div id="controls">
<ul>
<li onclick="bringToBack()">
<input type="radio" name="style" id="bringToBack">
<label for="bringToBack">Bring to back</label>
</li>
<li onclick="bringToFront()">
<input type="radio" name="style" checked id="bringToFront">
<label for="bringToFront">Bring to front</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const spainCitiesSource = new carto.source.Dataset('ne_10m_populated_places_simple');
const spainCitiesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const spainCitiesLayer = new carto.layer.Layer(spainCitiesSource, spainCitiesStyle);
const europeCountriesSource = new carto.source.Dataset('ne_adm0_europe');
const europeCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #826DBA;
polygon-opacity: 0.8;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.8;
}
}
`);
const europeCountriesLayer = new carto.layer.Layer(europeCountriesSource, europeCountriesStyle);
client.addLayers([europeCountriesLayer, spainCitiesLayer]);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
function bringToBack() {
spainCitiesLayer.bringToBack();
// or
// spainCitiesLayer.setOrder(0);
// or
// client.moveLayer(spainCitiesLayer, 0);
}
function bringToFront() {
spainCitiesLayer.bringToFront();
// or
// spainCitiesLayer.setOrder(1);
// or
// client.moveLayer(spainCitiesLayer, 1);
}
</script>
</body>
</html>

View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<title>Change order | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Move the layers</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the order of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click to move countries layer to&nbsp;front/back</p>
</section>
<div id="controls">
<ul>
<li onclick="bringToBack()">
<input type="radio" name="style" id="bringToBack">
<label for="bringToBack">Bring to back</label>
</li>
<li onclick="bringToFront()">
<input type="radio" name="style" checked id="bringToFront">
<label for="bringToFront">Bring to front</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const spainCitiesSource = new carto.source.Dataset('ne_10m_populated_places_simple');
const spainCitiesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const spainCitiesLayer = new carto.layer.Layer(spainCitiesSource, spainCitiesStyle);
const europeCountriesSource = new carto.source.Dataset('ne_adm0_europe');
const europeCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #826DBA;
polygon-opacity: 0.8;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.8;
}
}
`);
const europeCountriesLayer = new carto.layer.Layer(europeCountriesSource, europeCountriesStyle);
client.addLayers([europeCountriesLayer, spainCitiesLayer]);
client.getLeafletLayer().addTo(map);
function bringToBack() {
spainCitiesLayer.bringToBack();
// or
// spainCitiesLayer.setOrder(0);
// or
// client.moveLayer(spainCitiesLayer, 0);
}
function bringToFront() {
spainCitiesLayer.bringToFront();
// or
// spainCitiesLayer.setOrder(1);
// or
// client.moveLayer(spainCitiesLayer, 1);
}
</script>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<title>Change source | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the source</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the source of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Select different sources</p>
</section>
<div id="controls">
<ul>
<li onclick="setAllCities()">
<input type="radio" name="source" checked id="all">
<label for="all">All cities</label>
</li>
<li onclick="setEuropeanCities()">
<input type="radio" name="source" id="europe">
<label for="europe">European cities</label>
</li>
<li onclick="setSpanishCities()">
<input type="radio" name="source" id="spain">
<label for="spain">Spanish cities</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
function setAllCities() {
source.setQuery(`
SELECT *
FROM ne_10m_populated_places_simple
`);
}
function setEuropeanCities() {
source.setQuery(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`);
}
function setSpanishCities() {
source.setQuery(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name = \'Spain\'
`);
}
</script>
</body>
</html>

View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html>
<head>
<title>Change source | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the source</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the source of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Select different sources</p>
</section>
<div id="controls">
<ul>
<li onclick="setAllCities()">
<input type="radio" name="source" checked id="all">
<label for="all">All cities</label>
</li>
<li onclick="setEuropeanCities()">
<input type="radio" name="source" id="europe">
<label for="europe">European cities</label>
</li>
<li onclick="setSpanishCities()">
<input type="radio" name="source" id="spain">
<label for="spain">Spanish cities</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
function setAllCities() {
source.setQuery('SELECT * FROM ne_10m_populated_places_simple');
}
function setEuropeanCities() {
source.setQuery(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
`);
}
function setSpanishCities() {
source.setQuery(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name = \'Spain\'
`);
}
</script>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<title>Change style | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the style</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the style of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Select different styles</p>
</section>
<div id="controls">
<ul>
<li onclick="setRed()">
<input type="radio" name="style" checked id="red">
<label for="red">Size 7px - Red</label>
</li>
<li onclick="setGreen()">
<input type="radio" name="style" id="green">
<label for="green">Size 9px - Green</label>
</li>
<li onclick="setBlue()">
<input type="radio" name="style" id="blue">
<label for="blue">Size 11px - Blue</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
function setRed() {
style.setContent(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
}
function setGreen() {
style.setContent(`
#layer {
marker-width: 7;
marker-fill: #9BC63B;
marker-line-color: #FFFFFF;
}
`);
}
function setBlue() {
style.setContent(`
#layer {
marker-width: 9;
marker-fill: #1785FB;
marker-line-color: #FFFFFF;
}
`);
}
</script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<title>Change style | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Change the style</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Update the style of your layers.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Select different styles</p>
</section>
<div id="controls">
<ul>
<li onclick="setRed()">
<input type="radio" name="style" checked id="red">
<label for="red">Size 7px - Red</label>
</li>
<li onclick="setGreen()">
<input type="radio" name="style" id="green">
<label for="green">Size 9px - Green</label>
</li>
<li onclick="setBlue()">
<input type="radio" name="style" id="blue">
<label for="blue">Size 11px - Blue</label>
</li>
</ul>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
function setRed() {
style.setContent(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
}
function setGreen() {
style.setContent(`
#layer {
marker-width: 9;
marker-fill: #9BC63B;
marker-line-color: #FFFFFF;
}
`);
}
function setBlue() {
style.setContent(`
#layer {
marker-width: 11;
marker-fill: #1785FB;
marker-line-color: #FFFFFF;
}
`);
}
</script>
</body>
</html>

View File

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<title>Feature click | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Detect feature click</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Interact with the features on the click event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click on the markers</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureClickColumns: ['name', 'pop_max']
});
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
layer.on('featureClicked', featureEvent => {
const content = `
<h3>${featureEvent.data.name.toUpperCase()}</h3>
<p class="open-sans">${featureEvent.data.pop_max} <small>max inhabitants</small></p>
`;
document.getElementById('info').innerHTML = content;
});
</script>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>Feature click | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Detect feature click</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Interact with the features on the click event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Click on the markers</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureClickColumns: ['name', 'pop_max']
});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
layer.on('featureClicked', featureEvent => {
const content = `
<h3>${featureEvent.data.name.toUpperCase()}</h3>
<p class="open-sans">${featureEvent.data.pop_max} <small>max inhabitants</small></p>
`;
document.getElementById('info').innerHTML = content;
});
</script>
</body>
</html>

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<title>Feature over/out | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Detect feature over/out</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Interact with the features on the over/out event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Move the mouse over the markers</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 10;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureOverColumns: ['name', 'pop_max']
});
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
layer.on('featureOver', featureEvent => {
const content = `
<h3>${featureEvent.data.name.toUpperCase()}</h3>
<p class="open-sans">${featureEvent.data.pop_max} <small>max inhabitants</small></p>
`;
document.getElementById('info').innerHTML = content;
featureVisible = true;
});
layer.on('featureOut', featureEvent => {
hideInfo();
});
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
const hideInfo = debounce(function () {
document.getElementById('info').innerHTML = '';
}, 500);
</script>
</body>
</html>

View File

@ -0,0 +1,102 @@
<!DOCTYPE html>
<html>
<head>
<title>Feature over/out | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Detect feature over/out</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Interact with the features on the over/out event.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">Move the mouse over the markers</p>
</section>
<div id="controls">
<div id="info"></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 10;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {
featureOverColumns: ['name', 'pop_max']
});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
layer.on('featureOver', featureEvent => {
const content = `
<h3>${featureEvent.data.name.toUpperCase()}</h3>
<p class="open-sans">${featureEvent.data.pop_max} <small>max inhabitants</small></p>
`;
document.getElementById('info').innerHTML = content;
featureVisible = true;
});
layer.on('featureOut', featureEvent => {
hideInfo();
});
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
const hideInfo = debounce(function () {
document.getElementById('info').innerHTML = '';
}, 500);
</script>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with aggregation cluster | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Server tile aggregation cluster</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">This map has smart backend aggregation cluster applied. See source code for details.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 38.479395, lng: -102.480469 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
// Define source using value 1 as count to count the number
// of points within the aggregation that will be created
const source = new carto.source.SQL(`
SELECT *, 1 as count
FROM stormevents_locations_2014
`);
// Aggregation option summing al values of field count
const aggregation = new carto.layer.Aggregation({
threshold: 1,
resolution: 32,
placement: carto.layer.Aggregation.placement.SAMPLE,
columns: {
total_agg: {
aggregateFunction: carto.layer.Aggregation.operation.SUM,
aggregatedColumn: "count"
}
}
});
const style = new carto.style.CartoCSS(`
#layer {
marker-fill: red;
marker-width: ramp([total_agg], 6,25 , quantiles);
}
#layer::labels {
text-name: [total_agg];
text-face-name: 'DejaVu Sans Book';
text-size: 10;
text-fill: #FFFFFF;
text-label-position-tolerance: 0;
text-halo-radius: 1;
text-halo-fill: #6F808D;
text-allow-overlap: true;
text-placement: point;
text-placement-type: dummy;
}
`);
const layer = new carto.layer.Layer(source, style, { aggregation });
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
</script>
</body>
</html>

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with aggregation cluster | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Server tile aggregation cluster</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">This map has smart backend aggregation cluster applied. See source code for details.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([38.479395, -102.480469], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
// Define source using value 1 as count to count the number
// of points within the aggregation that will be created
const source = new carto.source.SQL(`
SELECT *, 1 as count
FROM stormevents_locations_2014
`);
// Aggregation option summing al values of field count
const aggregation = new carto.layer.Aggregation({
threshold: 1,
resolution: 32,
placement: carto.layer.Aggregation.placement.SAMPLE,
columns: {
total_agg: {
aggregateFunction: carto.layer.Aggregation.operation.SUM,
aggregatedColumn: "count"
}
}
});
const style = new carto.style.CartoCSS(`
#layer {
marker-fill: red;
marker-width: ramp([total_agg], 6,25 , quantiles);
}
#layer::labels {
text-name: [total_agg];
text-face-name: 'DejaVu Sans Book';
text-size: 10;
text-fill: #FFFFFF;
text-label-position-tolerance: 0;
text-halo-radius: 1;
text-halo-fill: #6F808D;
text-allow-overlap: true;
text-placement: point;
text-placement-type: dummy;
}
`);
const layer = new carto.layer.Layer(source, style, { aggregation });
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with aggregation | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Server tile aggregation</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">This map has smart backend aggregation applied. See source code for details.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: ramp([population], (#ecda9a, #f7945d, #ee4d5a), jenks());
marker-line-color: #FFFFFF;
}
`);
// Aggregation option
const aggregation = new carto.layer.Aggregation({
threshold: 1,
resolution: 4,
placement: carto.layer.Aggregation.placement.SAMPLE,
columns: {
population: {
aggregateFunction: carto.layer.Aggregation.operation.SUM,
aggregatedColumn: 'pop_max'
}
}
});
const layer = new carto.layer.Layer(source, style, { aggregation });
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
</script>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with aggregation | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Server tile aggregation</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">This map has smart backend aggregation applied. See source code for details.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: ramp([population], (#ecda9a, #f7945d, #ee4d5a), jenks());
marker-line-color: #FFFFFF;
}
`);
// Aggregation option
const aggregation = new carto.layer.Aggregation({
threshold: 1,
resolution: 4,
placement: carto.layer.Aggregation.placement.SAMPLE,
columns: {
population: {
aggregateFunction: carto.layer.Aggregation.operation.SUM,
aggregatedColumn: 'pop_max'
}
}
});
const layer = new carto.layer.Layer(source, style, { aggregation });
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with zoom options | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, { minzoom: 3, maxzoom: 3 });
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
</script>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Layer with zoom options | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<script>
const map = L.map('map').setView([30, 0], 3);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style, {minzoom: 3, maxzoom: 3});
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<title>Multilayer | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Add more layers</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Add multiple CARTO layers to your map.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 40, lng: 0 },
zoom: 5,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const spainCitiesSource = new carto.source.SQL(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name = \'Spain\'
`);
const spainCitiesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const spainCitiesLayer = new carto.layer.Layer(spainCitiesSource, spainCitiesStyle);
const europeCountriesSource = new carto.source.Dataset('ne_adm0_europe');
const europeCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #826DBA;
polygon-opacity: 0.8;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.8;
}
}
`);
const europeCountriesLayer = new carto.layer.Layer(europeCountriesSource, europeCountriesStyle);
client.addLayers([europeCountriesLayer, spainCitiesLayer]);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
</script>
</body>
</html>

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<title>Multilayer | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Add more layers</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Add multiple CARTO layers to your map.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([40, 0], 5);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const spainCitiesSource = new carto.source.SQL(`
SELECT *
FROM ne_10m_populated_places_simple
WHERE adm0name = \'Spain\'
`);
const spainCitiesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const spainCitiesLayer = new carto.layer.Layer(spainCitiesSource, spainCitiesStyle);
const europeCountriesSource = new carto.source.Dataset('ne_adm0_europe');
const europeCountriesStyle = new carto.style.CartoCSS(`
#layer {
polygon-fill: #826DBA;
polygon-opacity: 0.8;
::outline {
line-width: 1;
line-color: #FFFFFF;
line-opacity: 0.8;
}
}
`);
const europeCountriesLayer = new carto.layer.Layer(europeCountriesSource, europeCountriesStyle);
client.addLayers([europeCountriesLayer, spainCitiesLayer]);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>Single layer | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Add a layer</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Add one CARTO layer to your map.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
</script>
</body>
</html>

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<title>Single layer | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map">
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Add a layer</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Add one CARTO layer to your map.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.Dataset('ne_10m_populated_places_simple');
const style = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-line-color: #FFFFFF;
}
`);
const layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
</script>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>App | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
</head>
<body>
<!-- TODO: add your code here -->
</body>
</html>

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>App | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
</head>
<body>
<!-- TODO: add your code here -->
</body>
</html>

View File

@ -0,0 +1,178 @@
<!DOCTYPE html>
<html>
<head>
<title>Custom search dataset | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
<style>
#selectDrop {
background-color: #d2eaef;
opacity: 0.8;
position: absolute;
top: 50px;
left: 50px;
width: auto;
height: auto;
padding: 10px;
display: block;
z-index: 9000;
}
#selectDrop input {
width: 200px;
}
div#results {
background: #FFF;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="searchbox">
<select id="selectDrop">
<option selected value="">Please Select</option>
</select>
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Look for data within your dataset</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Look for data within your dataset using dropdown menu.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
let input;
// set map with initial zoom and coodinates view
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 40, lng: 2 },
zoom: 4,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
// populate dropdown menu
populateDrowpDown()
// set CARTO client
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.SQL(`
SELECT * FROM ne_adm0_europe
`);
// define CartoCSS code to style data on map
const style = new carto.style.CartoCSS(`
#ne_adm0_europe {
polygon-fill: #3E7BB6;
polygon-opacity: 0.7;
line-color: #FFF;
line-width: 0.5;
line-opacity: 1;
}
#layer::labels {
text-name: [admin];
text-face-name: 'DejaVu Sans Book';
text-size: 10;
text-fill: #FFFFFF;
text-label-position-tolerance: 0;
text-halo-radius: 1;
text-halo-fill: #6F808D;
text-dy: -10;
text-allow-overlap: true;
text-placement: point;
text-placement-type: dummy;
}
`);
// create CARTO layer from source and style variables
const Cartolayer = new carto.layer.Layer(source, style);
// add CARTO layer to the client
client.addLayer(Cartolayer);
// get tile from client and add them to the map object
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
// function to get list of country names to populate dropdown menu
function populateDrowpDown(){
return fetch(
`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=SELECT the_geom, admin FROM ne_adm0_europe ORDER BY admin ASC`
).then((resp) => resp.json())
.then((response) => {
return response['features'].map(function(feature){
option = document.createElement("option")
option.setAttribute("value", feature.properties.admin)
option.textContent = feature.properties.admin
document.getElementById("selectDrop").appendChild(option);
});
}).catch((error) => {
console.log(error)
})
}
// when select option from downdown menu, change bounding box of map
// to geometry of the selected country
document.getElementById('selectDrop').addEventListener("change", function (e) {
input = e.currentTarget.selectedOptions[0].attributes[0].value;
// calculate the xmax, ymax, xmin, ymin coordinates of the bounding box
// of the country polygon of the CARTO dataset
return fetch(
`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=
WITH bbox as (
SELECT ST_Envelope(the_geom) as the_geom
FROM ne_adm0_europe
WHERE admin Ilike '${input}'
)
SELECT the_geom, ST_Xmax(the_geom) as xmax,
ST_Ymax(the_geom) as ymax,
ST_Xmin(the_geom) as xmin,
ST_Ymin(the_geom) as ymin
FROM bbox
`)
.then((resp) => resp.json())
.then((response) => {
// get coordinates
coordinates = response['features'][0].properties
// set LatLng objects from coordinates from CARTO
let sw = new google.maps.LatLng(coordinates.ymin, coordinates.xmin);
let ne = new google.maps.LatLng(coordinates.ymax, coordinates.xmax);
// instantiate Google bounds
bounds = new google.maps.LatLngBounds(sw, ne)
// set bounds of map to the geometry from CARTO
map.fitBounds(bounds);
})
});
</script>
</body>
</html>

View File

@ -0,0 +1,147 @@
<!DOCTYPE html>
<html>
<head>
<title>Custom search dataset | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
<style>
#selectDrop {
background-color: #d2eaef;
opacity: 0.8;
position: absolute;
top: 10px;
left: 50px;
width: auto;
height: auto;
padding: 10px;
display: block;
z-index: 9000;
}
#selectDrop input {
width: 200px;
}
div#results {
background: #FFF;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="searchbox">
<select id="selectDrop">
<option selected value="">Please Select</option>
</select>
</div>
<!-- Description -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Look for data within your dataset</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Look for data within your dataset using dropdown menu.</p>
</section>
<footer class="js-footer"></footer>
</div>
</aside>
<script>
// set map with initial zoom and coodinates view
const map = L.map('map').setView([40, 2], 4);
let input;
// disable scroll wheel zoom
map.scrollWheelZoom.disable();
// populate dropdown menu
populateDrowpDown()
// add basemaps to map
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
// set CARTO client
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const source = new carto.source.SQL(`
SELECT * FROM ne_adm0_europe
`);
// define CartoCSS code to style data on map
const style = new carto.style.CartoCSS(`
#ne_adm0_europe {
polygon-fill: #3E7BB6;
polygon-opacity: 0.7;
line-color: #FFF;
line-width: 0.5;
line-opacity: 1;
}
#layer::labels {
text-name: [admin];
text-face-name: 'DejaVu Sans Book';
text-size: 10;
text-fill: #FFFFFF;
text-label-position-tolerance: 0;
text-halo-radius: 1;
text-halo-fill: #6F808D;
text-dy: -10;
text-allow-overlap: true;
text-placement: point;
text-placement-type: dummy;
}
`);
// create CARTO layer from source and style variables
const Cartolayer = new carto.layer.Layer(source, style);
// add CARTO layer to the client
client.addLayer(Cartolayer);
// get tile from client and add them to the map object
client.getLeafletLayer().addTo(map);
// function to get list of country names to populate dropdown menu
function populateDrowpDown(){
return fetch(
`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=SELECT the_geom, admin FROM ne_adm0_europe ORDER BY admin ASC`
).then((resp) => resp.json())
.then((response) => {
return response['features'].map(function(feature){
option = document.createElement("option")
option.setAttribute("value", feature.properties.admin)
option.textContent = feature.properties.admin
document.getElementById("selectDrop").appendChild(option);
});
}).catch((error) => {
console.log(error)
})
}
// when select option from downdown menu, change bounding box of map
// to geometry of the selected country
document.getElementById('selectDrop').addEventListener("change", function (e) {
input = e.currentTarget.selectedOptions[0].attributes[0].value;
return fetch(`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=SELECT * FROM ne_adm0_europe where admin Ilike '${input}'`)
.then((resp) => resp.json())
.then((response) => {
geojsonLayer = L.geoJson(response)
map.fitBounds(geojsonLayer.getBounds());
})
});
</script>
</body>
</html>

View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html>
<head>
<title>Edit SQL & CartoCSS | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Edit SQL & CartoCSS</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Edit manually the SQL query and the CartoCSS style.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">This example only uses one style and one layer whose content is changed.</p>
<p class="open-sans">Since the style and source objects are the same they won't trigger events. You need to use the promise to handle
errors.</p>
</section>
</section>
<footer class="js-footer"></footer>
</div>
<div class="box widget">
<h2 class="h2">SQL</h2>
<textarea id="sql" rows="3">SELECT * FROM ne_10m_populated_places_simple</textarea>
<button class="button" onclick="updateSource()">UPDATE SQL</button>
</div>
<div class="box widget">
<h2 class="h2">CartoCSS</h2>
<textarea id="cartocss" rows="3">
#layer {
marker-fill: red;
}
</textarea>
<button class="button-update button" onclick="updateStyle()">UPDATE STYLE</button>
</div>
</aside>
<script>
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 30, lng: 0 },
zoom: 3,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const populatedPlacesSource = new carto.source.SQL(getValue('#sql'));
const populatedPlacesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-fill-opacity: 0.9;
marker-line-width: 0.5;
marker-line-color: #FFFFFF;
}
`);
const populatedPlacesLayer = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle);
client.addLayer(populatedPlacesLayer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
function updateSource() {
reset('#sql');
populatedPlacesSource.setQuery(getValue('#sql'))
.catch(cartoError => {
error('#sql', cartoError);
});
}
function updateStyle() {
reset('#cartocss')
populatedPlacesStyle.setContent(getValue('#cartocss'))
.catch(cartoError => {
error('#cartocss', cartoError);
});
}
function getValue(id) {
return document.querySelector(id).value
}
function reset(id) {
document.querySelector(id).style.background = 'white';
}
function error(id, cartoError) {
document.querySelector(id).style.border = '1px solid #E57373';
alert(cartoError.message);
}
</script>
</body>
</html>

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<title>Edit SQL CARTOCSS | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Edit SQL & CartoCSS</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Edit manually the SQL query and the CartoCSS style.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">This example only uses one style and one layer whose content is changed.</p>
<p class="open-sans">Since the style and source objects are the same they won't trigger events. You need to use the promise to handle errors.</p>
</section>
</section>
<footer class="js-footer"></footer>
</div>
<div class="box widget">
<h2 class="h2">SQL</h2>
<textarea id="sql" rows="3">SELECT * FROM ne_10m_populated_places_simple</textarea>
<button class="button" onclick="updateSource()">UPDATE SQL</button>
</div>
<div class="box widget">
<h2 class="h2">CartoCSS</h2>
<textarea id="cartocss" rows="3">
#layer {
marker-fill: red;
}
</textarea>
<button class="button-update button" onclick="updateStyle()">UPDATE STYLE</button>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
const populatedPlacesSource = new carto.source.SQL(getValue('#sql'));
const populatedPlacesStyle = new carto.style.CartoCSS(`
#layer {
marker-width: 7;
marker-fill: #EE4D5A;
marker-fill-opacity: 0.9;
marker-line-width: 0.5;
marker-line-color: #FFFFFF;
}
`);
const populatedPlacesLayer = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle);
client.addLayer(populatedPlacesLayer);
client.getLeafletLayer().addTo(map);
function updateSource() {
reset('#sql');
populatedPlacesSource.setQuery(getValue('#sql'))
.catch(cartoError => {
error('#sql', cartoError);
});
}
function updateStyle() {
reset('#cartocss')
populatedPlacesStyle.setContent(getValue('#cartocss'))
.catch(cartoError => {
error('#cartocss', cartoError);
});
}
function getValue(id) {
return document.querySelector(id).value
}
function reset(id) {
document.querySelector(id).style.border = 'default';
}
function error(id, cartoError) {
document.querySelector(id).style.border = '1px solid #E57373';
alert(cartoError.message);
}
</script>
</body>
</html>

View File

@ -0,0 +1,201 @@
<!DOCTYPE html>
<html>
<head>
<title>Error handling | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<!-- Include Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDpVNTQI60ossApFzZ3dwSMZ1LcxOTY-rI&v=3.35"></script>
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Error handling</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Handle common errors in maps.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">In this example we handle the client error while calling the `addLayer` funciton.</p>
<p class="open-sans">See `refreshLayer` function in the source code for an example on how to handle Promise errors.</p>
</section>
<div id="controls">
<div id="info">
<p class="mt-16 open-sans"></p>
</div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
<div class="box widget">
<h2 class="h2">DATASET</h2>
<textarea id="dataset-value" rows=2></textarea>
<button id="dataset-button" class="button" onclick="updateDataset()">SET WRONG DATASET</button>
</div>
<div class="box widget">
<h2 class="h2">STYLE</h2>
<textarea id="style-value" rows="3"></textarea>
<button id="style-button" class="button" onclick="updateStyle()">UPDATE STYLE</button>
</div>
</aside>
<script>
// Setting up a Google Maps Map
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 50, lng: 15 },
zoom: 4,
fullscreenControl: false,
gestureHandling: 'cooperative'
});
// Hide the map labels and geometry strokes
map.set('styles', [{
elementType: 'labels',
stylers: [{ visibility: 'off' }]
}, {
elementType: 'geometry.stroke',
stylers: [{ visibility: 'off' }]
}]);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
// State
const state = {
isDatasetValid: true,
isStyleValid: true,
errorMessage: '',
updating: false
};
// Datasets
const validDataset = 'ne_10m_populated_places_simple';
const wrongDataset = 'wrong_dataset';
// Style
const validStyle = '#layer { marker-fill: red; }';
const wrongStyle = '#layer { marker-fill: wrong-color; }';
let source = new carto.source.Dataset(validDataset);
let style = new carto.style.CartoCSS(validStyle);
let layer = new carto.layer.Layer(source, style);
// Adding the layers to the map
client.addLayer(layer);
map.overlayMapTypes.push(client.getGoogleMapsMapType(map));
updateUI();
function refreshLayer(layer) {
client.addLayer(layer)
.then(function () {
state.errorMessage = '';
state.updating = false;
updateUI();
})
.catch(function (error) {
state.errorMessage = error.message;
state.updating = false;
updateUI();
});
}
function updateDataset() {
client.removeLayer(layer);
state.isDatasetValid = !state.isDatasetValid;
state.updating = true;
const dataset = state.isDatasetValid
? validDataset
: wrongDataset;
updateUI();
source = new carto.source.Dataset(dataset);
layer = new carto.layer.Layer(source, style);
refreshLayer(layer);
}
function updateStyle() {
client.removeLayer(layer);
state.isStyleValid = !state.isStyleValid;
state.updating = true;
const styleContent = state.isStyleValid
? validStyle
: wrongStyle;
updateUI();
style = new carto.style.CartoCSS(styleContent);
layer = new carto.layer.Layer(source, style);
refreshLayer(layer);
}
function updateUI() {
const datasetValueEl = document.getElementById('dataset-value');
const styleValueEl = document.getElementById('style-value');
const datasetButtonEl = document.getElementById('dataset-button');
const styleButtonEl = document.getElementById('style-button');
const panelEl = document.querySelector('#info p');
datasetValueEl.value = state.isDatasetValid
? validDataset
: wrongDataset;
styleValueEl.value = state.isStyleValid
? validStyle
: wrongStyle;
datasetButtonEl.textContent = state.isDatasetValid
? 'Set wrong dataset'
: 'Revert to a valid dataset';
styleButtonEl.textContent = state.isStyleValid
? 'Set wrong style'
: 'Revert to a valid style';
panelEl.textContent = state.updating
? 'Updating...'
: state.errorMessage
? state.errorMessage
: 'Everything OK';
if (state.updating) {
panelEl.classList.remove('bg-red');
panelEl.classList.remove('bg-white');
panelEl.classList.add('bg-orange');
panelEl.classList.add('p-8');
panelEl.classList.add('text-white');
} else if (state.errorMessage) {
panelEl.classList.add('bg-red');
panelEl.classList.remove('bg-white');
panelEl.classList.remove('bg-orange');
panelEl.classList.add('p-8');
panelEl.classList.add('text-white');
} else {
panelEl.classList.add('bg-white');
panelEl.classList.remove('bg-red');
panelEl.classList.remove('bg-orange');
panelEl.classList.remove('p-8');
panelEl.classList.remove('text-white');
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,190 @@
<!DOCTYPE html>
<html>
<head>
<title>Error handling | CARTO</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<!-- Include Leaflet -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
<!-- Include CARTO.js -->
<script src="../../../dist/public/carto.js"></script>
<link href="../style.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
<aside class="toolbox">
<div class="box">
<header>
<h1>Error handling</h1>
<button class="github-logo js-source-link"></button>
</header>
<section>
<p class="description open-sans">Handle common errors in maps.</p>
<div class="separator"></div>
<section class="usage">
<header>USAGE</header>
<p class="open-sans">In this example we handle the client error while calling the `addLayer` funciton.</p>
<p class="open-sans">See `refreshLayer` function in the source code for an example on how to handle Promise errors.</p>
</section>
<div id="controls">
<div id="info"><p class="mt-16 open-sans"></p></div>
</div>
</section>
<footer class="js-footer"></footer>
</div>
<div class="box widget">
<h2 class="h2">DATASET</h2>
<textarea id="dataset-value" rows=2></textarea>
<button id="dataset-button" class="button" onclick="updateDataset()">SET WRONG DATASET</button>
</div>
<div class="box widget">
<h2 class="h2">STYLE</h2>
<textarea id="style-value" rows="3"></textarea>
<button id="style-button" class="button" onclick="updateStyle()">UPDATE STYLE</button>
</div>
</aside>
<script>
const map = L.map('map').setView([30, 0], 3);
map.scrollWheelZoom.disable();
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
const client = new carto.Client({
apiKey: 'default_public',
username: 'cartojs-test'
});
// State
const state = {
isDatasetValid: true,
isStyleValid: true,
errorMessage: '',
updating: false
};
// Datasets
const validDataset = 'ne_10m_populated_places_simple';
const wrongDataset = 'wrong_dataset';
// Style
const validStyle = '#layer { marker-fill: red; }';
const wrongStyle = '#layer { marker-fill: wrong-color; }';
let source = new carto.source.Dataset(validDataset);
let style = new carto.style.CartoCSS(validStyle);
let layer = new carto.layer.Layer(source, style);
client.addLayer(layer);
client.getLeafletLayer().addTo(map);
updateUI();
function refreshLayer (layer) {
client.addLayer(layer)
.then(function () {
state.errorMessage = '';
state.updating = false;
updateUI();
})
.catch(function (error) {
state.errorMessage = error.message;
state.updating = false;
updateUI();
});
}
function updateDataset() {
client.removeLayer(layer);
state.isDatasetValid = !state.isDatasetValid;
state.updating = true;
const dataset = state.isDatasetValid
? validDataset
: wrongDataset;
updateUI();
source = new carto.source.Dataset(dataset);
layer = new carto.layer.Layer(source, style);
refreshLayer(layer);
}
function updateStyle() {
client.removeLayer(layer);
state.isStyleValid = !state.isStyleValid;
state.updating = true;
const styleContent = state.isStyleValid
? validStyle
: wrongStyle;
updateUI();
style = new carto.style.CartoCSS(styleContent);
layer = new carto.layer.Layer(source, style);
refreshLayer(layer);
}
function updateUI () {
const datasetValueEl = document.getElementById('dataset-value');
const styleValueEl = document.getElementById('style-value');
const datasetButtonEl = document.getElementById('dataset-button');
const styleButtonEl = document.getElementById('style-button');
const panelEl = document.querySelector('#info p');
datasetValueEl.value = state.isDatasetValid
? validDataset
: wrongDataset;
styleValueEl.value = state.isStyleValid
? validStyle
: wrongStyle;
datasetButtonEl.textContent = state.isDatasetValid
? 'Set wrong dataset'
: 'Revert to a valid dataset';
styleButtonEl.textContent = state.isStyleValid
? 'Set wrong style'
: 'Revert to a valid style';
panelEl.textContent = state.updating
? 'Updating...'
: state.errorMessage
? state.errorMessage
: 'Everything OK';
if (state.updating) {
panelEl.classList.remove('bg-red');
panelEl.classList.remove('bg-white');
panelEl.classList.add('bg-orange');
panelEl.classList.add('p-8');
panelEl.classList.add('text-white');
} else if (state.errorMessage) {
panelEl.classList.add('bg-red');
panelEl.classList.remove('bg-white');
panelEl.classList.remove('bg-orange');
panelEl.classList.add('p-8');
panelEl.classList.add('text-white');
} else {
panelEl.classList.add('bg-white');
panelEl.classList.remove('bg-red');
panelEl.classList.remove('bg-orange');
panelEl.classList.remove('p-8');
panelEl.classList.remove('text-white');
}
}
</script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More