diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f271d50302..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true - }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier/@typescript-eslint', - 'plugin:prettier/recommended' - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 12, - sourceType: 'module' - }, - plugins: ['@typescript-eslint', 'lit'], - rules: { - 'lit/attribute-value-entities': 'warn', - 'lit/binding-positions': 'warn', - 'lit/no-duplicate-template-bindings': 'warn', - 'lit/no-invalid-escape-sequences': 'warn', - 'lit/no-invalid-html': 'warn', - 'lit/no-legacy-template-syntax': 'warn', - 'lit/no-private-properties': 'warn', - 'lit/no-property-change-update': 'warn', - 'lit/no-template-bind': 'warn', - 'lit/no-value-attribute': 'warn', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/no-empty-function': 'off' - } -}; diff --git a/.github/styles/Vaadin/Abbr.yml b/.github/styles/Vaadin/Abbr.yml deleted file mode 100644 index 474d07fae8..0000000000 --- a/.github/styles/Vaadin/Abbr.yml +++ /dev/null @@ -1,42 +0,0 @@ -extends: conditional -message: "'%s' has no definition." -level: warning -scope: text -ignorecase: false -# Ensures that the existence of 'first' implies the existence of 'second'. -first: '\b([A-Z]{3,5})\b' -second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' -# ... with the exception of these: -exceptions: - - API - - CLI - - CPU - - CSS - - CSV - - DOM - - FAQ - - GET - - GUI - - HTML - - HTTP - - HTTPS - - IDE - - JAR - - JPA - - JSON - - JWT - - LDAP - - NPM - - PATH - - PDF - - POST - - SQL - - SSH - - SSL - - SVG - - TCP - - REST - - URI - - URL - - UTF - - XML diff --git a/.github/styles/Vaadin/AdmonitionTitle.yml b/.github/styles/Vaadin/AdmonitionTitle.yml deleted file mode 100644 index 6a4106659c..0000000000 --- a/.github/styles/Vaadin/AdmonitionTitle.yml +++ /dev/null @@ -1,8 +0,0 @@ -# NOTE: The annotation appears two lines above the offending admonition (Vale limitation) -extends: existence -message: 'Admonitions should have a title.' -level: warning -scope: raw -nonword: true -tokens: - - '\n\n\[?(?:NOTE|TIP|CAUTION|WARNING|IMPORTANT)[:\]]\s' diff --git a/.github/styles/Vaadin/Admonitions.yml b/.github/styles/Vaadin/Admonitions.yml deleted file mode 100644 index 1f3911a411..0000000000 --- a/.github/styles/Vaadin/Admonitions.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: occurrence -message: 'Avoid using more than 3 admonitions per article.' -level: warning -scope: raw -ignorecase: false -max: 3 -token: '\[(?:NOTE|TIP|WARNING|CAUTION|IMPORTANT)\]\n|(?:NOTE: |TIP: |WARNING: |CAUTION: |IMPORTANT: )' diff --git a/.github/styles/Vaadin/CrossReference.yml b/.github/styles/Vaadin/CrossReference.yml deleted file mode 100644 index 1dc8a12231..0000000000 --- a/.github/styles/Vaadin/CrossReference.yml +++ /dev/null @@ -1,10 +0,0 @@ -extends: existence -message: 'Use cross references when linking within documentation.' -link: https://asciidoctor.org/docs/user-manual/#xref -nonword: true -level: error -scope: raw -ignorecase: true -# For some reason, 'http' in accept.txt cancels out this check if we use 'http' in full -tokens: - - ttps?:\/\/vaadin\.com\/docs.*?(?:\s|\[) diff --git a/.github/styles/Vaadin/HeadingFormatting.yml b/.github/styles/Vaadin/HeadingFormatting.yml deleted file mode 100644 index 8b2d41e47e..0000000000 --- a/.github/styles/Vaadin/HeadingFormatting.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: existence -message: "Don't use rich formatting in headings (bold, italic, monospace)." -nonword: true -level: error -scope: raw -tokens: - - ^={1,6} .*?\*{1,2}(.*?)\*{1,2} - - ^={1,6} .*?_(.*?)_.* - - ^={1,6} .*?\x60(.*?)\x60.* diff --git a/.github/styles/Vaadin/Headings.yml b/.github/styles/Vaadin/Headings.yml deleted file mode 100644 index d3aeef0e43..0000000000 --- a/.github/styles/Vaadin/Headings.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: capitalization -message: "'%s' should be in title case." -level: error -scope: heading -# $title, $sentence, $lower, $upper, or a pattern. -match: $title -style: AP # AP or Chicago; only applies when match is set to $title. diff --git a/.github/styles/Vaadin/OneSentencePerLine.yml b/.github/styles/Vaadin/OneSentencePerLine.yml deleted file mode 100644 index 160aac3be4..0000000000 --- a/.github/styles/Vaadin/OneSentencePerLine.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: 'Write one sentence per line.' -nonword: true -level: warning -tokens: - - '[^\d\n\r][.!?].*[^\n\r]' - - '(\d\.)+ +[^\n\r]+' diff --git a/.github/styles/Vaadin/Passive.yml b/.github/styles/Vaadin/Passive.yml deleted file mode 100644 index 46b4064c6e..0000000000 --- a/.github/styles/Vaadin/Passive.yml +++ /dev/null @@ -1,185 +0,0 @@ -extends: existence -message: "'%s' may be passive voice. Use active voice if you can." -ignorecase: true -level: warning -raw: - - \b(am|are|were|being|is|been|was|be)\b\s* -tokens: -# Disabled because it's OK to say: -# "is defined in the constructor" -# - '[\w]+ed' - - awoken - - beat - - become - - been - - begun - - bent - - beset - - bet - - bid - - bidden - - bitten - - bled - - blown - - born - - bought - - bound - - bred - - broadcast - - broken - - brought - - built - - burnt - - burst - - cast - - caught - - chosen - - clung - - come - - cost - - crept - - cut - - dealt - - dived - - done - - drawn - - dreamt - - driven - - drunk - - dug - - eaten - - fallen - - fed - - felt - - fit - - fled - - flown - - flung - - forbidden - - foregone - - forgiven - - forgotten - - forsaken - - fought - - found - - frozen - - given - - gone - - gotten - - ground - - grown - - heard - - held - - hidden - - hit - - hung - - hurt - - kept - - knelt - - knit - - known - - laid - - lain - - leapt - - learnt - - led - - left - - lent - - let - - lighted - - lost - - made - - meant - - met - - misspelt - - mistaken - - mown - - overcome - - overdone - - overtaken - - overthrown - - paid - - pled - - proven - - put - - quit - - read - - rid - - ridden - - risen - - run - - rung - - said - - sat - - sawn - - seen - - sent - - set - - sewn - - shaken - - shaven - - shed - - shod - - shone - - shorn - - shot - - shown - - shrunk - - shut - - slain - - slept - - slid - - slit - - slung - - smitten - - sold - - sought - - sown - - sped - - spent - - spilt - - spit - - split - - spoken - - spread - - sprung - - spun - - stolen - - stood - - stridden - - striven - - struck - - strung - - stuck - - stung - - stunk - - sung - - sunk - - swept - - swollen - - sworn - - swum - - swung - - taken - - taught - - thought - - thrived - - thrown - - thrust - - told - - torn - - trodden - - understood - - upheld - - upset - - wed - - wept - - withheld - - withstood - - woken - - won - - worn - - wound - - woven - - written - - wrung diff --git a/.github/styles/Vaadin/ProductName.yml b/.github/styles/Vaadin/ProductName.yml deleted file mode 100644 index a6c0c3d7e4..0000000000 --- a/.github/styles/Vaadin/ProductName.yml +++ /dev/null @@ -1,50 +0,0 @@ -extends: substitution -message: "Use '%s' instead of '%s'." -level: error -ignorecase: false -# swap maps tokens in form of bad: good -swap: - AppLayout: App Layout - AvatarGroup: Avatar Group - CollaborationAvatarGroup: Collaboration Avatar Group - (?:[Cc])ollaboration ?(?:[Ee])ngine: Collaboration Engine - BigDecimalField: BigDecimal Field - Crud: CRUD - CheckBox: Checkbox - CheckboxGroup: Checkbox Group - CheckBoxGroup: Checkbox Group - ComboBox: Combo Box - ConfirmDialog: Confirm Dialog - ContextMenu: Context Menu - CookieConsent: Cookie Consent - CustomField: Custom Field - DatePicker: Date Picker - DateTimePicker: Date Time Picker - EmailField: Email Field - FormLayout: Form Layout - GridPro: Grid Pro - Grid PRO: Grid Pro - Pro Grid: Grid Pro - ProGrid: Grid Pro - ListBox: List Box - lumo: Lumo - MenuBar: Menu Bar - NumberField: Number Field - PasswordField: Password Field - ProgressBar: Progress Bar - RadioButton: Radio Button - RadioButtonGroup: Radio Button Group - RadioButton Group: Radio Button Group - RadioGroup: Radio Button Group - Radio Group: Radio Button Group - RichTextEditor: Rich Text Editor - SplitLayout: Split Layout - Testbench: TestBench - TextArea: Text Area - TextField: Text Field - TimePicker: Time Picker - Vaadin designer: Vaadin Designer - Vaadin flow: Vaadin Flow - Vaadin fusion: Vaadin Fusion - Vaadin Platform: the Vaadin platform - (?:[^\s]*) ?Vaadin platform: the Vaadin platform diff --git a/.github/styles/Vaadin/README.md b/.github/styles/Vaadin/README.md deleted file mode 100644 index 295d4fac75..0000000000 --- a/.github/styles/Vaadin/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Based on [Vale write-good](https://github.com/errata-ai/write-good). -Based on [write-good](https://github.com/btford/write-good). - -Copyright (c) 2020 Vaadin Ltd - -> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too. - -``` -The MIT License (MIT) - -Copyright (c) 2014 Brian Ford - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -``` diff --git a/.github/styles/Vaadin/SourceCode.yml b/.github/styles/Vaadin/SourceCode.yml deleted file mode 100644 index 4e15cae0e2..0000000000 --- a/.github/styles/Vaadin/SourceCode.yml +++ /dev/null @@ -1,13 +0,0 @@ -extends: existence -message: "Avoid writing source code inside Asciidoc content." -nonword: true -level: warning -scope: raw -tokens: -ignorecase: true -# Checks for the presence of the ; character within source code blocks -# (java, typescript, javascript, css, html), only if the character is -# followed by a white space character. Asciidoc include directive can -# use ; to delimit multiple tag names -tokens: - - '(?s)(\[source,\s?(?:java|typescript|javascript|css|html).*?\]\n----\s+.*?;\s.*?\n----)' diff --git a/.github/styles/Vaadin/Terms-App.yml b/.github/styles/Vaadin/Terms-App.yml deleted file mode 100644 index 7fa788aa52..0000000000 --- a/.github/styles/Vaadin/Terms-App.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Need to keep this as a separate rule in order to allow for 'app layout' -extends: substitution -message: "Prefer 'application' over 'app'." -level: warning -ignorecase: true -swap: - 'app (?:[^\s]*)': 'app layout' diff --git a/.github/styles/Vaadin/Terms.yml b/.github/styles/Vaadin/Terms.yml deleted file mode 100644 index 705301b182..0000000000 --- a/.github/styles/Vaadin/Terms.yml +++ /dev/null @@ -1,14 +0,0 @@ -extends: substitution -message: "Prefer '%s' over '%s'." -level: warning -ignorecase: true -action: - name: replace -swap: - dropdown: overlay - timeframe: time frame - repo: repository - NPM: npm - back[-|\s]end: backend - front[-|\s]end: frontend - separators?: dividers? diff --git a/.github/styles/Vaadin/TooWordy.yml b/.github/styles/Vaadin/TooWordy.yml deleted file mode 100644 index 1c55106e57..0000000000 --- a/.github/styles/Vaadin/TooWordy.yml +++ /dev/null @@ -1,224 +0,0 @@ -extends: existence -message: "'%s' is too wordy." -ignorecase: true -level: warning -tokens: - - a number of - - abundance - - accede to - - accelerate - - accentuate - - accompany - - accomplish - - accorded - - accrue - - acquiesce - - acquire - - additional - - adjacent to - - adjustment - - admissible - - advantageous - - adversely impact - - advise - - aforementioned - - aggregate - - aircraft - - all of - - all things considered - - alleviate - - allocate - - along the lines of - - already existing - - alternatively - - amazing - - ameliorate - - anticipate - - apparent - - appreciable - - as a matter of fact - - as a means of - - as far as I'm concerned - - as of yet - - as to - - as yet - - ascertain - - assistance - - at the present time - - at this time - - attain - - attributable to - - authorize - - because of the fact that - - belated - - benefit from - - bestow - - by means of - - by virtue of - - by virtue of the fact that - - cease - - close proximity - - commence - - comply with - - concerning - - consequently - - consolidate - - constitutes - - demonstrate - - depart - - designate - - discontinue - - due to the fact that - - each and every - - economical - - eliminate - - elucidate - - employ - - endeavor - - enumerate - - equitable - - equivalent - - evaluate - - evidenced - - exclusively - - expedite - - expend - - expiration - - facilitate - - factual evidence - - feasible - - finalize - - first and foremost - - for all intents and purposes - - for the most part - - for the purpose of - - forfeit - - formulate - - have a tendency to - - honest truth - # - however - - if and when - - impacted - # - implement - - in a manner of speaking - - in a timely manner - - in a very real sense - - in accordance with - - in addition - - in all likelihood - - in an effort to - - in between - - in excess of - - in lieu of - - in light of the fact that - - in many cases - - in my opinion - - in order to - - in regard to - - in some instances - - in terms of - - in the case of - - in the event that - - in the final analysis - - in the nature of - - in the near future - - in the process of - - inception - - incumbent upon - - indicate - - indication - - initiate - - irregardless - - is applicable to - - is authorized to - - is responsible for - # - it is - - it is essential - - it seems that - # OK: "the previous time it was called" - # - it was - - magnitude - - maximum - - methodology - - minimize - - minimum - - modify - - monitor - # OK: "is called multiple times" - # - multiple - - necessitate - - nevertheless - - not certain - - not many - - not often - - not unless - - not unlike - - notwithstanding - - null and void - - numerous - - objective - - obligate - - obtain - - on the contrary - - on the other hand - - one particular - - optimum - - overall - - owing to the fact that - - participate - - particulars - - pass away - - pertaining to - - point in time - - portion - - possess - - preclude - - previously - - prior to - - prioritize - - procure - - proficiency - - provided that - - purchase - - put simply - - readily apparent - - refer back - - regarding - - relocate - - remainder - - remuneration - - requirement - - reside - - residence - - retain - - satisfy - - shall - - should you wish - # - similar to - - solicit - - span across - - strategize - - subsequent - - substantial - - successfully complete - - sufficient - - terminate - - the month of - - the point I am trying to make - - therefore - - time period - - took advantage of - - transmit - - transpire - # "type of " not like "he is the type of a person..." - # - type of - - until such time as - - utilization - - utilize - - validate - - various different - - what I mean to say is - - whether or not - - with respect to - - with the exception of - - witnessed diff --git a/.github/styles/Vaadin/Versions.yml b/.github/styles/Vaadin/Versions.yml deleted file mode 100644 index f4f36028ac..0000000000 --- a/.github/styles/Vaadin/Versions.yml +++ /dev/null @@ -1,6 +0,0 @@ -extends: substitution -message: "Don't refer to a specific Vaadin version." -link: https://github.com/vaadin/docs/wiki/Authoring-articles#indicating-new-and-deprecated-features -level: error -swap: - 'Vaadin [0-9]{1,2}': Vaadin diff --git a/.github/styles/Vaadin/Weasel.yml b/.github/styles/Vaadin/Weasel.yml deleted file mode 100644 index 072ccc2c9a..0000000000 --- a/.github/styles/Vaadin/Weasel.yml +++ /dev/null @@ -1,209 +0,0 @@ -extends: existence -message: "'%s' is a weasel word." -ignorecase: true -level: warning -tokens: - - absolutely - - accidentally - - additionally - - allegedly - - alternatively - - angrily - - anxiously - - approximately - - awkwardly - - badly - - barely - - beautifully - - blindly - - boldly - - bravely - - brightly - - briskly - - bristly - - bubbly - - busily - - calmly - - carefully - - carelessly - - cautiously - - cheerfully - - clearly - - closely - - coldly - - completely - - consequently - - correctly - - courageously - - crinkly - - cruelly - - crumbly - - cuddly - - currently - - daily - - daringly - - deadly - - definitely - - deliberately - - doubtfully - - dumbly - - eagerly - - early - - easily - - elegantly - - enormously - - enthusiastically - - equally - - especially - - eventually - - exactly - - exceedingly - - exclusively - - extremely - - fairly - - faithfully - - fatally - - fiercely - - finally - - fondly - - few - - foolishly - - fortunately - - frankly - - frantically - - generously - - gently - - giggly - - gladly - - gracefully - - greedily - - happily - - hardly - - hastily - - healthily - - heartily - - helpfully - - honestly - - hourly - - hungrily - - hurriedly - - immediately - - impatiently - - inadequately - - ingeniously - - innocently - - inquisitively - - interestingly - - irritably - - jiggly - - joyously - - justly - - kindly - - largely - - lately - # OK: "to bind data lazily" - # - lazily - - likely - - literally - - lonely - - loosely - - loudly - - loudly - - luckily - - madly - # - many - - mentally - - mildly - - monthly - - mortally - - mostly - - mysteriously - - neatly - - nervously - - nightly - - noisily - - normally - - obediently - - occasionally - # OK: "should only be used for..." - # - only - - openly - - painfully - - particularly - - patiently - - perfectly - - politely - - poorly - - powerfully - - presumably - - previously - - promptly - - punctually - - quarterly - - quickly - - quietly - - rapidly - - rarely - - really - - recently - - recklessly - - regularly - - remarkably - - relatively - - reluctantly - - repeatedly - - rightfully - - roughly - - rudely - - sadly - - safely - - selfishly - - sensibly - - seriously - - sharply - - shortly - - shyly - - significantly - - silently - - simply - - sleepily - - slowly - - smartly - - smelly - - smoothly - - softly - - solemnly - - sparkly - - speedily - - stealthily - - sternly - - stupidly - - substantially - - successfully - - suddenly - - surprisingly - - suspiciously - - swiftly - - tenderly - - tensely - - thoughtfully - - tightly - - timely - - truthfully - - unexpectedly - - unfortunately - - usually - - very - - victoriously - - violently - - vivaciously - - warmly - - waverly - - weakly - - wearily - - weekly - - wildly - - wisely - - worldly - - wrinkly - - yearly diff --git a/.github/styles/Vocab/Docs/accept.txt b/.github/styles/Vocab/Docs/accept.txt deleted file mode 100644 index 958cd5ee7d..0000000000 --- a/.github/styles/Vocab/Docs/accept.txt +++ /dev/null @@ -1,47 +0,0 @@ -[aA]utoselect -app -async -[bB]oolean -[cC]acheable -classpath -configurator -Ctrl -[dD]eclaratively -[dD]raggable -favicon -Figma -GlassFish -Gradle -[gG]rayscale -Gretty -[hH]otpatch(ed|ing)? -Karaf -Lumo -Maven -[mM]iddleware -[nN]avbar -NetBeans -npm -npx -Payara -[pP]olyfills? -[pP]ortlets? -[rR]enderers? -repo -[sS]crollable -[sS]crollbars? -[sS]croller -[sS]ervlets? -[sS]upertype -[tT]odos? -[tT]oolchain -[tT]ooltips? -TravaOpenJDK -URIs -Vaadin -[vV]alidate -[vV]alidators? -[vV]iewports? -webpack -WildFly -Workbox diff --git a/.github/styles/Vocab/Docs/reject.txt b/.github/styles/Vocab/Docs/reject.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 13707be201..0000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Lint -on: [pull_request] -jobs: - vale: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: errata-ai/vale-action@master - with: - styles: | - https://github.com/errata-ai/Microsoft/releases/latest/download/Microsoft.zip - https://github.com/errata-ai/Google/releases/latest/download/Google.zip - https://github.com/errata-ai/write-good/releases/latest/download/write-good.zip - config: https://raw.githubusercontent.com/vaadin/docs/master/.vale.ini - files: __onlyModified - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - alex: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: reviewdog/action-alex@v1 - with: - github_token: ${{ secrets.github_token }} - # Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review]. - reporter: github-pr-review - # Change reporter level if you need. - # GitHub Status Check won't become failure with warning. - level: warning diff --git a/.gitignore b/.gitignore index b68bc4e1b1..51d9eaca29 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ scripts/docs-app .github/styles/write-good frontend/themes/docs/docs.generated.js + +dspublisher/theme/antlers diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 554f2a3baa..0000000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "singleQuote": true, - "printWidth": 100 -} diff --git a/.vale.ini b/.vale.ini deleted file mode 100644 index bd88453969..0000000000 --- a/.vale.ini +++ /dev/null @@ -1,97 +0,0 @@ -StylesPath = .github/styles - -Vocab = Docs - -# Ignored CSS class names -IgnoredClasses = filename, classname, methodname, interfacename, propertyname, guibutton, guilabel, custom-property - -# Some rules are still applied on asciidoc files unless they are replicated here -[*] - -# Ignored (blocks) -# Front matter -# # Block annotations (roles, etc) -BlockIgnores = (---[\S\s]*---), \ -(\[\S+\]) - -# Rules for asciidoc files -[*.{asciidoc,adoc}] - -# Ignored (blocks) -# Front matter -# # Include directives -BlockIgnores = (---[\S\s]*---), \ -(include::\S+\[.*]) - -# Ignored (inline text) -# Attribute substitution names -# Cross reference paths -# Include directives -# Image directives -TokenIgnores = \ -({\S+}), \ -(<<\S+\,), (<<[^\,]+>>), \ -(include::\S+\[.*]), \ -(image:{1\,2}\S+\[.*]) - -BasedOnStyles = Vaadin, Google, Microsoft, write-good, Vale - -############################################################################## -# Disabled checks - -# Google uses sentence-case for headings -# See https://developers.google.com/style/capitalization -Google.Headings = NO - -# Google has recommendations that we don't want for some words. -# Replace "application" with "app", etc. -# See https://developers.google.com/style/word-list -Google.WordList = NO - -# Google prefers em-dash instead of en-dash. Vaadin allows en-dashes as well. -Google.EnDash = NO - -# In American English, comma normally goes before the ending quotation mark, -# but in our case quotation marks are typically used to surround -# identifiers and such, where comma should go outside quotes. -Google.Quotes = NO - -# Microsoft recommends writing "address" instead of "URL" -# https://docs.microsoft.com/en-us/style-guide/urls-web-addresses -# https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/u/url -Microsoft.GeneralURL = NO - -# Microsoft suggests using contractions instead of formal writing -# https://docs.microsoft.com/en-us/style-guide/word-choice/use-contractions -Microsoft.Contractions = NO - -# Microsoft suggests against using acronyms in headings, -# such as "HTML Templates" -# https://docs.microsoft.com/en-us/style-guide/acronyms -Microsoft.HeadingAcronyms = NO - -# Microsoft suggests to avoid "backend" (among others), -# whereas we prefer that over "back end" or "back-end" -Microsoft.Avoid = NO - -# Duplicates Google.EmDash -Microsoft.Dashes = NO - -# Duplicates Google.Quotes -Microsoft.Quotes = NO - -# Duplicates Google.We -Microsoft.We = NO - -# Duplicates Google.FirstPerson -Microsoft.FirstPerson = NO - -# write-good classifies too wordy too eagerly for a more formal writing style -# The weasel words are also rather sensitive. -# Replaced by Vaadin.TooWordy, Vaadin.Weasel, and Vaadin.Passive -write-good.TooWordy = NO -write-good.Weasel = NO -write-good.Passive = NO - -# As per instructions in https://docs.errata.ai/vale/vocab#relation-to-ignore-files -Vale.Avoid = NO diff --git a/README.md b/README.md index f334f3232b..136a2cd887 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,14 @@ -# Vaadin documentation +# Vaadin 8 documentation -Official documentation and code examples for Vaadin. - -> **CONTENT ONLY** -> This repository does not generate the vaadin.com/docs website. It only contains the content for it. - -> **BETA** -> This repository is work-in-progress, and will eventually replace the existing separate documentation repositories for the different parts of the Vaadin platform. - - -## Branches - -All official documentation version branches (listed below) can and should contain documentation for pre-release features once they are available in a Vaadin pre-release. Remember to indicate new features with a “since version” indicator in Asciidoc, for example, `[role="since:com.vaadin:vaadin@V18"]`. - -### `master` - -Documentation for the latest major Vaadin version, including all previous major versions since the latest LTS version. If in doubt, make documentation updates against this branch. - -### `v14` - -Documentation Vaadin 14, the latest long-term supported version (LTS). +Documentation and code examples for Vaadin 8. ## Contents -Files not explicitly listed below are from the standard Vaadin project setup. - ### `articles` - A hierarchy of AsciiDoc (either `.asciidoc` or `.adoc`) files, documenting the use of all Vaadin features. The file path defines the resulting URL on the documentation site. For example: - - `articles/intro/index.asciidoc` → `/intro/` - `articles/forms/data-binding.asciidoc` → `/forms/data-binding/` See [Authoring articles](https://github.com/vaadin/docs/wiki/Authoring-articles) to learn how to write documentation articles. - -### `frontend` - -Fusion/TypeScript examples, which are included as rendered examples in the documentation. Follow Vaadin best practices when creating code examples. - -### `src` - -Flow/Java examples, which are included as rendered examples in the documentation. Follow Vaadin best practices when creating code examples. - -### `scripts` - -Project related scripts (tests, validation builds, preview deployment, etc). - -### `.github` - -Files related to linting the articles against the writing style guidelines with [Vale](https://docs.errata.ai/vale/about). See [Vale linter setup instructions](). - -### `versions.json` - -Describes the publicly available documentation versions. These versions will appear in the published website, as options for the users. This file is only relevant in the `master` branch. diff --git a/articles/404.asciidoc b/articles/404.asciidoc new file mode 100644 index 0000000000..c73a945faa --- /dev/null +++ b/articles/404.asciidoc @@ -0,0 +1,14 @@ +--- +title: Page Not Found (404) +layout: index +--- + +[small]#404# + +== Page Not Found + +[.lead] +Unfortunately, we couldn't find this page. +It might have moved, or it no longer exists. + +You can try searching for it (press kbd:[Ctrl/Cmd+K]), or you can go to the link:/[start page, role=skip-xref-check]. diff --git a/articles/_commercial-banner.asciidoc b/articles/_commercial-banner.asciidoc index 8fb85a17ae..32a7605870 100644 --- a/articles/_commercial-banner.asciidoc +++ b/articles/_commercial-banner.asciidoc @@ -2,11 +2,11 @@ ++++ -ifndef::commercial-feature-included[] -:commercial-feature-included: This feature is +ifndef::commercial-feature[] +:commercial-feature: this feature +endif::[] + +ifdef::kit-trial[] +:trial-link: https://pages.vaadin.com/acceleration-kit-trials[Request Trial^] +endif::[] + +ifndef::trial-link[] +:trial-link: https://vaadin.com/trial[Start Free Trial^] +endif::[] + +ifndef::commercial-banner-content[] +:commercial-banner-content: A commercial Vaadin subscription is required to use {commercial-feature} in your project. endif::[] -.Subscription required -[.commercial] +.Commercial feature +[.commercial.skip-search-index] [NOTE] ==== -{commercial-feature-included} included in Pro, Prime, and Enterprise subscriptions. +{commercial-banner-content} [.buttons] -- https://vaadin.com/trial[Start Free Trial^] +- {trial-link} - https://vaadin.com/pricing[See Pricing^] ==== diff --git a/articles/_images/bov-8-half.png b/articles/_images/bov-8-half.png new file mode 100644 index 0000000000..501fcd3288 Binary files /dev/null and b/articles/_images/bov-8-half.png differ diff --git a/articles/_images/ce.svg b/articles/_images/ce.svg deleted file mode 100644 index 29533036d0..0000000000 --- a/articles/_images/ce.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/articles/_images/components.svg b/articles/_images/components.svg index b0766a2176..1e15b01605 100644 --- a/articles/_images/components.svg +++ b/articles/_images/components.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/articles/_images/design-system.svg b/articles/_images/design-system.svg deleted file mode 100644 index 34a0c9b115..0000000000 --- a/articles/_images/design-system.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/articles/_images/flow.svg b/articles/_images/flow.svg index 207b6d3461..0dd09ae8a5 100644 --- a/articles/_images/flow.svg +++ b/articles/_images/flow.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/articles/_images/fusion.svg b/articles/_images/fusion.svg deleted file mode 100644 index f52563f4c9..0000000000 --- a/articles/_images/fusion.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/articles/_images/guides.svg b/articles/_images/guides.svg index 304aabc391..4f9e91a0f1 100644 --- a/articles/_images/guides.svg +++ b/articles/_images/guides.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/articles/_images/themes.svg b/articles/_images/themes.svg deleted file mode 100644 index 45aa9b88b1..0000000000 --- a/articles/_images/themes.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/articles/appseckit/advanced-topics.asciidoc b/articles/appseckit/advanced-topics.asciidoc new file mode 100644 index 0000000000..a7226daaa2 --- /dev/null +++ b/articles/appseckit/advanced-topics.asciidoc @@ -0,0 +1,57 @@ +--- +title: Advanced Topics +order: 3 +layout: page +--- + + +[[appseckit.advanced]] += Advanced Topics + +This page highlights some advanced topics related to AppSec Kit. + + +== AppSec Kit Configuration + +This section describes the configuration options and their default values. The AppSec Kit has the `AppSecConfiguration` class. An instance of this class can be set to configure the `AppSecService` like so: + +[source,java] +---- +AppSecConfiguration configuration = new AppSecConfiguration(); +configuration.setAutoScanInterval(Duration.ofDays(2)); + +AppSecService.getInstance().setConfiguration(appSecConfiguration); +---- + +You can set or override the following configuration values in the `AppSecConfiguration`: + +- `dataFilePath` is the path of the data file for storing information about the vulnerabilities; +- `bomFilePath` is the path of the SBOM (Software Bill Of Materials) file used as a source of dependencies; +- `taskExecutor` is the executor used to run asynchronous tasks during the vulnerability scanning; +- `autoScanInterval` is the duration of the interval between automatic scanning for vulnerabilities; and +- `osvApiRatePerSecond` is the rate per second for the OSV (Open Source Vulnerability) API calls. + + +=== Data File Path + +In the `Vulnerability Details View`, you can add an analysis of the vulnerability. When this analysis is saved with the vulnerability information, it's stored in a data file in JSON format. Its default path is the application's root; the file name is [filename]`appsec-data.json`. The path can be configured by the `vaadin.appsec.data` system property. + + +=== SBOM File Path + +An application's Maven dependencies in the [guilabel]*Dependencies View* are populated from this file. The file should contain the dependencies in link:https://cyclonedx.org/specification/overview/[CycloneDX JSON schema] format. Its default path is the `/resources`; the file name is [filename]`bom.json`. The path can be configured by the `vaadin.appsec.bom` system property. + + +=== Task Executor + +You can set a custom executor for the background and scheduled jobs run by the AppSec Kit. For example, scheduled jobs are run when an automatic or manual vulnerability scan happens. The default task executor is a single-thread executor. + + +=== Auto Scan Interval + +You can configure the duration of the interval between automatic scanning for vulnerabilities. The default interval is 1 day. + + +=== OSV Rate Per Second + +You can configure the rate per second value for the OSV (Open Source Vulnerability) link:https://google.github.io/osv.dev/api/[API] calls. The default value is 25. diff --git a/articles/appseckit/appseckit-overview.asciidoc b/articles/appseckit/appseckit-overview.asciidoc new file mode 100644 index 0000000000..1e3a0fb3fd --- /dev/null +++ b/articles/appseckit/appseckit-overview.asciidoc @@ -0,0 +1,36 @@ +--- +title: Overview +order: 1 +layout: page +--- + + +[[appseckit.overview]] += AppSec Kit + +AppSec Kit offers seamless security integration into the development of your Vaadin-based applications. It provides comprehensive dependency visibility, earlier remediation of vulnerabilities, and fewer false positives. + +:commercial-feature: AppSec Kit +:kit-trial: true +include::{articles}/_commercial-banner.asciidoc[opts=optional] + + +=== Comprehensive Dependency Visibility + +Managing dependencies is a crucial aspect of any software project, but it can be a complex and time-consuming task. AppSec Kit provides dependency visibility, generating a Software Bill of Materials (SBOM) that offers a comprehensive view of all direct and transitive dependencies used in your application. + +The SBOM is generated automatically each time you do a development build -- or can be initiated on-demand. This allows you to have complete visibility of the contents of your application. + + +=== Earlier Remediation of Vulnerabilities + +AppSec Kit further streamlines the remediation process by regularly scanning the SBOM and cross-referencing it with multiple industry-standard vulnerability databases, including National Vulnerability Database and GitHub Security Advisories. It identifies known vulnerabilities in both direct and transitive dependencies and includes detailed information, such as severity and patch versions. + +Reports on the results are displayed in Vaadin Development tools, ensuring smooth integration into your Vaadin application development process. This allows you to address vulnerabilities earlier in the development process, ensuring the security of your web applications without compromising development speed. + + +=== Fewer False Positives + +By identifying and highlighting any false positives associated with Vaadin Flow and its dependencies, AppSec Kit makes it easier for developers to identify the vulnerabilities that actually do need addressing. + +AppSec Kit flags any _false positive_ vulnerabilities that were identified in the dependencies of the Vaadin platform. It shows the analysis from Vaadin's security team, describing why it was considered a false positive. This allows you to focus on true vulnerabilities, what matters. diff --git a/articles/appseckit/getting-started.asciidoc b/articles/appseckit/getting-started.asciidoc new file mode 100644 index 0000000000..036ef8a8af --- /dev/null +++ b/articles/appseckit/getting-started.asciidoc @@ -0,0 +1,174 @@ +--- +title: Getting Started +order: 2 +layout: page +--- + + +[[appseckit.introduction]] += Getting Started with AppSec Kit + +AppSec Kit is an excellent tool for monitoring your application dependencies for vulnerabilities. It lets you see details of discovered vulnerabilities. You can record and store your analysis to share with other developers. + +This step-by-step guide will show you how to use AppSec Kit in an application. + + +== Add AppSec Kit Dependency + +To start, you'll need to add AppSec Kit as a dependency to your application. To add to a Maven project, you might add something like this to your [filename]`pom.xml` file: + +.pom.xml +[source,xml] +---- + + com.vaadin + appsec-kit-v8 + 1.0.1 + +---- + +.Version Number +[NOTE] +See the link:https://github.com/vaadin/appsec-kit/releases[AppSec Kit releases page] for the latest version, or a different version of the dependency. + + +== Generating an SBOM + +To be able to monitor the application dependencies, AppSec Kit needs a Software Bill of Materials (SBOM) file. This file contains information about the dependencies and their transitives. + +To generate the SBOM file, you'll need to add the link:https://github.com/CycloneDX/cyclonedx-maven-plugin[cyclonedx-maven-plugin] to the plugins in your [filename]`pom.xml` file like so: + +.pom.xml +[source,xml] +---- + + org.cyclonedx + cyclonedx-maven-plugin + 2.7.7 + + + generate-resources + + makeAggregateBom + + + + + library + 1.4 + true + true + true + true + true + false + false + true + json + bom + ${project.build.outputDirectory}/resources + false + + +---- + +Before starting the application, be sure to run `maven install`. The SBOM file, [filename]`bom.json` should then be generated in the `/resources` sub-directory in the project's output directory. The plugin is configured to do this. + +=== External APIs + +AppSec Kit calls external APIs to get vulnerabilities and a vulnerability analysis for Vaadin dependencies. Since these calls are required for a normal operation, they need to be accessible. + +[source,text] +---- +OSV (Open Source Vulnerability) API: +https://api.osv.dev/v1/querybatch +https://api.osv.dev/v1/vulns/ + +GitHub API: +https://api.github.com/repos/vaadin/framework/releases + +Vaadin vulnerability analysis: +https://raw.githubusercontent.com/vaadin/vulnerability-analysis/main/analysis.json +---- + + +=== Start the Application + +AppSec Kit isn't enabled in production mode. You'll need to start your application in debug mode -- or in development mode. By default, the Vaadin 8 applications start in link:https://vaadin.com/docs/v8/framework/application/application-environment#application.environment.parameters.production-mode[debug mode]. You don't need to enable this, explicitly. + + +=== Notification Dialog + +After the application has started, AppSec Kit analyzes the dependencies, collects new vulnerabilities, and displays a notification dialog. A vulnerability is considered as new if a developer analysis has not yet been added to it. Therefore, vulnerabilities with developer analysis aren't counted in the found vulnerabilities number. In the screenshot, you'll see a link labeled _Open AppSec Kit_ that you can click on to open the UI in a new tab. + +[[getting-started-notification-dialog]] +.AppSec Kit Notification Dialog +image::img/notification-dialog.png[] + +You can also navigate to the UI using the `vaadin-appsec-kit` URL parameter. For example, on your localhost, enter something like this in your browser: link:http://localhost:8080/?vaadin-appsec-kit[http://localhost:8080/?vaadin-appsec-kit]. + +You should configure link:https://vaadin.com/docs/v8/framework/advanced/advanced-push[server push] for a `UI` so you'll be notified when new vulnerabilities are found. You can do this by adding the `@Push` annotation to a UI class like so: + +[source,java] +---- +@Push +public class ExampleUI extends UI { + // ... +} +---- + +The server push support in Vaadin, though, requires the separate Vaadin Push library. In Maven, add the following dependency to your [filename]`pom.xml` file: + +.pom.xml +[source,xml] +---- + + com.vaadin + vaadin-push + ${vaadin.version} + +---- + + +== AppSec Kit UI + +The AppSec Kit UI has views for seeing vulnerabilities and dependencies of which you should be aware. This section describes these views, which can be found under the two main tabs of the UI. + + +=== Vulnerabilities Tab + +When you open the UI, you'll see the *Vulnerabilities* tab (see screenshot here). Any collected vulnerabilities are listed there. They're shown in a grid view with columns to help identify each vulnerability, the dependency in which each has been found, the severity, a risk score and some analyses. + +You can filter the vulnerabilities by using the Dependency, Developer Analysis, and Severity Level filters. You'd choose these filters from the pull-down menus near the top left, then click the `Filter` button at the top right. Click on the `Clear` button next to it to reset the filters. + +[[getting-started-vulnerabilities-tab]] +.AppSec Kit Vulnerabilities View +image::img/vulnerabilities-tab.png[] + +To run a new scan, click the `Scan now` button at the top right corner. After it's finished, the `Last Scan` date and time is updated -- located also at the top right. + +If you want to see more details about a vulnerability, select the row containing the vulnerability of interest and then click the `Show details` button. Or you can just double-click on a row. The `Vulnerability Details View` is then opened -- which is described next. + + +=== Vulnerability Details + +When you open a listed vulnerability, you can find a more detailed description of it (see screenshot here). You'll also find there links to other pages to explain the vulnerability and offer some general suggestions to resolve the vulnerability. + +If the Vaadin Security Team is reviewing the vulnerability, it will be noted at the top. This includes Vaadin's specific assessment and recommendations related to the vulnerability. + +[[getting-started-vulnerability-details-view]] +.AppSec Kit Vulnerability Details View +image::img/vulnerability-details-view.png[] + +On the right side of the Details View, there's a `Developer analysis` panel. There you can set the `Vulnerability status` and add your own description and other information you've uncovered. Preserve what you enter by clicking the `Save` button. Note, your analysis will be available to other developers if you commit it to the version control system. + + +==== Dependencies Tab + +To see your application dependencies, click on the *Dependencies* tab at the top left of the UI. There you'll find a list of dependencies shown in a grid view (see screenshot here). They're listed in columns to help identify each dependency and the group to which it belongs, the version, the severity, and a risk score. + +[[getting-started-dependencies-tab]] +.AppSec Kit Dependencies View +image::img/dependencies-tab.png[] + +You can filter the list of dependencies based on the Dependency Group and the Security Level. You'd do this by choosing one or both of these two filters from the pull-down menus near the top left, then clicking the `Filter` button at the top right. Click the `Clear` button next to it to reset the filters. diff --git a/articles/appseckit/img/dependencies-tab.png b/articles/appseckit/img/dependencies-tab.png new file mode 100644 index 0000000000..cdfa159d77 Binary files /dev/null and b/articles/appseckit/img/dependencies-tab.png differ diff --git a/articles/appseckit/img/notification-dialog.png b/articles/appseckit/img/notification-dialog.png new file mode 100644 index 0000000000..468bfc1dd4 Binary files /dev/null and b/articles/appseckit/img/notification-dialog.png differ diff --git a/articles/appseckit/img/vulnerabilities-tab.png b/articles/appseckit/img/vulnerabilities-tab.png new file mode 100644 index 0000000000..2fd0fcedfb Binary files /dev/null and b/articles/appseckit/img/vulnerabilities-tab.png differ diff --git a/articles/appseckit/img/vulnerability-details-view.png b/articles/appseckit/img/vulnerability-details-view.png new file mode 100644 index 0000000000..0e9a437497 Binary files /dev/null and b/articles/appseckit/img/vulnerability-details-view.png differ diff --git a/articles/appseckit/index.asciidoc b/articles/appseckit/index.asciidoc new file mode 100644 index 0000000000..2a4ded5379 --- /dev/null +++ b/articles/appseckit/index.asciidoc @@ -0,0 +1,4 @@ +--- +title: AppSec Kit +order: 8 +--- diff --git a/articles/bakeryfw8/adding-a-view.asciidoc b/articles/bakeryfw8/adding-a-view.asciidoc new file mode 100644 index 0000000000..37ca9cc125 --- /dev/null +++ b/articles/bakeryfw8/adding-a-view.asciidoc @@ -0,0 +1,104 @@ +--- +title: Adding a view +order: 4 +layout: page +--- + += Adding a view + +In the following, we're going to create a new view and add it to the navigation, step-by-step. The view we are creating here is an "About" view. + +== Creating a design + +The views of bakery are built with Designer. We start off by creating a new design file. Bakery uses a convention that each main view has it's own package. We create a new package called `about` inside the `ui.view` package and within it a new design called `AboutViewDesign`. + +image::img/new-design.png[Adding a new design file] + +== Creating the View for the Design + +Creating a design will create a HTML design file in the resource package as well as generated Java class in the java package. We then create a class called `AboutView` in the same package and extend the generated Design Java file. We extend the generated class because it is regenerated whenever the design is modified and if we edit the generated file, our changes would be removed when the file is regenerated. The `AboutView` is the class that will be initialized when the user wants to enter the view. + +```java +package com.vaadin.starter.bakery.ui.view.about; + +public class AboutView extends AboutViewDesign { +} +``` + +Any logic or configuration that you want to add into the view goes here. + +== Including the view to the application + +We have to tell the application that `AboutView` is a valid view to be shown in the application. This is achived by annotating the class with `@SpringView` (Spring) or `@CDIView` and implementing `View`. + +```java +package com.vaadin.starter.bakery.ui.view.about; + +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.starter.bakery.ui.view.NavigableView; + +@SpringView +public class AboutView extends AboutViewDesign implements View { + + @Override + public void enter(ViewChangeEvent viewChangeEvent) { + } +} +``` + +`@SpringView` or `@CDIView` tells Vaadin that this is a view which should be associated with a URI fragment. Using a parameter for the `@SpringView(name="something")` or `@CDIView("something")` annotation we can define the URL for the view for the view, for example _https://www.myapplication.com/#!something._. If we leave out the name parameter, the URL will be deduced from the class name by removing the `View` suffix. + ++If you want to execute some code when the user enters the view, you can override the `enter(ViewChangeEvent)` method in the `View` interface. This is an easy place to for example update/refresh data. + +The view is now accessible by going to the url http://localhost:8080/#!about. However, it does not appear in the menu yet. + +image::img/about-view-not-in-menu.png[About view available, but not in menu.] + +== Adding the view to the menu + +To modify the menu, we want to first open the main layout design, `MainViewDesign` in the view package. We want to add a new Button into the 'menu' layout. The easiest way to do this is select the last view and pressing copy paste on it (ctrl+c -> ctrl+v). This will add a copy of the menu button with same icon and caption. Let's change those. In the properties panel, you want to change Name, Icon, Caption and DomId to match your new view. Next to icon is a handy button where you see the icons and select a new one visually. The list contains all the built-in font-icons from link:https://vaadin.com/docs/latest/components/icons/default-icons[Vaadin Icons]. + +TIP: Refer to link:https://vaadin.com/docs/-/part/designer/designer-overview.html[Vaadin Designer documentation] to learn more about visually designing your UI. + +image::img/about-to-menu-designer.png[About added to the menu.] + +The button is now in the menu but it still doesn't do anything. The event handlers are wired in the `MainView` class in the `ui.view.MainView` Java package. We can make the "About the app" button navigate to the `AboutView` by modifying the `init()` method: + +```java +public void init() { + attachNavigation(storefront, StorefrontView.class); + attachNavigation(dashboard, DashboardView.class); + attachNavigation(users, UserAdminView.class); + attachNavigation(products, ProductAdminView.class); + attachNavigation(about, AboutView.class); + + logout.addClickListener(e -> logout()); +} +``` + +Now we have the view in the menu as well and the user can navigate to it. That's it! + +image::img/about-in-menu.png[About view ready.] + +== Restricting access to the view. + +If you want to restrict access to some views, you can require the user to have certain roles by adding an annotation. Restricting access to the About-view might not make much sense usually, but we'll do it anyway: + +```java +@SpringView(name = "about") +@Secured(Role.ADMIN) +public class AboutView extends AboutViewDesign implements View { + ... +``` + +or + +```java +@CDIView("about") +@RolesAllowed(Role.ADMIN) +public class AboutView extends AboutViewDesign implements View { + ... +``` + +`@Secured(Role.ADMIN)` or `@RolesAllowed(Role.ADMIN)` will require that the user that is logged in has the ADMIN role to be able to access the view. If the user does not have the role, then the view will not be in the menu and the user will get an "Access denied" message if she tries to access it with a direct URL or otherwise. diff --git a/articles/bakeryfw8/architecture.asciidoc b/articles/bakeryfw8/architecture.asciidoc new file mode 100644 index 0000000000..cd3de96ab9 --- /dev/null +++ b/articles/bakeryfw8/architecture.asciidoc @@ -0,0 +1,76 @@ +--- +title: Architecture +order: 3 +layout: page +--- + += Architecture +The guiding principle when create the architecture was +"Create what is needed, do not create what you might think possibly will be needed sometimes in the future maybe". + +By focusing on the current needs you are able to ship a fully working version much faster than if you try to take all possibly future scenarios into account. When the application evolves and becomes more complex, you can add complexity in the parts that really need it and not spend effort on adding complexity where it will just be in the way. As long as you have automated tests, you can be confident in your refactoring that you are not breaking the application. + +The app starter is a layered application, where the service layer knows how to deal with persistent data i.e. the database, and the UI layer takes care of setting up the correct component hierarchy for the user to see and reacting to events from the user. + +== Service Layer +The service layer is separated from the UI layer for multiple reasons. The most pertinent one is to avoid creating messy UI code. + +The service layer is responsible for providing data to the UI layer for showing to the end user, and for handling updates to the data based on actions the end user performs in the application. +It hides the data layer implementation details, e.g. Spring/Deltaspike Data in this app starter, from the UI so the UI can use understandable and descriptive high level methods. In addition to making the UI code easy to read, this provides a logical place to handle transaction boundaries, data level access control (not implemented in this app starter) and other database related concepts. + +While the service layer in this app starter is separated only using a package name, it could quite easily be extracted to a separate Maven module. The advantage of this is that you can verify you are not accidentally using the UI layer from the service layer (there should be no dependency ever in this direction). The disadvantage is that you will have a more complex project as it will become a multi module Maven project. + +The service layer in this app starter is built upon Spring/Deltaspike Data. Validation in the service layer is performed using bean validation and annotations on the entity classes. + +An H2 in-memory database is used by default for easy setup and getting started. This should be swapped out for a real database before going into production, see <>. + +== UI Layer +The UI layer is responsible for creating an interface for the user to see, reacting to events from the user, calling the service layer to fetch and update data, and to update the user interface based on changes. + +=== Everything is a component +As the UI layer is built using Vaadin Framework 8, it is component based. Everything you see on the screen is a component, possibly containing other components. + +There are two types of components involved in creating the UI: Basic UI components and Application components. + +*Basic UI components* are the components shipped with Vaadin Framework itself or included as add-ons. This includes components such as `Button` where you mainly listen for events from the user, layout components like `Board` and user input components such as `TextField`. The basic UI components are general purpose and can be used in all applications as they are not tied in any way to the application logic. + +*Application components* are components created inside the application itself. An application component differs from a basic UI component in the way that it knows about the application and how the application should work. In many cases you do not think about that you create application components, but in practice all views in your application are components, parts of the views are typically extracted to application components and so on. + +In this app starter, there are many application components used. In addition to the main layout and all views, there are smaller components like `OrdersGrid` and `RoleSelect`. + +Both `OrdersGrid` and `RoleSelect` are standalone components which knows how to show certain data to the user. `OrdersGrid` is the grid used on the Dashboard and the Storefront views, capable of showing the orders which are due today and in the future. `RoleSelect` is a drop down which shows the available roles in the application. They both connect to the service layer when they need some data and present it to the user in a suitable way. + +=== Patterns for Building Application Components +Some application components are very simple, like `RoleSelect`. They can be implemented using a few lines of code and naturally fit into one class. Trying to split a component like this into multiple parts would only include complexity and go against the guiding principles for the achitecture. + +Some application components on the other hand are very complex. At least views with much functionality tend to fall into this category. To be able to deal with the complexity, the implementation should be split into multiple parts, each with a clear responsibility. This can be done in different ways but in this app starter the first split is done into layout and logic using Vaadin Designer for the layouts. + +Vaadin Designer naturally splits out all the layout configuration into the Design HTML file and creates an auto generated companion Java file so the components used in the layout can be accessed from Java. The logic (event listeners, service layer calls etc) is then added to a separate Java file, which typically extends the generated class so it can access the components in the layout. + +For some application components, the split between layout and logic is not enough to deal with the complexity. There are a couple of cases in this app starter when this split just did not make the code readable and understandable. The view where you create/edit an order and the CRUD views for users and products will still be hard to read when you have split out the layout code as there is simply quite much logic code. In these cases, the MVP pattern (or a variant thereof) has been utilized so that pure business logic goes into a `presenter` class and UI related logic goes into a `view` class (there is no `model` class as the model is so simple in all the cases). + +[NOTE] +Do not confuse the "V" in MVP with a `View` in Vaadin. The "V" in MVP stands for the UI part of the component while a `View` in Vaadin stands for something which has a URL and can be navigated to. You can build an application component using MVP even though the component is not a Vaadin `View`. + +In the cases the MVP pattern is utilized, the view decides which components to use and how to lay them out (the Design file is considered as part of the view). The view also wires event listeners, configures how fields are bound and what validators to use in the UI (validators are UI level helpers, the real data validation takes place in the service layer). + +The presenter is the one aware of the service layer (view is not), deals with what should happen on view events and also handles navigation to/from views. + +[NOTE] +To follow the guiding principle, the MVP implementations do not try to accomplish goals like making the presenter not know about Vaadin Framework, making it possible to swap the View class with an implementation not based on Vaadin Framework etc. The presenter class is aware of Vaadin Framework concepts and classes but does not care about specific components used in the view. + +=== Communication between Application Components +Application components are built to be standalone and reusable in multiple places. To avoid coupling them to other application components, they provide an API which can be used to configure them and/or they fire events to indicate that something has happened which might be of interest to other components. + +References to other components are acquired by utilizing dependency injection. Many components exist only in one place in the view and are then using `@ViewScope` (only one instance is created per view). These can be injected into any other component in the view without accidentally creating multiple instances. After injection, the component API can be used to e.g. add an event listener. + +Some components can appear multiple times on a view, like the `ProductInfo` component which encapsulates the information about one product in an order (product name, quantity, details) and provides controls for modifying and removing the product. The `ProductInfo` component is set to `prototype` scope so that a new instance is created whenever it is injected. We can therefore not inject references into other components the same way as for components using `@ViewScope`. To get events from the `ProductInfo` components, a view scoped event bus is used. The `ProductInfo` component fires an event whenever some information inside it changed and every other component in the view can listen to any event it is interested in. In this case `OrderEditPresenter` listens for `ProductInfoChangeEvent`s and reacts to them by recalculating the new total price for the order. + +[TIP] +Keep it simple, do what you need now and refactor when you need more. + +[NOTE] +The event bus is scoped to the active view so that views can be removed from memory once the user has navigated away. + +[NOTE] +Events should tell what happened and not what action the receiver should take. This makes code much more clear and also ensures the responsibilities stay clear. diff --git a/articles/bakeryfw8/bakery.asciidoc b/articles/bakeryfw8/bakery.asciidoc new file mode 100644 index 0000000000..ea8ccbac3f --- /dev/null +++ b/articles/bakeryfw8/bakery.asciidoc @@ -0,0 +1,15 @@ +:sectnums: + +include::overview.asciidoc[] + +:toc: + +include::running-building-packaging.asciidoc[] + +include::adding-a-view.asciidoc[] + +include::theming.asciidoc[] + +include::changing-database.asciidoc[] + +include::going-to-production.asciidoc[] diff --git a/articles/bakeryfw8/changing-database.asciidoc b/articles/bakeryfw8/changing-database.asciidoc new file mode 100644 index 0000000000..995324385a --- /dev/null +++ b/articles/bakeryfw8/changing-database.asciidoc @@ -0,0 +1,55 @@ +--- +title: Changing database +order: 6 +layout: page +--- + +[[changing-database]] += Changing Database + +The application comes bundled with an in-memory H2 database. You can change which database is in use by adding the correct dependencies for the your database and modifying the `application.properties` file (when using Spring) or configuring the server to use another database (when using JavaEE). See the sections below for more detailed information. + +== Configuring the Spring Application to use your Database + +The corresponding connector for you database needs to be available to be able to use your database of choice. For example if you use MySQL, you need to add the approriate dependency to your `pom.xml`: + +``` + + mysql + mysql-connector-java + + 6.0.4 + +``` + +The database is configured in `src/main/resources/application.properties`. You can configure the database with the following properties. + +``` +spring.jpa.hibernate.ddl-auto=create +spring.datasource.url=jdbc:mysql://localhost/dbtest +spring.datasource.username=someuser +spring.datasource.password=somepassword +``` + +Here the URL to the database is given using `spring.datasource.url`. Spring Boot can most often deduce which database you have in use from the url and you don't have to explicitely specify it. If for some reason you need to have control of them, you can also add `spring.datasource.driver-class-name=com.mysql.jdbc.Driver` and `spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect`. + +== Configuring the JavaEE Application to use your Database + +In JavaEE applications, the database is configured in the server and made available through JNDI to the application. In `src/main/resources/META-INF/persistence.xml` the database connection is configured using `BakeryDS`. The server must make a data source named `BakeryDS` available for this to work. + +There are configuration files in the project to setup the test database in `src/main/webapp/WEB-INF`: `resources.xml` for TomEE, `wildfly-h2-ds.xml` for Wildfly and `src/test/resources/server.xml` for Liberty. These are included only to make it easy to get started and are not meant for production. For production, you should specify the datasource in the server itself. + +If you want to change the database defined in the project itself, you can update the configuration file for the server you are using. All the configuration files specify more or less the same parameters: JDBC url, driver, user and password. These need to be updated to match your database. + +== Automatically Updating the Database Schema + +The property `spring.jpa.hibernate.ddl-auto` in `application.properties` (Spring) or `` in `persistence.xml` (JavaEE) defines what should be done to the database when the application starts. The valid options are none, update, create and create-drop. + +* `none` does not modify the database in any way on application start-up. +* `update` tries to modify an existing schema to match the one defined by the application without deleting old data. +* `create` creates the database if one doesn't exist from before, but doesn't modify an existing database in any way. +* `create-drop` always deletes any existing database and creates it again from scratch. + +In Spring, the default option depends on the choice of database. In-memory databases by default do `create-drop` while other databases use `none`. + +You can read more on how to configure the database in Spring's documentation https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html[Working with SQL databases] diff --git a/articles/bakeryfw8/deploying-to-aws.asciidoc b/articles/bakeryfw8/deploying-to-aws.asciidoc new file mode 100644 index 0000000000..2726b2ae3a --- /dev/null +++ b/articles/bakeryfw8/deploying-to-aws.asciidoc @@ -0,0 +1,108 @@ +--- +title: Going to production with Spring & Beanstalk +order: 7 +layout: page +--- + += Going to production with Spring & Beanstalk +There are many options when looking to deploy your application for production, ranging from in-house to cloud-based solutions. + +In the following we'll take a look at how to deploy the Spring version to AWS Elastic Beanstalk (EB). + +Beanstalk is part of Amazon Web Services (AWS) and hides a lot of the complexity with provisioning, load balancing, scaling etc, since you do not have to deal with each of these individually. However, since it's part of AWS, you can still take full control of the individual services, if you have specific needs, or as your application grows. + +== Getting an Amazon Elastic Beanstalk account + +In order to use Amazon Elastic Beanstalk, you need to have a AWS account. Head over to https://aws.amazon.com/elasticbeanstalk to read more about the service, and create an account. + +TIP: You will be asked to provide credit-card details before making use of AWS services, but there is a link:https://aws.amazon.com/free[free tier] that allows you to try the service for free. You can also set up a link:https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/free-tier-alarms.html[billing alarm] to ensure you don't accidentally exceed the free tier limits (or any other spending budget you might have.) + +We'll do the following steps + + 1. Configure the application for production + 2. Build a production WAR + 3. Create an EB application, upload the WAR + 4. Create a stand-alone production database in EB + 5. Configure the application to use the production database + +== Configuring Vaadin for Production +When going to production, you want to make sure your Vaadin application is in production mode by setting the following parameter in `application.properties`: + +`vaadin.servlet.productionMode=true` + +== Configuring a Production Database + +To be able to use another database, you first need to add the appropriate JDBC driver as a dependency in `pom.xml`, e.g for MySQL: +``` + + mysql + mysql-connector-java + +``` +Changing the database is covered in more detail in <> + +When running in EB, the environment provides some variables we can use to configure our database connection in `application.properties`: +``` +spring.jpa.hibernate.ddl-auto=create +spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME}:${RDS_PORT}/${RDS_DB_NAME} +spring.datasource.username=${RDS_USERNAME} +spring.datasource.password=${RDS_PASSWORD} +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +``` + +NOTE: There is a separate `application.production.properties` with these properties pre-configured. We'll configure EB to use that instead of the regular `application.properties` - that way we can have separate production and development properties, and use the embedded database when developing. + +== Preparing a Production WAR +Run `mvn install` to build and package your application into a `.war` -file (it will be placed in the `target` folder). + +== Creating an EB Web Application +To create a new Elastic Beanstalk application, either click "Build a web app" in the AWS main page, know as the "console". +(You can also find Elastic Beanstalk in the menu and "Create New Application" - the steps will be similar, but not identical.) + +image::img/aws-eb-create.png[Creating a EB web application] + +Next choose a name for your application, select "tomcat", and "upload your code". + +At this point, we can click "Create application", and wait for the environment to start (it can take a while). + +Once started, we can go to the URL (available in at the top of the page) and verify our application is working. + +image::img/aws-eb-running.png[Application running] + +However, at this point the application is still using the internal database. + +== Creating a Database for Production +From the "Configuration" screen we can configure a database in the "Data Tier" -section. We'll "create a new RDS database", choose MySQL, set a master username and password, and go ahead an create the database. This operation can take a while to complete. + +image::img/aws-eb-mysql.png[Creating a database] + +== Enabling Production Mode +Once the database is up-and-running, we'll configure our application to use `application.production.properties`, which will enable productionMode and take the production database into use. Go to "Software Configuration" on the "Configuration" screen. You want to set the following in "Environment Properties": + +`spring.config.name=application.production` + +image::img/aws-eb-props.png[Use production mode properties] + +NOTE: The `spring.config.name` -property should not have the `.properties` extension. + +When you apply the change, your environment will be restarted with the new configuration. + +== Post Production +Once you have your application up-and-running with a production database, you might wonder how you can see the contents of your database. You can do this with the regular tools you use to connect to MySQL, but by default access is restricted; you need to modify your security realm. AWS provides a handy "My IP" shorthand; after applying, you should be able to connect to the database (note: Elastic Beanstalk uses the database name "ebdb" by default.) + +image::img/aws-eb-mysql2.png[Accessing the database remotely] + +You may also want to review server logs, especially if you run into problems. You can request and download (view) logs easily from the console: + +image::img/aws-eb-logs.png[Accessing the database remotely] + +There is a lot more you can do with AWS Elastic Beanstalk and Amazon Web Services in general, and fortunately the link:https://aws.amazon.com/documentation/elasticbeanstalk[official documentation] is very good. + +Here are some further topics you might want to review: + +* link:https://aws.amazon.com/answers/web-applications/aws-web-app-deployment-java/[Deploying Java web applications on AWS (starting point)] +* link:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Java.html[Working with Java (starting point)] +* link:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customdomains.html[Your domain name] +* link:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https.html[Configuring HTTPS] +* link:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.managing.db.html[Configuring databases] +* link:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3.html[EB CLI] diff --git a/articles/bakeryfw8/deploying-to-bluemix.asciidoc b/articles/bakeryfw8/deploying-to-bluemix.asciidoc new file mode 100644 index 0000000000..866541dbc8 --- /dev/null +++ b/articles/bakeryfw8/deploying-to-bluemix.asciidoc @@ -0,0 +1,113 @@ +--- +title: Going to production with Java EE & Bluemix +order: 8 +layout: page +--- + += Going to production with Java EE & Bluemix +There are many options when looking to deploy your application for production, ranging from in-house to cloud-based solutions. + +In the following we'll take a look at how to deploy the JavaEE version to IBM Bluemix. + +Bluemix is a cloud platform as a service based on Cloud Foundry technology. It hides a lot of the complexity with provisioning, load balancing, scaling etc, since you do not have to deal with each of these individually. You can still take full control of the individual services, if you have specific needs, or as your application grows. + +== Getting a Bluemix account + +In order to use Bluemix, you need to have a Bluemix account. Head over to https://console.bluemix.net/ to read more about he service, and create an account. + +TIP: These deployment instructions are based on a free 30-day account for Bluemix, meant to test it out. For a real deployment, you should get a real account. + +== Configuring Vaadin for Production +The provided `manifest.yml` file will automatically set your Vaadin application to run in production mode by specifying `-Dvaadin.productionMode=true` for the server. + +== Configuring a Production Database +The database configuration is defined in `src/main/resources/META-INF/persistence.xml`. By default, the application uses a JTA data source named `BakeryDS` and looks it up through standard JNDI. There is no need to change this as long as you create a database using the same identifier in Bluemix (see below). + +What you need to change to avoid dropping and re-creating your production database on each redeploy, is to remove +``` + +``` +from `persistence.xml`. + +TIP: If you are just testing deployment to Bluemix, leave the `schema-generation.database.action` there for the first deploy to get initial data into the database. Remember to remove it afterwards. + +== Preparing a production WAR +Bluemix does not provide an SLF4J implementation. Uncomment the dependency to `slf4j-simple` in `pom.xml` to make sure you see all the log messages. + +Run +``` +mvn install +``` +to build and package the application into a `.war` -file (it will be placed in the `target` folder). + +== Preparing your Bluemix Account +When you log in to https://console.bluemix.net for the first time, you will be asked to create an organization for your account. + +To be able to use the instructions in this document, create an organization in the "US South" region. The name of the organization can be anything. Once you created an organization, create a "space" inside the organization and name it "dev". + +Once the organization and space is created, we can use the command line tools to setup and deploy the application. + +First, download the Cloud Foundry command line tools based on the instructions in https://github.com/cloudfoundry/cli#downloads. + +Once the command line tools are installed, define the Bluemix API endpoint to use for deployment: +``` +cf api https://api.ng.bluemix.net +``` + +NOTE: If you chose another region than "US South", you need to use the corresponding API endpoint. + +We then need to authenticate to Bluemix using our credentials: +``` +cf login +``` + +TIP: If you get a message about "No org or space targeted, use 'cf target -o ORG -s SPACE'" it might be that you have created the space in another region and did not change the API endpoint. Fix that before continuing. + +== Creating a database for production +Once the organization and space has been found, we can create a database to use: +``` +cf create-service elephantsql turtle BakeryDS +``` + +This will create a free (slow) PostgreSQL server to store the data. The application is already configured to use a data source named "BakeryDS", so the newly created database will automatically be used as long as you do not change the identifier. + +TIP: The `turtle` plan of ElephantSQL is run on a shared server and the size of the database is quite limited. For a real production deployment, you should consider a better plan (or another database). + +== Deploying the Application + +With everything set up, we can deploy the application using: +``` +cf push +``` + +TIP: If you get a message about "Server error, status code: 400, error code: 210003, message: The host is taken" you need to change the `name:` attribute in `manifest.yml`. The `name` attribute is used to determine the hostname of the application, e.g. `name.mybluemix.net` + +If all goes well, you should see something like +``` +0 of 1 instances running, 1 starting +1 of 1 instances running + +App started + +OK + +App mybakery was started using this command `.liberty/initial_startup.rb` +... +urls: app.mybluemix.net +``` +once the application has been deployed. + +Open the url in your browser to access the application (https://app.mybluemix.net, change `app` in the URL to whatever your application name is in the manifest). + +TIP: If all does not go well, run `cf logs mybakery` to see the deployment logs for the application. It might just be something which is slower than usual. Try waiting for a while longer or re-reun the `cf push` command. + +NOTE: When running in production mode, the application will by default create the database and add only an `admin@vaadin.com` user and nothing else. + +== Post Production +Once you have your application up-and-running with a production database, you might wonder how you can see the contents of your database. You can do this through the Bluemix console at https://console.bluemix.net/. Click on the `BakeryDS` service and then open the `ElephantSQL` dashboard. This will show you the URL to the database together with username and password. It will also allow you to browser the DB using the `BROWSER` tab. + +image::img/bluemix-query-users.png[Querying the database] + +If you want to review logs in the browser, they are also available through https://console.bluemix.net/ -> select your Cloud Foundry app -> select `Logs` + +There is a lot more you can do with Bluemix, and fortunately the link:https://console.bluemix.net/docs/[official documentation] is quite comprehensive. diff --git a/articles/bakeryfw8/img/about-in-menu.png b/articles/bakeryfw8/img/about-in-menu.png new file mode 100644 index 0000000000..b43ef0f688 Binary files /dev/null and b/articles/bakeryfw8/img/about-in-menu.png differ diff --git a/articles/bakeryfw8/img/about-to-menu-designer.png b/articles/bakeryfw8/img/about-to-menu-designer.png new file mode 100644 index 0000000000..e231a30eac Binary files /dev/null and b/articles/bakeryfw8/img/about-to-menu-designer.png differ diff --git a/articles/bakeryfw8/img/about-view-not-in-menu.png b/articles/bakeryfw8/img/about-view-not-in-menu.png new file mode 100644 index 0000000000..393e8b35f0 Binary files /dev/null and b/articles/bakeryfw8/img/about-view-not-in-menu.png differ diff --git a/articles/bakeryfw8/img/add-to-homescreen.png b/articles/bakeryfw8/img/add-to-homescreen.png new file mode 100644 index 0000000000..b1d8a04be8 Binary files /dev/null and b/articles/bakeryfw8/img/add-to-homescreen.png differ diff --git a/articles/bakeryfw8/img/architecture-diagram-javaee.png b/articles/bakeryfw8/img/architecture-diagram-javaee.png new file mode 100644 index 0000000000..eaf647c298 Binary files /dev/null and b/articles/bakeryfw8/img/architecture-diagram-javaee.png differ diff --git a/articles/guide/starter/bakeryflow/img/architecture-diagram.png b/articles/bakeryfw8/img/architecture-diagram-spring.png similarity index 100% rename from articles/guide/starter/bakeryflow/img/architecture-diagram.png rename to articles/bakeryfw8/img/architecture-diagram-spring.png diff --git a/articles/bakeryfw8/img/aws-eb-create.png b/articles/bakeryfw8/img/aws-eb-create.png new file mode 100644 index 0000000000..7a396fd052 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-create.png differ diff --git a/articles/bakeryfw8/img/aws-eb-logs.png b/articles/bakeryfw8/img/aws-eb-logs.png new file mode 100644 index 0000000000..aa46b04fb3 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-logs.png differ diff --git a/articles/bakeryfw8/img/aws-eb-mysql.png b/articles/bakeryfw8/img/aws-eb-mysql.png new file mode 100644 index 0000000000..4008aae521 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-mysql.png differ diff --git a/articles/bakeryfw8/img/aws-eb-mysql2.png b/articles/bakeryfw8/img/aws-eb-mysql2.png new file mode 100644 index 0000000000..b366406a05 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-mysql2.png differ diff --git a/articles/bakeryfw8/img/aws-eb-props.png b/articles/bakeryfw8/img/aws-eb-props.png new file mode 100644 index 0000000000..02e11d0a95 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-props.png differ diff --git a/articles/bakeryfw8/img/aws-eb-running.png b/articles/bakeryfw8/img/aws-eb-running.png new file mode 100644 index 0000000000..c409d13735 Binary files /dev/null and b/articles/bakeryfw8/img/aws-eb-running.png differ diff --git a/articles/bakeryfw8/img/bakery-crud.png b/articles/bakeryfw8/img/bakery-crud.png new file mode 100644 index 0000000000..714212ecf2 Binary files /dev/null and b/articles/bakeryfw8/img/bakery-crud.png differ diff --git a/articles/bakeryfw8/img/bakery-dashboard.png b/articles/bakeryfw8/img/bakery-dashboard.png new file mode 100644 index 0000000000..b83adcda86 Binary files /dev/null and b/articles/bakeryfw8/img/bakery-dashboard.png differ diff --git a/articles/bakeryfw8/img/bakery-login.png b/articles/bakeryfw8/img/bakery-login.png new file mode 100644 index 0000000000..476fd37ac1 Binary files /dev/null and b/articles/bakeryfw8/img/bakery-login.png differ diff --git a/articles/bakeryfw8/img/bakery-mobile.png b/articles/bakeryfw8/img/bakery-mobile.png new file mode 100644 index 0000000000..b18ce2395f Binary files /dev/null and b/articles/bakeryfw8/img/bakery-mobile.png differ diff --git a/articles/bakeryfw8/img/bluemix-query-users.png b/articles/bakeryfw8/img/bluemix-query-users.png new file mode 100644 index 0000000000..2f8f4aa08b Binary files /dev/null and b/articles/bakeryfw8/img/bluemix-query-users.png differ diff --git a/articles/bakeryfw8/img/chrome-favicon.png b/articles/bakeryfw8/img/chrome-favicon.png new file mode 100644 index 0000000000..a8962da80e Binary files /dev/null and b/articles/bakeryfw8/img/chrome-favicon.png differ diff --git a/articles/bakeryfw8/img/dark-gray-bakery.png b/articles/bakeryfw8/img/dark-gray-bakery.png new file mode 100644 index 0000000000..7cf1413de4 Binary files /dev/null and b/articles/bakeryfw8/img/dark-gray-bakery.png differ diff --git a/articles/bakeryfw8/img/new-design.png b/articles/bakeryfw8/img/new-design.png new file mode 100644 index 0000000000..f85f6665d4 Binary files /dev/null and b/articles/bakeryfw8/img/new-design.png differ diff --git a/articles/bakeryfw8/img/on-homescreen.png b/articles/bakeryfw8/img/on-homescreen.png new file mode 100644 index 0000000000..64ff579da0 Binary files /dev/null and b/articles/bakeryfw8/img/on-homescreen.png differ diff --git a/articles/bakeryfw8/img/overview.png b/articles/bakeryfw8/img/overview.png new file mode 100644 index 0000000000..2384ae733b Binary files /dev/null and b/articles/bakeryfw8/img/overview.png differ diff --git a/articles/bakeryfw8/index.asciidoc b/articles/bakeryfw8/index.asciidoc new file mode 100644 index 0000000000..33b99a0a88 --- /dev/null +++ b/articles/bakeryfw8/index.asciidoc @@ -0,0 +1,5 @@ +--- +title: Bakery App Starter +order: 7 +--- + diff --git a/articles/bakeryfw8/overview.asciidoc b/articles/bakeryfw8/overview.asciidoc new file mode 100644 index 0000000000..1b7d075a2c --- /dev/null +++ b/articles/bakeryfw8/overview.asciidoc @@ -0,0 +1,98 @@ +--- +title: Overview +order: 1 +layout: page +--- + += Bakery App Starter for FW8 and Spring/JavaEE + +Bakery is an App Starter to give you a head start building your business application based on Vaadin Framework 8 and Spring or JavaEE. + +It includes an end-to-end technology stack covering each layer that is needed to build a production grade application. The App Starter is opinionated and reflects Vaadin's view on what is the best way to build business applications. + +image::img/overview.png[Bakery on different devices,250,align=center] + +== Features + +=== Full stack architecture +Bakery architecture is built to give a full opinionated working stack with all the technologies changed out. Every project has however their own needs and each stack doesn't fit in to every project. If the default stack is not a perfect fit for your needs, you can switch out the technologies to match your requirements better. + +There are two versions of the app starter: One based on Spring and one based on JavaEE. + +The Spring version uses Spring Data to take care of the database, Spring Security to manage authentication and authorization and Spring boot to help in packaging, configuring and running. It runs in any Servlet 3.1 compatible server. + +The JavaEE version uses JPA 2.1 + Deltaspike Data to take care of the database, Shiro to manage authentication and authorization. It has been verified using Wildfly 10, TomEE 7 Plume and WebSphere Liberty but should run on any JavaEE7 compatible server with JPA 2.1 support. + +[NOTE] +TomEE 7.0.3 WebProfile and TomEE 7.0.3 plus (newest version at time of writing) ship with JPA 2.0 although it otherwise supports JavaEE7. You need to use the Plume version. + +Both versions uses an H2 database so that you can run the software directly with zero configuration and it can easily be replaced for your production database. Vaadin Designer has been used to build all UIs and the application is tested with Vaadin TestBench. Gatling, along with TestBench is used to perform scalability tests on the system. + +.Architecture diagram for Spring +image::img/architecture-diagram-spring.png[Spring Architecture diagram] + +.Architecture diagram for JavaEE +image::img/architecture-diagram-javaee.png[JavaEE Architecture diagram] + +=== Declarative, mobile-first views + +Views are built with Vaadin Framework 8 with the help of Vaadin Designer. Each view is built responsively, mobile-first. Vaadin Designer enables you to build the views visually and in a very fast and productive way. The views that are bundled show paradigms on how to create certain types of view and serve as bases for your own views. + +.Bakery Mobile view +image::img/bakery-mobile.png[Bakery Mobile view,250,align=center] + +=== CRUD views + +They go with multiple names. Create-Read-Update-Delete, Master-Detail. Updating data is at the core of many business applications. Bakery includes two examples of CRUD views where you can maintain the data. + +.Bakery CRUD view +image::img/bakery-crud.png[Bakery CRUD view] + +=== Dashboard with Charts + +A dashboard view is included to give the user an overview of the data in the application in one glance. Customize the widgets to show the data that is relevant to your users and give them indications on events that they should react to. Vaadin Board is used to layout the dashboard and Vaadin Charts visualizes the data. + +.Bakery Dashboard view +image::img/bakery-dashboard.png[Bakery Dashboard view] + + +=== Authentication and authorization + +The application is protected with user login to keep your sensitive data safe. Users can have different roles defined in the application which defines what they can do within the application. + +In the Spring version, the authentication and authorization is built on top of Spring Security. In the JavaEE version, Shiro is used for the same purpose. Both offer you many extensions points so you can configure it the way you handle security in your company. + +.Bakery Login screen +image::img/bakery-login.png[Bakery Login screen] + +=== Tested + +Integration tests are built on the application with the help of Vaadin TestBench. We content that you don't break functionality of the application why developing by maintaining and running the tests while developing. Running tests can be set up to happen on an integration server along with every commit. + +=== Scalable + +The application includes a scalability setup for testing how your application scales to multiple users. + +We have tested the application's performance. Download the https://v.vaadin.com/hubfs/Bakery%20app%20starter/full-stack-starter-bakery-fw8-spring-scalability-report.pdf[scalability report] to find out closer how many end users you can serve. + +=== Service layer + +Views contact a service layer which separates the UI layer from the business logic layer. The Service layer is divided to Services which is the contact point for the UI layer, and repositories that communicate with the database. + +=== Maven + +Dependency management and building is handled by Maven and the standardized Maven conventions help working in the industry-proven way. + + +== Getting started + +A personalized project can be link:https://vaadin.com/docs/v8/framework/getting-started/getting-started-archetypes[created from Maven Archetypes] by giving group id, artifact id and developer name. + +NOTE: A paid _Pro or Prime subscription is required_ for creating a new software project from a Starter template. After its creation, results can be used, developed and distributed freely, but licenses for the used commercial components are required during development. The Starter or its parts cannot be redistributed as a code example or template. For full terms, see the link:https://vaadin.com/license/cvtl-1[Commercial Vaadin Template License.] + +See more information on setting up your environment in <>. + +=== Software needed + +* Java JDK 1.8 or higher +* Maven is required for building, running and packaging the Software diff --git a/articles/bakeryfw8/running-building-packaging.asciidoc b/articles/bakeryfw8/running-building-packaging.asciidoc new file mode 100644 index 0000000000..ab6b5e86fe --- /dev/null +++ b/articles/bakeryfw8/running-building-packaging.asciidoc @@ -0,0 +1,22 @@ +--- +title: Running, building and packaging +order: 2 +layout: page +--- + += Running, building and packaging. + +== Running the first time +After downloading and extracting the zip package, it is recommended to run the software once and see that it is working. + +To start the Spring version, run `mvn spring-boot:run` from the terminal or your IDE. + +To start the JavaEE version, run `mvn wildfly:run` from the terminal or your IDE. + +== Building the package +To build the project, the standard `mvn install` command can be used. This will produce a deployable, self containing jar in the target package + +== Running integration tests +Integration tests are run with the `mvn verify -Pit` command. + +UI tests can take a while to run, so the integration tests are in a separate `it` profile, to provide a little bit more flexibility. diff --git a/articles/bakeryfw8/theming.asciidoc b/articles/bakeryfw8/theming.asciidoc new file mode 100644 index 0000000000..230ca31ec3 --- /dev/null +++ b/articles/bakeryfw8/theming.asciidoc @@ -0,0 +1,175 @@ +--- +title: Theming, styling, look and feel +order: 5 +layout: page +--- + += Theming, styling, look and feel + +This chapter covers how to adjust the visual look of your application, including styles, icons, homescreen icons, and some other customisations for mobile. + +It should be noted up-front that the application comes with two parts that need to be styled separately: 1) `login.html` which has minimal CSS defining the look of the login screen, and 2) the actual application which has a visual theme built with SCSS (https://sass-lang.com/) using the customizable Valo theme engine (https://vaadin.com/docs/v8/framework/themes/themes-valo). + +TIP: More information about theming Vaadin applications: +https://vaadin.com/docs/v8/framework/themes/themes-overview + +== Tools +Various editors have support for SCSS, and you can use any editor you like, but notice that the IDE might need a nudge (refresh) once you're done editing the theme. + +To get better integration with the IDE, you can also install a plug-in, e.g _LiClipseText_ - recent Eclipse versions will notify that there are editors available to install. You can also use Eclipse’s built-in CSS or plain-text editors. + +If your IDE is set up to auto-redeploy resources, you'll see the changes in your application after a browser reload. + +TIP: If you're using _Vaadin Designer_, it will notice changes to the theme and live-update the design to match, including any external previews you have open. This is a convenient way to style, allowing you to preview multiple sizes at once. + +=== Compiling +If you delete the pre-compiled `styles.css`, the application will auto-update the theme during development. + +TIP: If your theme stops auto-updating, check if you inadvertently compiled the theme and now have a styles.css + +However, when deploying the application, you should make sure you have a compiled and up-to-date styles.css. +---- +mvn vaadin:compile-theme +---- + +Please not that if you use an IDE, such as Eclipse, but edit files with an external editor (e.g Atom to edit SCSS), or use the command-line, you might have to 'refresh' your project (or the relevant folders) for your IDE to notice the changes. + +TIP: More information about compiling the theme: +https://vaadin.com/docs/v8/framework/themes/themes-compiling + +== Styling the login screen +The login screen is defined in the stand-alone `login.html` file. It has a pretty simple DOM structure, which can still support multiple screen sizes and layouts. The included CSS makes the button and fields approximate the style of the application, and defines some responsive behaviour; on narrow screens the layout is simple, but on wider screens there is a styled box in the center of the screen, floating over a background image. + +image::img/bakery-login.png[The login screen] + +The main color +++#4b4b65+++ is set as background-color in a few places and can easily be replaced. + +The background-image is defined in one breakpoint, for screens wider than 1000px. As a result, it will not be loaded on smaller screen sizes. +Additionally, a gradient is used to approximate the look of the background image on smaller devices to make the application immediately recognisable. + +You can modify the background-image or gradient, or remove them entirely: +---- +@media (min-width: 1000px) { + html { + background: linear-gradient(145deg, #484962 30%, #d06b41 100%); + } + body { + background-color: transparent; + background-image: url(VAADIN/themes/apptheme/bg.jpg); + background-size: cover; + } +} +---- + +== Styling the application + +The application theme consists of a number of SCSS-files that are compiled into one CSS file. The different files are described below. + +=== styles.scss +This is the theme “entrypoint” that should generally not be touched. If you compile the theme manually, this is the file you want to compile. + +=== styles.css +This is the compiled CSS version of the application theme, to be directly used by the application. Note that if your project contains this file, no auto-compilation of the theme will take place, and you'll have to trigger a compile after modifying the theme. I.e you might not want to have this file while developing, but you definately need this file when going to production. + +=== addons.scss +This file contains styles imported from addons, if any. There is usually no need to touch this, except to check what styles an add-on might have out-of-the-box. + +=== designs.scss +Here you can find styles imported from Vaadin Designer templates. + +For clarity, it’s recommended not to modify these, and override things in your own theme files instead. +However, this is just a guiding principle - as long as you don’t delete the “// Styles imported from xyz” comment, your modifications will not be overridden. + +=== apptheme.scss +*This is you main theme file*. Here, you configure Valo parameters, as well as set up any global variable you might want to use in your application theme. You also import and include the various sub-parts of your theme. + +In applications with really limited styling, you might just have one apptheme.scss, but usually it makes sense to split things. As a rule of thumb, put each independent part (view, component) that requires some amount of styling in its own file. + +The scss files specific to this project start with underscore, and the name indicates the scope of the file. Each file consists of a mixin, that is then included in the appropriate place within apptheme.scss. + +==== Adjusting Valo parameters +Various aspects of the theme can be easily adjusted by changing parameters. A number of these are listed in the beginning of apptheme.scss. + +For instance, the menu-bar gets it's color from the v-focus-color, in effect acting as a sort of main color for the theme: +---- +$v-focus-color: #333; +---- +To see the effect, you can disable the background-gradient and -image: +---- +$app-background-gradient: false; +$app-background-image: false; +---- +You now have a dark-gray application without background image or gradient. + +image::img/dark-gray-bakery.png[Dark-gray Bakery] + +=== _dashboardview.scss +Styles for the Dashboard, which is implemented using _Vaadin Board_ and _Vaadin Charts_. + +TIP: A good starting point for styling Vaadin Charts can be found here: https://vaadin.com/blog/styling-your-vaadin-charts + +The main things done here is 1) joining the first row into a joint “panel”, while the other rows’ content is styled as separate panels 2) making sure padding and spacing follows Valo parameters. + +There is one responsive breakpoint, which reduces spacing and removes side-margins on narrow devices. + +=== _menu.scss +Styles for the responsive menu. + +Because it’s responsive, styles for different screen-sizes appear in separate sections. Notice that Vaadin responsiveness works with regard to the parent element (as opposed to the browser size), so that components can adjust based on the space available to them, regardless of window/device size. + +A responsive selector looks like this: +---- +.app-shell[width-range~="-600px”] { … } +---- + +In this case, the rules within the block will take effect when the element with the _app-shell_ class is up to 600px wide. + +You can remove all styles in __menu.scss_ and still have a decent-looking application, as it is based on a Vaadin Designer template. + +=== _ordersgrid.scss +Styles for the grid that lists all orders, including the filters. + +Most of the styling here applyes different colors and icons to depending on the order’s status. + +=== _ordersview.scss +Styles for the form that is used to input new orders, as well as display the details of the existing orders. + +This particular view shows how to do a responsive layout “from scratch”, using mostly CSSLayouts and laying things out in CSS. This is a good approach if 1) you have a fairly small view, 2) specific behaviour in mind. + +This particular view is set up so that fields (or a group of related fields) basically split the view in half, but on small devices the fields take up the whole width. It’s worth considering using _Vaadin Board_ to achieve a similar effect - it can be seen in action on the dashboard view. + +Note that _ProductInfo_ is a separate component (defined in _ProductInfoDesign_) within the OrderEditView which uses the same responsive styles. + +== Icons, logos and viewport configuration + +=== Favicon +There is a favicon.ico which can be replaced; it will show up in the browser tab, bookmarks, and such, depending on the browser used. + +image::img/chrome-favicon.png[Chrome displaying a favicon] + +=== Homescreen icons +The theme also contains two sizes of application icons; these are also used as logo on the login-screen, but the main use case is to be used as “homescreen” icons when added to the homescreen of a device. You can either just replace these two icons, or if you want to add different sized icons, or remove the icons altogheter, you can do so in `ApplicationServlet.IconBootstrapListener`. + +image::img/add-to-homescreen.png[Adding to iOS homescreen] + +image::img/on-homescreen.png[On iOS homescreen] + +=== Viewport configuration +Making the application work well on mobile devices of various sizes requires us to tell the device how we intend it to be shown. We can do this by adding a _@Viewport_ annotation to the _AppUI_ class. +---- + +---- +Applications that are built for mobile tend to give a more robust feel if zooming is turned off, but you might want to turn it back on, if your application contains content that the user might want to zoom. + +=== Full screen app +If you want your application to run full-screen - without any browser controls, just like a native app - you can add the _mobile-web-app-capable_ meta-tag. +---- + + +---- +There is commented code ready to be enabled in `ApplicationServlet.IconBootstrapListener` + +=== Don’t forget login.html +Remember that `login.html` is a stand-alone page, and has all the icons/viewport tags mentioned above added separately; please remember to update it as well. + +In fact, you might want to start customising by setting up `login.html` so that it works as you wish, then modify the Java code to match. diff --git a/articles/board/board-overview.asciidoc b/articles/board/board-overview.asciidoc new file mode 100644 index 0000000000..275fd7688d --- /dev/null +++ b/articles/board/board-overview.asciidoc @@ -0,0 +1,22 @@ +--- +title: Overview +order: 1 +layout: page +--- + +[[board.overview]] += Board + +The [elementname]#vaadin-board# is a Polymer element for creating flexible responsive layouts and building nice looking dashboards. +The [elementname]#vaadin-board# key feature is how it effectively reorders the widgets on different screen sizes, maximizing the use of space and looking stunning. +Vaadin Board is using link:https://github.com/polymer/polymer/tree/2.0-preview[Polymer 2]. + +[[board.features]] += Features + +- Four and three columns based layout for laying out things the way you like it. +- Responsive design, works on all screen sizes, it rearranges child elements based on available space. +- Element responsiveness. Not only is the component itself responsive, but each row reacts individually to the space given to it in a responsive way. +- Allows to divide your layout into regions by using vaadin-board-row. +- `board-cols` attribute makes one widget flow over multiple slots. This way you can build row configurations where for example you have one widget that takes 75% of the space and another that takes 25%, 25-50-25 or 33-67. +- Supports nested regions. You can put a new row within another row to build how ever complex layouts that you want in a simple way. diff --git a/articles/board/index.asciidoc b/articles/board/index.asciidoc new file mode 100644 index 0000000000..b3a120965b --- /dev/null +++ b/articles/board/index.asciidoc @@ -0,0 +1,5 @@ +--- +title: Board +order: 6 +--- + diff --git a/articles/board/java-api/basic-use.asciidoc b/articles/board/java-api/basic-use.asciidoc new file mode 100644 index 0000000000..bf70d3d6c2 --- /dev/null +++ b/articles/board/java-api/basic-use.asciidoc @@ -0,0 +1,115 @@ +--- +title: Basic Use +order: 3 +layout: page +--- + +[[board.basic-use]] += Basic Use + +The [classname]#Board# is a responsive layout, where you can add any Vaadin component. +This chapter assumes you have already added Vaadin Board to your project and installed the license key. +If not, check the instructions in <>. + +[[board.basic-use.configuration]] +== Basic Configuration + +[classname]#Board# is divided into rows, using [classname]#Row# class. +Rows are divided into columns. +You can put any Vaadin component inside the [classname]#Row#. +Every element inside the row can take from one to four columns. +Vaadin Board rearranges child elements based on available space. +In the example below every child [classname]#Label# will use 25% on Desktop, but will be +rearranged to two rows when switching to tablet: both with 2 items that take 50% of available space each, see example below. + +[source, java] +---- + Board board = new Board(); + board.setSizeFull(); + + Label lbl1 = new Label("LABEL1"); + Label lbl2 = new Label("LABEL2"); + Label lbl3 = new Label("LABEL3"); + Label lbl4 = new Label("LABEL4"); + + board.addRow(lbl1, lbl2, lbl3, lbl4); + setContent(board); +---- +[NOTE] +Setting height for the row is not supported. Set height for the child components. +[NOTE] +With IE11 if you want to have a border for the direct child of the [classname]#Row# you need to create a wrapper HTML element +and add a border there, but not to the direct child of the [classname]#Row#. + +[NOTE] +For a few components you should not use relative height, but set height of the component in pixels or leave it undefined height. This affects Grid, Tree, TreeGrid, GridLayout and Spreadsheet. + +[NOTE] +Vaadin TabSheet does not resize correctly, when changing from a small viewport size to a big one. Wrapping TabSheet inside the CSSLayout fixes the problem + +You can specify the element to occupy from one to four columns, by using [methodname]#setComponentSpan()#: + +[source, java] +---- + Board board = new Board(); + board.setSizeFull(); + + Label lbl1 = new Label("LABEL1"); + Label lbl2 = new Label("LABEL2"); + Label lbl3 = new Label("LABEL3"); + + Row row = board.addRow(lbl1, lbl2, lbl3); + // specify first component to use + // 2 columns + row.setComponentSpan(lbl1, 2); + setContent(board); +---- + +[NOTE] +By default, mobile browsers have fixed viewport size. +Set the viewport size to follow the screen-width of the device by adding the [classname]#@Viewport# annotation to the UI class: + +[source, java] +---- +@Viewport("width=device-width") +public class MyUI extends UI { +---- + + +[[board.basic-use.styling]] +== Styling + +Vaadin Board rearranges elements in your layout based on available space. +In some cases you want to use different styles depending on how the elements are laid out, e.g. use smaller font size for mobile devices. +Vaadin Board has three predefined class selectors for [classname]#vaadin-board-row#: + +* small - for rows smaller than 600 pixels. +* middle - for rows between 600 and 969 pixels. +* large - for rows bigger than 960 pixels. + +[source, java] +---- + Board board = new Board(); + board.setSizeFull(); + + Label lbl1 = new Label("LABEL1"); + Label lbl2 = new Label("LABEL2"); + Label lbl3 = new Label("LABEL3"); + + board.addRow(lbl1, lbl2, lbl3); + setContent(board); +---- + +[source, css] +---- +vaadin-board-row.large .v-label { + font-weight: bold; + font-size: 28px; +} +vaadin-board-row.medium .v-label { + font-weight: normal; + font-size: 18px; +} +---- + +After adding this CSS to your theme you will see that labels have different font-size for different viewport size. diff --git a/articles/board/java-api/getting-started.asciidoc b/articles/board/java-api/getting-started.asciidoc new file mode 100644 index 0000000000..8c7c67d5f5 --- /dev/null +++ b/articles/board/java-api/getting-started.asciidoc @@ -0,0 +1,194 @@ +--- +title: Getting Started +order: 1 +layout: page +--- + +[[board.introduction]] += Getting Started + +NOTE: Vaadin Board is only available for Vaadin Framework 8.1 and newer. + +In this chapter, we are going to create a simple Vaadin application and use the Vaadin Board add-on to create a responsive layout. + +[[board.prerequisites]] +== Prerequisites + +In order to follow this tutorial, you will need the following tools/setup: + +* Command line Maven +* JDK installed +* IDE (optional) + +[[board.project-setup]] +== Project setup + +To start off, we need to create a new project where we can use Vaadin Board. +We will use Maven to set up a project, which can later be imported into your favorite IDE. +You can also use your IDE to generate a new maven project using the `vaadin-archetype-application archetype`, version 8.1.0. +Execute the following command to create the project: + +[subs="normal"] +---- +mvn archetype:generate \ + -DarchetypeGroupId=com.vaadin \ + -DarchetypeArtifactId=vaadin-archetype-application \ + -DarchetypeVersion=8.1.0 +---- + +You will be asked a few questions for setting up the project. +In the following, the suitable answers are given for going through this quickstart: + +[subs="normal"] +---- +Define value for property 'groupId': : [replaceable]#com.vaadin# +Define value for property 'artifactId': : [replaceable]#getting-started# +Define value for property 'version': 1.0-SNAPSHOT: : [replaceable]## +Define value for property 'package': com.vaadin: : [replaceable]## +[INFO] Using property: themeName = mytheme +[INFO] Using property: uiName = MyUI +[INFO] Using property: widgetsetName = MyAppWidgetset +Confirm properties configuration: +groupId: com.vaadin +artifactId: spreadsheet-quickstart +version: 1.0-SNAPSHOT +package: com.vaadin +themeName: mytheme +uiName: MyUI +widgetsetName: MyAppWidgetset +Y: : [replaceable]## +---- + +Now you should have a generated project in a directory that you specified its name after the `artifactId`, for example, `getting-started`. +You can run the new project by issuing the following commands: + +[subs="normal"] +---- +[command]#cd# getting-started +[command]#mvn# jetty:run +---- + +The latter command will compile all sources and start a local web server. +Wait until it prints out “Started Jetty Server” and navigate to http://localhost:8080 using your favorite browser. + +In your browser, you should see a [guibutton]#Click Me# button. +When you click it, the text “Thank you for clicking” should appear below it. +Great, the application works! +We can now move on to replace this button with a Vaadin Board! +Stop the web server by pressing kbd:[Ctrl+C] in the window where you started it. + +Let us first add the Vaadin Board dependency to the project and compile the widget set. +Open the [filename]#pom.xml# file and find the [elementname]#dependencies# tag. +Add the following dependency declaration just before the end tag ([elementname]#/dependencies#): + +[subs="normal"] +---- +... + * + com.vaadin + vaadin-board + 1.1.0 + * + +... +---- + +It is recommended to use the latest version available, the version number can be checked at link:https://vaadin.com/directory#!addon/vaadin-board[Vaadin Directory]. + +After this, we need to fetch a license for Vaadin Board in order to be able to compile the widget set. +You can get a free trial key from link:https://vaadin.com/directory#!addon/vaadin-board[Vaadin Directory]. +Click the large orange “Free trial key” button to the right and copy and paste the key into a file named [literal]#.vaadin.board.developer.license# in your link:https://en.wikipedia.org/wiki/Home_directory#Default_home_directory_per_operating_system[home directory]. + +Now we have created a new project, added the Vaadin Board add-on to it and can move on to create our layout. + + + +[[board.creating]] += Creating your first Board + +Go to [classname]`MyUI` class and replace [methodname]`init` method with the following one: + +[source, java] +---- + protected void init(VaadinRequest request) { + Board board = new Board(); + board.setSizeFull(); + Label lbl1 = createLabel("LABEL1"); + Label lbl2 = createLabel("LABEL2"); + Label lbl3 = createLabel("LABEL3"); + Label lbl4 = createLabel("LABEL4"); + + board.addRow(lbl1, lbl2, lbl3, lbl4); + setContent(board); + } + private Label createLabel(String content) { + Label label = new Label(content); + label.setSizeFull(); + label.addStyleName(ValoTheme.LABEL_H1); + label.addStyleName("mystyle"); + return label; + } +---- + + +[classname]`Board` is divided into rows, using [classname]`Row`. +Rows are divided into columns. +You can put any Vaadin Component inside the [classname]`Row`. +Every element inside the row can take from one to four columns. +Vaadin Board rearranges child elements based on available space. + +In the example below every label will use 25% on Desktop, but will be +rearranged to two rows when switching to tablet: one row with 2 items 50% of available space each and second row +with 100% width item. + +Then we can add styling to our content. Insert the following CSS to your theme, inside the mytheme.scss file: + +[source,html] +---- + .v-label.mystyle { + display: block; + margin-left: 0; + margin-right: 0; + font-weight: bold; + border-style: solid; + border-width: 5px; + border-color: #fff; + text-align: center; + background-color: #cacaca; + } +---- + +[NOTE] +By default, mobile browsers have fixed viewport size. +Set the viewport size to follow the screen-width of the device by adding the [classname]#@Viewport# annotation to the UI class: + +[source, java] +---- +@Viewport("width=device-width") +public class MyUI extends UI { +---- + +Start your server to see the result: + +[subs="normal"] +---- +[command]#mvn# jetty:run +---- + +[[getting-started-configuration-desktop]] +.Vaadin Board Basic Configuration on desktop +image::img/board-getting-started-configuration-desktop.png[] + +Vaadin Board rearranges child elements based on viewport size. +You can change the size of the Web browser window to see how your application will look on different devices. + +[[figure.getting-started-configuration-tablet]] +.Vaadin Board Basic Configuration on tablet +image::img/getting-started-configuration-tablet.png[] + +[[figure.getting-started-configuration-mobile]] +.Vaadin Board Basic Configuration on mobile +image::img/getting-started-configuration-mobile.png[] + +Congratulations! You have your first Vaadin Board setup. +Continue with link:https://vaadin.com/docs/-/part/board/board-overview.html[docs] and visit our link:https://demo.vaadin.com/vaadin-board[demos] for more information. diff --git a/articles/board/java-api/img/board-getting-started-configuration-desktop.png b/articles/board/java-api/img/board-getting-started-configuration-desktop.png new file mode 100644 index 0000000000..d185627242 Binary files /dev/null and b/articles/board/java-api/img/board-getting-started-configuration-desktop.png differ diff --git a/articles/board/java-api/img/getting-started-configuration-mobile.png b/articles/board/java-api/img/getting-started-configuration-mobile.png new file mode 100644 index 0000000000..d0c1bd591e Binary files /dev/null and b/articles/board/java-api/img/getting-started-configuration-mobile.png differ diff --git a/articles/board/java-api/img/getting-started-configuration-tablet.png b/articles/board/java-api/img/getting-started-configuration-tablet.png new file mode 100644 index 0000000000..9673388564 Binary files /dev/null and b/articles/board/java-api/img/getting-started-configuration-tablet.png differ diff --git a/articles/board/java-api/img/nested-rows-basic-desktop.png b/articles/board/java-api/img/nested-rows-basic-desktop.png new file mode 100644 index 0000000000..f7067a764d Binary files /dev/null and b/articles/board/java-api/img/nested-rows-basic-desktop.png differ diff --git a/articles/board/java-api/img/nested-rows-basic-mobile.png b/articles/board/java-api/img/nested-rows-basic-mobile.png new file mode 100644 index 0000000000..7fd8e9e29e Binary files /dev/null and b/articles/board/java-api/img/nested-rows-basic-mobile.png differ diff --git a/articles/board/java-api/img/nested-rows-basic-tablet.png b/articles/board/java-api/img/nested-rows-basic-tablet.png new file mode 100644 index 0000000000..1d8ebc3cbd Binary files /dev/null and b/articles/board/java-api/img/nested-rows-basic-tablet.png differ diff --git a/articles/board/java-api/img/nested-rows-span-desktop.png b/articles/board/java-api/img/nested-rows-span-desktop.png new file mode 100644 index 0000000000..bda42d98b5 Binary files /dev/null and b/articles/board/java-api/img/nested-rows-span-desktop.png differ diff --git a/articles/board/java-api/img/nested-rows-span-mobile.png b/articles/board/java-api/img/nested-rows-span-mobile.png new file mode 100644 index 0000000000..beb501af8c Binary files /dev/null and b/articles/board/java-api/img/nested-rows-span-mobile.png differ diff --git a/articles/board/java-api/img/nested-rows-span-tablet.png b/articles/board/java-api/img/nested-rows-span-tablet.png new file mode 100644 index 0000000000..58e82a986c Binary files /dev/null and b/articles/board/java-api/img/nested-rows-span-tablet.png differ diff --git a/articles/ds/components/charts/java-api/index.asciidoc b/articles/board/java-api/index.asciidoc similarity index 100% rename from articles/ds/components/charts/java-api/index.asciidoc rename to articles/board/java-api/index.asciidoc diff --git a/articles/board/java-api/installing.asciidoc b/articles/board/java-api/installing.asciidoc new file mode 100644 index 0000000000..266adf123e --- /dev/null +++ b/articles/board/java-api/installing.asciidoc @@ -0,0 +1,133 @@ +--- +title: Installing Vaadin Board +order: 2 +layout: page +--- + +[[board.installing]] += Installing Vaadin Board + +NOTE: Vaadin Board is only available for Vaadin Framework 8.1 and newer. + +As with most Vaadin add-ons, you can install Vaadin Board as a Maven dependency in your project. +For general instructions on installing add-ons, please see +<>. + +Vaadin Board 1.1.0 requires Vaadin 8.1 or later. + +Using Vaadin Board requires a license key, which you must install before +compiling the widget set. The widget set must be compiled after setting up the +dependency or library JARs. + +[[board.installing.maven]] +== Maven Dependency + +The Maven dependency for Vaadin Board is as follows: + +[subs="normal"] +---- +<dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-board</artifactId> + <version>[replaceable]##1.1.0##</version> +</dependency> +---- +You also need to define the Vaadin add-ons repository if not already defined: + +[source,xml] +---- + + vaadin-addons + https://maven.vaadin.com/vaadin-addons + +---- + +[[board.installing.license]] +== Installing License Key + +You need to install a license key before compiling the widget set. The license +key is checked during widget set compilation, so you do not need it when +deploying the application. + +You can obtain a free trial key from the +link:https://vaadin.com/myaccount/licenses#classic[Vaadin Pro Licenses]. +You need to register in Vaadin Directory to get the key. + +To install the license key in a development workstation, you can copy and paste +it verbatim to a [filename]#.vaadin.board.developer.license# file in your home +directory. For example, in Linux and OS X: + +[subs="normal"] +[source,xml] +---- +[prompt]#$# [command]#echo# "[replaceable]##L1cen5e-c0de##" > [parameter]#~/.vaadin.board.developer.license# +---- +You can also pass the key as a system property to the widget set compiler, +usually with a [literal]#++-D++# option. For example, on the command-line: + +[subs="normal"] +[source,xml] +---- +[prompt]#$# [command]#java# -D[parameter]##vaadin.board.developer.license##=[replaceable]##L1cen5e-c0de## ... +---- +ifdef::web[] +See link:https://vaadin.com/docs/v8/framework/addons/addons-cval[the CVAL +license key installation instructions] for more details. +endif::web[] + +[[board.installing.license.environments]] +=== Passing License Key in Different Environments + +How you actually pass the parameter to the widget set compiler depends on the +development environment and the build system that you use to compile the widget +set. Below are listed a few typical environments: + +Eclipse IDE:: To install the license key for all projects, select "Window > Preferences" and +navigate to the "Java > Installed JREs" section. Select the JRE version that you +use for the application and click [guibutton]#Edit#. In the [guilabel]#Default +VM arguments#, give the [parameter]#-D# expression as shown above. + +Apache Ant:: If compiling the project with Apache Ant, you could set the key in the Ant +script as follows: + + ++ +[subs="normal"] +[source,xml] +---- +<sysproperty key="vaadin.board.developer.license" + value="**L1cen5e-c0de**"/> +---- ++ +However, you should never store license keys in a source repository, so if the +Ant script is stored in a source repository, you should pass the license key to +Ant as a property that you then use in the script for the value argument of the +[literal]#++++# as follows: + + ++ +[subs="normal"] +[source,xml] +---- +<sysproperty key="vaadin.board.developer.license" + value="**${vaadin.board.developer.license}**"/> +---- ++ +When invoking Ant from the command-line, you can pass the property with a +[parameter]#-D# parameter to Ant. + +Apache Maven:: If building the project with Apache Maven, you can pass the license key with a +[literal]#++-D++# parameter to Maven: + + ++ +[subs="normal"] +[source,xml] +---- +[prompt]#$# [command]#mvn# -D[parameter]##vaadin.board.developer.license##=[replaceable]##L1cen5e-c0de## package +---- +Continuous Integration Systems:: In CIS systems, you can pass the license key to build runners as a system +property in the build configuration. However, this only passes it to a runner. +As described above, Ant does not pass it to sub-processes implicitly, so you +need to forward it explicitly as described earlier. diff --git a/articles/board/java-api/nested-rows.asciidoc b/articles/board/java-api/nested-rows.asciidoc new file mode 100644 index 0000000000..b95d76aea8 --- /dev/null +++ b/articles/board/java-api/nested-rows.asciidoc @@ -0,0 +1,110 @@ +--- +title: Nested rows +order: 4 +layout: page +--- + +[[board.nested-rows]] += Nested Rows + +While building your board, sometimes you might want to add more components into one row. +To do that, Vaadin Board support nested regions so you can add a row inside another one and let Vaadin Board handle the work, thanks to its responsiveness capabilities. + +Here, we are going to show how to create nested rows and how they will help you. +This chapter assumes you have already added Vaadin Board to your project and installed the license key. +If not, check the instructions in <>. + +[[board.nested-rows.basic-usage]] +== Basic Usage + +For this example, we are going to create a row with 2 buttons and place it inside a outer row. + +[source, java] +---- + protected void init(VaadinRequest request) { + VerticalLayout container = new VerticalLayout(); + + Board board = new Board(); + + Button button1 = new Button("Button 1"); + Button button2 = new Button("Button 2"); + Button button3 = new Button("Button 3"); + Row outerRow = board.addRow(button1, button2, button3); + + Row nestedRow = new Row(); + Button inner1 = new Button("Inner 1"); + Button inner2 = new Button("Inner 2"); + nestedRow.addComponents(inner1, inner2); + + outerRow.addNestedRow(nestedRow); + + container.addComponent(board); + + setContent(container); + } +---- + +The result for different view port is the following: + +[[figure.basic-use-nested-desktop]] +.Nested rows on desktop +image::img/nested-rows-basic-desktop.png[] + +[[figure.basic-use-nested-tablet]] +.Nested rows on tablet +image::img/nested-rows-basic-tablet.png[] + +[[figure.basic-use-nested-mobile]] +.Nested rows on mobile +image::img/nested-rows-basic-mobile.png[] + +Also, you can opt to add `nestedRow` to `outerRow` either by calling `outerRow.addComponent(nestedRow)` (this is possible because `Row` is also a `Component`) or at `board.addRow(button1, button2, button3, nestedRow)`. + +[[board.nested-rows.component-span]] +== Component Span + +As any other component inside a row, the nested row can also be spanned to fill more than one column (keep in mind that the maximum number of columns for each row is 4). +Take this example, based on the previous one: + +[source, java] +---- + protected void init(VaadinRequest request) { + VerticalLayout container = new VerticalLayout(); + container.setMargin(true); + container.setSizeFull(); + + Board board = new Board(); + + Button button1 = new Button("Button 1"); + Button button2 = new Button("Button 2"); + Row outerRow = board.addRow(button1, button2); + + Row nestedRow = new Row(); + Button inner1 = new Button("Inner 1"); + Button inner2 = new Button("Inner 2"); + Button inner3 = new Button("Inner 3"); + Button inner4 = new Button("Inner 4"); + nestedRow.addComponents(inner1, inner2, inner3, inner4); + + outerRow.addNestedRow(nestedRow); + outerRow.setComponentSpan(nestedRow, 2); + + container.addComponent(board); + + setContent(container); + } +---- + +We are telling that `nestedRow` will fill 2 columns of the row. This example will produce the following result for each view port: + +[[figure.basic-use-nested-desktop]] +.Component span for nested rows on desktop +image::img/nested-rows-span-desktop.png[] + +[[figure.basic-use-nested-tablet]] +.Component span for nested rows on tablet +image::img/nested-rows-span-tablet.png[] + +[[figure.basic-use-nested-mobile]] +.Component span for nested rows on mobile +image::img/nested-rows-span-mobile.png[] diff --git a/articles/board/webcomponents-api/board-basic-use.asciidoc b/articles/board/webcomponents-api/board-basic-use.asciidoc new file mode 100644 index 0000000000..a3962b9a17 --- /dev/null +++ b/articles/board/webcomponents-api/board-basic-use.asciidoc @@ -0,0 +1,215 @@ +--- +title: Basic Use +order: 3 +layout: page +--- + +[[board.basic-use]] += Basic Use + +The [classname]#vaadin-board# is a regular web component, which you can add to a +web page. Vaadin Board is using link:https://github.com/polymer/polymer/tree/2.0-preview[Polymer 2]. + +[[board.install]] +== Install +You can use https://bower.io[Bower] to install Vaadin Board dependency by running the following command inside your project folder: + +[subs="normal"] +---- +[prompt]#$# [command]#bower# install --save vaadin-board +---- +Replace the version number with the most current one. + +Add html import: + +[source, html] +---- + + + + + + +---- +[[board.installing.license]] +== Installing a License Key +You need to install a license key in order to develop your application with Vaadin Board web component. + +You can purchase Vaadin Board or obtain a free trial key from the link:https://vaadin.com/myaccount/licenses#classic[Vaadin Licenses page]. +You need to register in the Vaadin website to obtain the key. + +When you first time open the web page with Vaadin Board, you will see a pop-up that asks you to enter the license key. +If the license is valid, it will be saved to the local storage of the browser and you will not see the pop-up again. The license dialog will only be shown in development environment when accessing the web page using localhost or 127.0.0.1. + +[[board.basic-use.configuration]] +== Basic Configuration + +[classname]#vaadin-board# is divided into rows, using [classname]#vaadin-board-row#. +Rows are divided into columns. +You can put any WebComponent or HTML element inside the [classname]#vaadin-board-row#. +Every element inside the row can take from one to four columns. +Based on available space, the vaadin board rearranges child elements based on available space. +In the example below every child [elementname]#div# will use 33% on Desktop, but will be +rearranged to two rows when switching to tablet: one row with 2 items 50% of available space each and second row +with 100% width item, see example below. + +[source, html] +---- + + +
1
+
2
+
3
+
+
+---- + +We can add styling to our content. Insert the following CSS , inside the [elementname]`style` tag: + +[source, html] +---- +.item { +   display: block; +   margin-left: 0; + margin-right: 0; + font-weight: bold; + border-style: solid; + border-width: 3px; + border-color: #fff; + text-align: center; + background-color: #cacaca; + height:200px; +} +---- + +[[figure.board.basic-use]] +.Vaadin Board Basic Configuration +image::img/board-basic-use.png[] + +You can use `board-cols` to specify the width of the inner element in columns: + +[source, html] +---- + + +
1
+
2
+
+
+---- + +[[figure.board.basic-use.board-cols]] +.Configure Row Width +image::img/board-basic-use-board-cols.png[] + +[NOTE] + +Elements inside a row will have overflow set to hidden by default, it can be overriden. + +[[board.basic-use.nested]] +== Nested Rows + +Vaadin Board allows to have nested rows. +Nested rows are responsive in relation to the parent slot size. + +[source, html] +---- + + +
1
+ +
2
+
3
+
4
+
+
+
+---- + +[[figure.board.basic-use.nested]] +.Nested Rows +image::img/board-basic-use-nested.png[] + +[[board.basic-use.styling]] +== Styling + +Vaadin Board rearranges elements in your layout based on available space. +In some cases you want to use different styles depending on how the elements are laid out, e.g. use smaller font size for mobile devices. +Vaadin Board has three predefined class selectors for [classname]#vaadin-board-row#: + +* small - for rows smaller than 600 pixels. +* middle - for rows between 600 and 969 pixels. +* large - for rows bigger than 960 pixels. + + +[source, html] +---- + + +
top A
+
top B
+
top C
+
top C
+
+
+---- + +[source, css] +---- +.large { + font-size:20px; +} +.medium { + font-size:16px; +} +.small { + font-size:10px; +} +---- + +[[board.basic-use.redraw]] +=== Redraw method + +Vaadin Board relies on resize events to achieve responsiveness. +In some cases the board size might change without a resize event, for instance if a fixed size is set in its style, for such cases the [methodname]#redraw# method of the [elementname]#vaadin-board# element should be used. + +[[board.basic-use.es6-transpile]] +== Internet Explorer 11 & Safari 9 support + +Vaadin Board is using Polymer 2 and ES6. To support IE11 and Safari 9 you need to transpile ES6 to ES5. +The easiest way to do that, is using link:https://www.polymer-project.org/2.0/docs/tools/polymer-cli#build[Polymer CLI]. +Add a build configuration to your link:https://www.polymer-project.org/2.0/docs/tools/polymer-json[polymer.json]: + +[source, html] +---- + "builds": [{ + "name": "my-app", + "js": {"minify": true, "compile": true}, + "css": {"minify": true}, + "html": {"minify": true} + }] +---- +Running [command]`polymer build` in you application folder will create a transpiled version of your application. +Your application will be transpiled and saved in build folder. + +Another option to transpile ES6 to ES5 is to use link:https://babeljs.io/[Babel]. + +[[board.basic-use.known-issues]] +== Known Issues + +- Because non-chrome browsers need to load a polyfill, you can see flickering, before definition of the web component comes in. +You can suspend rendering the component before it is ready by adding the `unresolved` attribute in body: + +[source, html] +---- + + //Your code here + +---- + +- Because Vaadin Board uses flexbox, there is a limited support for IE11. +If you want to have a border for the direct child of the [elementname]#vaadin-board-row# you need to create a wrapper +[elementname]#div# and add a border there, but not to the direct child of the [elementname]#vaadin-board-row#. +The description of the bug can be found link:https://github.com/philipwalton/flexbugs#7-flex-basis-doesnt-account-for-box-sizingborder-box[here]. + +- There is a memory leak problem with Internet Explorer 11 and Polymer 2, see details link:https://github.com/Polymer/polymer/issues/3430[here]. diff --git a/articles/board/webcomponents-api/getting-started.asciidoc b/articles/board/webcomponents-api/getting-started.asciidoc new file mode 100644 index 0000000000..17806f743c --- /dev/null +++ b/articles/board/webcomponents-api/getting-started.asciidoc @@ -0,0 +1,198 @@ +--- +title: Getting Started +order: 2 +layout: page +--- + +[[board.getting-started]] += Getting started with Vaadin Board + +[classname]`vaadin-board` is a regular https://www.webcomponents.org/[web component], which you can add to any web page. It can be used both with and without https://www.polymer-project.org/2.0/docs/about_20[Polymer 2]. + +In this tutorial, you will learn how to: + +1. <> +2. <> +3. <> +4. <> +5. <> + +In this tutorial we will use https://www.polymer-project.org/2.0/docs/tools/polymer-cli[Polymer CLI] for creating the initial project. At the end of the tutorial, you should end up with the same code as found at https://github.com/vaadin/vaadin-board-getting-started[GitHub]. + +[[board.project.setup]] +== Create a Polymer application + +1. https://www.polymer-project.org/2.0/docs/tools/polymer-cli#install[Install Polymer CLI]. +2. Create a directory for your app project: ++ +[subs="normal"] +---- +[prompt]#$# [command]#mkdir# my-app +[prompt]#$# [command]#cd# my-app +---- ++ +3. Use Polymer to initialize a new application: ++ +[subs="normal"] +---- +[prompt]#$# [command]#polymer# init +---- + +Polymer CLI will ask you a few questions to set up your app. Choose `polymer-2-application` as the starter template for your project. After the initialization process, Polymer CLI downloads dependencies and generates the following files and directories: + +`bower.json`:: Configuration file for Bower. +`bower_components/`:: Project dependencies. See Manage dependencies. +`index.html`:: Entrypoint page of the app. +`src/my-app/my-app.html`:: Source code for main element. +`test/my-app/my-app_test.html`:: Tests for main element. + +== Running your application + +Run your app with: +[subs="normal"] +---- +[prompt]#$# [command]#polymer# serve --open +---- +The [command]`--open` flag will fire up a browser window and open your app in it. + +[[board.project.setup.dependency]] +== Install Vaadin Board + +You can use https://bower.io[Bower] to install Vaadin Board dependency by running the following command inside your project folder: + +[subs="normal"] +---- +[prompt]#$# [command]#bower# install --save vaadin-board +---- + +This will install the latest available version of Vaadin Board in your project. + +== Import Vaadin Board in your app + +Next we'll modify your app to include a Vaadin Board. Open your app element in `src/my-app/my-app.html` and add the following line in as the second line in the file, under the Polymer import, to import Vaadin Board component into your app: + +[source, html] +---- + +---- + +[[board.project.setup.configuration]] +== Add the Vaadin Board component to your web page + +[classname]`vaadin-board` is divided into rows, using [classname]`vaadin-board-row`. +Rows are divided into columns. +You can put any WebComponent or HTML element inside the [classname]`vaadin-board-row`. +Every element inside the row can take from one to four columns. +Vaadin Board rearranges child elements based on available space. + +In the example below every child [elementname]`div` will use 25% on Desktop, but will be +rearranged to two rows when switching to tablet: one row with 2 items 50% of available space each and second row +with 100% width item. + +Insert the following code in your HTML element (again, in `src/my-app/my-app.html`), inside [elementname]`template` tag: + +[source, html] +---- + + +
1
+
2
+
3
+
4
+
+ +
1
+
2
+
+
+---- + +Then we can add styling to our content. Insert the following CSS , inside the [elementname]`style` tag: + +[source, html] +---- +.item { +   display: block; +   margin-left: 0; + margin-right: 0; + font-weight: bold; + border-style: solid; + border-width: 3px; + border-color: #fff; + text-align: center; + background-color: #cacaca; + height:100px; +} +---- + +After these modifications your `src/my-app/my-app.html` should look like this: + +[source, html] +---- + + + + + + + + +---- + +Run [command]`polymer serve --open` to see the following result: + +[[figure.board.getting.started.configuration]] +.Vaadin Board Basic Configuration +image::img/board-getting-started-configuration.png[] + +Vaadin Board rearranges child elements based on viewport size. +You can change the size of the Web browser window to see how your application will look on different devices. + +Congratulations! You have your first Vaadin Board setup. +Visit our link:https://vaadin.com/docs/-/part/board/board-overview.html[docs] and link:https://demo.vaadin.com/vaadin-board[demos] for more information. diff --git a/articles/board/webcomponents-api/img/board-basic-use-board-cols.png b/articles/board/webcomponents-api/img/board-basic-use-board-cols.png new file mode 100644 index 0000000000..201b5a8fbb Binary files /dev/null and b/articles/board/webcomponents-api/img/board-basic-use-board-cols.png differ diff --git a/articles/board/webcomponents-api/img/board-basic-use-nested.png b/articles/board/webcomponents-api/img/board-basic-use-nested.png new file mode 100644 index 0000000000..82e33d1139 Binary files /dev/null and b/articles/board/webcomponents-api/img/board-basic-use-nested.png differ diff --git a/articles/board/webcomponents-api/img/board-basic-use.png b/articles/board/webcomponents-api/img/board-basic-use.png new file mode 100644 index 0000000000..fd5542a12b Binary files /dev/null and b/articles/board/webcomponents-api/img/board-basic-use.png differ diff --git a/articles/board/webcomponents-api/img/board-getting-started-configuration.png b/articles/board/webcomponents-api/img/board-getting-started-configuration.png new file mode 100644 index 0000000000..4325c4c1f0 Binary files /dev/null and b/articles/board/webcomponents-api/img/board-getting-started-configuration.png differ diff --git a/articles/board/webcomponents-api/index.asciidoc b/articles/board/webcomponents-api/index.asciidoc new file mode 100644 index 0000000000..ebb1072493 --- /dev/null +++ b/articles/board/webcomponents-api/index.asciidoc @@ -0,0 +1,5 @@ +--- +title: Elements API +order: 3 +--- + diff --git a/articles/ce/collaboration-avatar-group.asciidoc b/articles/ce/collaboration-avatar-group.asciidoc deleted file mode 100644 index ec3dcb9c82..0000000000 --- a/articles/ce/collaboration-avatar-group.asciidoc +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: CollaborationAvatarGroup -order: 6 -layout: page ---- - -[[ce.indicating-user-presence]] -= Indicating User Presence With Collaboration Avatar Group - -Collaboration Engine includes an extension to Vaadin's `AvatarGroup` component, -called `CollaborationAvatarGroup`. -It automatically updates the displayed avatars based on the users who are -currently present in a view. -More specifically, when `CollaborationAvatarGroup` is attached, the user's avatar -will be added to the group for all users. When the component becomes detached, often because -of navigating to another view or closing the browser tab, the user's avatar is -removed from the group. - - -.Example of a `CollaborationAvatarGroup` -image::images/collaboration-avatar-group-example.png[Three avatars in a group, with three more avatars collapsed to an overflow item] - -To get started with `CollaborationAvatarGroup`, provide the `UserInfo` that represents -the current active user and the id of the topic to connect to. -Then add the component to your view: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/AvatarGroupDocumentation.java[render,tags=avatar-group-new,indent=0,group=Java] ----- - -.`User`, `UserService` and `"ensuranceClaims"` are examples -[NOTE] -The `User` and `UserService` classes are not available in Collaboration Engine. -They are examples of classes that might exist in your application for user management. -The topic ID `"ensuranceClaims"` can be any string to identify what the users are collaborating on. - -After running the app and opening the view, you should see your own avatar. -Try opening the view in another browser tab at the same time, as a separate user entity -(distinguished by the id provided to `UserInfo`). -Both tabs should display the avatars of both users. - -== Configuring the Avatars - -The avatars are mostly configured through the `UserInfo` object. -When no other information is available, the avatar displays a generic icon. - -=== Name and Abbreviation - -When a user name is provided via `UserInfo::setName`, -an automatically generated abbreviation will be displayed in the avatar. -To display a custom abbreviation, `UserInfo::setAbbreviation` can be used. -Hovering the mouse over the avatar displays the full name in a tooltip. -The name is also presented in the overflow dropdown; -when all of the avatars don't fit into the group, -the last avatar, which has text such as "+3", can be clicked to show -the overflowing avatars and names in a dropdown. - -=== Loading Images from a URL - -To display an image inside the avatar, there are two options. -First of all, if the image is already hosted somewhere, -you can provide its URL as a string to `UserInfo::setImage`. -Note that setting an image is not a replacement for the `name` property. -When an image is provided, `name` is still displayed in a tooltip on hover -and in the overflow dropwdown. - -=== Loading Images from a Backend - -The way to load images from a database to components such as `Image` or `Avatar` -with Vaadin is to use `StreamResources`. -`CollaborationAvatarGroup` supports stream resources with the `setImageProvider` method. -It takes a function that generates `StreamResources` for users based on their `UserInfo`. -For example, if the user entity contains the image as a byte array, -you can create a `StreamResource` that loads those bytes and let the framework take care -of hosting the image: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/AvatarGroupDocumentation.java[render,tags=avatar-group-images,indent=0,group=Java] ----- - -The explanation for this image provider pattern is, -that `StreamResource` is not serializable as JSON, -so it can't be included in `UserInfo` and sent back and forth -through Collaboration Engine. - -== Scoping the Avatars with setTopic - -Using different topic ids in the `setTopic` method allows defining which users -can see each others' avatars in the group. -If everyone in the view should see each other in the same avatar group, -the topic id can be any constant string, -as long as it doesn't conflict with potential other avatar groups in other views. -For example, the view name could be used as the topic id in this case. - -In many cases, the same `CollaborationAvatarGroup` component should be re-used for -different topics. -Think about a form view that is used for editing different entities, -where you want to see only the avatars of the users who are editing the same entity. -In this case, the topic id should be specific to the edited entity. -For example, consider a form for editing different `Person` entities. -When selecting the entity to edit, the topic could be updated as follows: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/AvatarGroupDocumentation.java[render,tags=avatar-group-topic,indent=0,group=Java] ----- - -If the form uses `CollaborationBinder`, it makes sense to use the same topic id -for the binder and the avatar group. - -Setting `null` topic disables the connection to Collaboration Engine. -The group won't display any avatars until a non-null topic id is provided. - -== Displaying User's Own Avatar Separately - -It's a common design pattern to display the user's own avatar somewhere separately -from the group of collaborators' avatars. -To achieve this, you can exclude the user's own avatar from the `CollaborationAvatarGroup` -and create a separate `Avatar` component. -You can then add it anywhere in your view, independently of the other avatars. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/AvatarGroupDocumentation.java[render,tags=avatar-group-own,indent=0,group=Java] ----- - -You can set the same `name`, `abbreviation` and `image` properties as for the `UserInfo`. -To load the image from a backend, you can pass a `StreamResource` directly -to the `Avatar::setImageResource` method. diff --git a/articles/ce/collaboration-binder.asciidoc b/articles/ce/collaboration-binder.asciidoc deleted file mode 100644 index c00d23f863..0000000000 --- a/articles/ce/collaboration-binder.asciidoc +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: CollaborationBinder -order: 7 -layout: page ---- - -[[ce.collaborative-form-editing]] -= Collaborative Form Editing with CollaborationBinder - -The recommended way of binding data from Java beans to forms in Vaadin applications is to use `Binder` -ifdef::articles[] -(read <<{articles}/flow/binding-data/components-binder#,Binding Data to Forms>> to learn more). -endif::articles[] -ifndef::articles[] -(read <<../flow/binding-data/tutorial-components-binder#,Binding Data to Forms>> to learn more). -endif::articles[] -Collaboration Engine provides a `Binder` extension called `CollaborationBinder`, -which adds the following real-time features on top of the binder's data binding and validation APIs: - -* Field value synchronization: When a user enters a new value to a field, the value is updated for the other users as well. -* Field highlight: When a user is focused on a field, other users see a highlight around the field and his/her user name indicating that he/she is currently editing it. - -== Constructing a CollaborationBinder - -The constructor of `CollaborationBinder` requires the bean type to bind values to, -similarly to the regular `Binder` when binding by property names. -As the second argument, you must provide some information about the end user. -The same `UserInfo` object is required by all Collaboration Engine features. -`CollaborationBinder` uses the name in `UserInfo`, when indicating -that another user is editing a field with the field highlight. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-new,indent=0,group=Java] ----- - -== Connecting to Collaboration Engine and Populating the Form - -The `CollaborationBinder::setTopic` method serves two purposes: - -1. Connecting to Collaboration Engine in the scope of the edited item -2. Populating the form with initial values loaded from a backend - -Here is an example use case. When selecting an item to edit (an instance of `Person` bean class in this case), -`setTopic` is used to connect to the topic and to populate the form: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-topic,indent=0,group=Java] ----- - -The first parameter is the id of the topic to connect to. By using unique topic ids for different -items, we make sure that edits on different items don't interfere with each other. - -The second parameter is a callback for providing the bean that populates the fields. -The regular `Binder` has the `readBean` method for populating the fields based on bean properties. -This method is not supported by `CollaborationBinder`. The reason is, that calling `readBean` -when a new view instance is constructed would have an unwanted effect: -Every time a new user would join editing the form, the field values would reset for every user. -The `setBean` method is unsupported for the same reason. - -The callback provided for `setTopic` replaces `readBean`. -It will be used to populate the form if the topic doesn't have any data yet, -i.e. the user is the first one to edit that form. -Otherwise, the field values are loaded from the topic in Collaboration Engine. -In this case, the callback is not even called, possibly avoiding an unnecessary database request. - -NOTE: If you explicitly want to override all field values for all collaborators (e.g. implement a reset button), -you can use `CollaborationBinder::reset` method, which takes a bean instance and uses its properties for -setting the field values. - -== Binding Collaborative Fields - -Here is an example of how we can bind the `Person` bean's `name` property to a text field, -enabling also the collaborative features (value synchronization and field highlight): - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-bind,indent=0,group=Java] ----- - -You could write exactly the same code with the regular `Binder`. -`CollaborationBinder` just adds the collaborative features on top of the regular data binding. -Note that binding based on a property name ("name" in this case) requires the bean class (`Person`) -to have standard getter and setter methods `getName` and `setName`. - -The other `bind` variant, which takes the getter and setter callbacks as arguments, is not supported -by `CollaborationBinder`. The technical reason for this is, that some unique key is needed -per each field/property to store the data in the underlying `CollaborationMap` data structure. -The property name is required for that purpose, to be used as the key. - -Because the data used to communicate with Collaboration Engine is serialized as JSON, there are some limitations -to what `CollaborationBinder` can do automatically. -Next, we'll cover the special cases where you need to do a little bit more than -simply binding a property to a field. - -=== Non-Primitive Value Types - -Collaboration Engine supports only a limited set of primitive-like value types, -that it knows how to serialize and deserialize. -When using some other field value type, you must explicitly provide the serializer -and deserializer functions. - -When the field is used for selecting a bean object that has a unique identifier, -you can serialize the value by converting the bean to its identifier, and deserialize -by fetching the bean object that matches the id. - -In this example, the `Person` bean that we are editing, has a reference to the person's -supervisor, which is another `Person`. We'll use a `ComboBox` component for selecting -the person's supervisor: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-serializer,indent=0,group=Java] ----- - -The person ids are stored as `longs` in this case, and the serialized value needs to be a `String`. -In this case, we need to do a bit of converting between strings and longs. - -=== Converters - -When a `Converter` is used, you must provide the field's value type in `forField`. - -In this example, we are binding an enum property of the bean to a `Checkbox`, -so the checkbox's value type `boolean` needs to be provided: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-converter,indent=0,group=Java] ----- - -This is necessary, because `CollaborationBinder` uses the bean -property type (`MaritalStatus` enum in this case) for deserializing -the field value by default. - -=== Multi Select Fields - -When the field's value type is a collection, -you must provide the type of the collection as well as the -type of its contents in `forField`. - -For example, the value type of `CheckboxGroup` is `Set`. -In the example below, we must provide the collection type `Set` and the content type `String`. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/BinderDocumentation.java[render,tags=binder-bind,indent=0,group=Java] ----- - -This is necessary, because `CollaborationBinder` can't automatically infer the -generic type for deserializing the value. -Note that if the element type is not supported by Collaboration Engine (e.g. `CheckboxGroup`), -you need to implement custom (de)serializer functions anyway. - -pass:[] - -== Propagate Values Eagerly in Text Fields -On text fields, the default and recommended mode for propagating values from one user to others is when the user blurs the field or presses the enter key. -You can configure how eagerly the field sends data through its own API, using the `setValueChangeMode(ValueChangeMode)` method. - -pass:[] -For example, to instantly send each keystroke to other users, you would do the following: - -[source, java] ----- -TextField textField = new TextField(); -textField.setValueChangeMode(ValueChangeMode.EAGER); ----- - -Modes like `ValueChangeMode.LAZY` and `ValueChangeMode.TIMEOUT` can also be used together with the `setValueChangeTimeout(int)` method to reduce the amount of traffic. diff --git a/articles/ce/developing-with-ce.asciidoc b/articles/ce/developing-with-ce.asciidoc deleted file mode 100644 index 129e46f022..0000000000 --- a/articles/ce/developing-with-ce.asciidoc +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Trial and Development Use -order: 3 -layout: page ---- - -[[ce.developing]] -= Trial and Development Use - -Collaboration Engine is licensed under the https://vaadin.com/license/cvrl-1.0[Commercial Vaadin Runtime License (CVRL)]. -You can try Collaboration Engine out and develop applications with it without charge. -When you take your application to production, you need a valid subscription. -To get started, follow the <> to learn about the features. - -While your application is in development mode, you can use all the features of Collaboration Engine without restrictions. -You do not need a development license or a separate trial. -Development mode is the default mode of a Vaadin application and is used when not explicitly configured to do a production build. diff --git a/articles/ce/documentation.asciidoc b/articles/ce/documentation.asciidoc deleted file mode 100644 index a4944500c3..0000000000 --- a/articles/ce/documentation.asciidoc +++ /dev/null @@ -1,21 +0,0 @@ -= Collaboration Engine -1.0.0 -:sectnums: -:toc: -:toclevels: 4 -:toc-title: Table of content -:description: - -include::overview.asciidoc[leveloffset=+1] - -include::tutorial.asciidoc[leveloffset=+1] - -include::developing-with-ce.asciidoc[leveloffset=+1] - -include::going-to-production.asciidoc[leveloffset=+1] - -include::topic-api.asciidoc[leveloffset=+1] - -include::collaboration-avatar-group.asciidoc[leveloffset=+1] - -include::collaboration-binder.asciidoc[leveloffset=+1] diff --git a/articles/ce/going-to-production.asciidoc b/articles/ce/going-to-production.asciidoc deleted file mode 100644 index af6a1d20cf..0000000000 --- a/articles/ce/going-to-production.asciidoc +++ /dev/null @@ -1,295 +0,0 @@ ---- -title: Setting Up for Production -order: 4 -layout: page ---- - -[[ce.production]] -= Setting Up for Production - -ifdef::articles[] -Enabling the production mode is described in <<{articles}/guide/production/production-overview#, Deploying to Production>>. -endif::articles[] -ifndef::articles[] -Enabling the production mode is described in <<../flow/production/tutorial-production-mode-basic#, Deploying to Production>>. -endif::articles[] -Using Collaboration Engine requires some extra steps when you take your application to production. - -You need to: - -. Get a license file with an end-user quota. -. Configure where Collaboration Engine files are stored. -. Store the license file in the right location. -. Implement a `LicenseEventHandler` to be notified when the license needs to be updated. - - -[[ce.production.obtain-license]] -== Obtaining a License File - -First, you need to have a subscription with a large enough user limit to meet your needs. -If you do not yet have a license, https://vaadin.com/collaboration/#contact-us[request a license through the product page] to get in contact with Vaadin. - -The name of the license file is `ce-license.json`. -It defines how many unique end users can use collaborative features per month and when the license expires. - -[[ce.production.configure-data-dir]] -== Configuring File Storage Location - -You need to configure which directory should be used by Collaboration Engine to store files by setting the `vaadin.ce.dataDir` property. -In version 2, the only file that Collaboration Engine uses is the `ce-license.json`, but in upcoming versions can use the directory to store automatic usage statistics, topic data, and so forth. - -You can configure the directory path by either: - -. configuring the data directory in project files or -. passing it in as a parameter on the server startup. - -If both are present, the server startup parameter is used. - -[[ce.production.data-dir-in-project-files]] -=== Configuring the Data Directory in Project Files - -Storing the path into the project files is a good way if you always deploy your application into the same environment and the folder does not change. -You can set the path as a system property in a `VaadinServiceInitListener`, which runs once on server startup. - -==== Spring Applications - -If you have a Spring application, you can register a `VaadinServiceInitListener` by implementing the interface and annotating the class as a `@SpringComponent`. -In the `serviceInit` method, you can then set `vaadin.ce.dataDir` as a system property. - -.`com.company.myapp.MyVaadinInitListener.java` -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/MyVaadinInitListener.java[render,tags=init-listener;!*,indent=0,group=Java] ----- - -==== Other Applications - -If you have a non-Spring application, you can implement the `VaadinServiceInitListener` in the same way as seen above, except that you can't use the `@SpringComponent` annotation. -Instead, you need to register it through the Java Service Provider Interface (SPI) loading facility. -You can do that by providing a file, `src/main/resources/META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener` with a fully qualified class name to your listener as content, for example, `com.company.myapp.MyVaadinInitListener`. - -.The location of the configuration file -image::images/service-init-listener.png[The location of the configuration file] - -.`src/main/resources/META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener` -``` -com.company.myapp.MyVaadinInitListener -``` - -=== Configuring the Data Directory on Server Startup - -For another way, you can pass the data directory as a parameter on server startup. -This way assumes that you have already a production-ready build available and want to run the package on the server. -ifdef::articles[] -Read <<{articles}/guide/production/mode#, Building in Production Mode>> to learn more about building your application for production. -endif::articles[] -ifndef::articles[] -Read <<../flow/production/tutorial-production-mode-basic#, Deploying to Production>> to learn more about building your application for production. -endif::articles[] - -==== Spring Boot Applications - -You can set the data directory with the `vaadin.ce.dataDir` system property for Java, for example as follows on the command line: - -``` -java -Dvaadin.ce.dataDir=/Users/steve/.vaadin/collaboration-engine -jar my-app-1.0-SNAPSHOT.jar -``` - -Note that the system property should be before the `-jar` parameter. - -==== Other Servlet Containers - -You can pass the data directory parameter as a context parameter to the servlet container. -You should refer to your servlet container's documentation on how to provide it. -You need to set the `vaadin.ce.dataDir` context parameter. -The value should be the directory path. - -For example, you can pass the context parameter to Jetty as follows: - -``` -mvn jetty:run -Dvaadin.ce.dataDir=/Users/steve/vaadin/collaboration-engine/ -``` - -ifdef::articles[] -See <<{articles}/flow/advanced/flow-runtime-configuration#,Changing the Application Behavior with Runtime Configuration>> for more information. -endif::articles[] -ifndef::articles[] -See <<../flow/advanced/tutorial-flow-runtime-configuration#,Changing the Application Behavior with Runtime Configuration>> for more information. -endif::articles[] - -The directory should be both readable and writable by the user running the Vaadin application. - -[[ce.production.files-to-server]] -== Placing the License File - -After obtaining the license file and the data directory, you need to put the license file in that directory on the server. -For example, if you configured the folder to be `/Users/steve/vaadin/collaboration-engine/`, you should place the license file so that the application can read it as `/Users/steve/vaadin/collaboration-engine/ce-license.json`. - -Collaboration Engine uses the file to verify that you have a proper license. -The application does not require an internet connection to Vaadin servers to verify the license. - -== Providing a Data Directory for a Docker Container - -It is recommended to provide the data directory to a Docker container on runtime by either using a https://docs.docker.com/storage/volumes/[volume] or a https://docs.docker.com/storage/bind-mounts/[bind mount]. -It is not recommended to copy the license file into the container image, as the data directory is erased every time you deploy a new version of your application. - -If you are deploying to a cloud provider, you may not have access to the host file system to be able to make use of bind mounts. -Consult the documentation for your cloud provider to get instructions on how to set up and provide a volume to your application. - -While a volume is preferred, if you have access to the host's file system or want to test the Docker image locally, you can do it with a bind mount with the following steps: - -. Set up a data directory on the host's file system. -For example: `/Users/steve/.vaadin/collaboration-engine`. -. Copy the `ce-license.json` file into the folder above. -. Pick a suitable folder within your Docker image where the container mounts the host folder. -For example: `/usr/app/ce`. -. Configure your `Dockerfile` to start up the server with the `vaadin.ce.dataDir` parameter pointing to the internal folder. For example `CMD java -Dvaadin.ce.dataDir=/usr/app/ce -jar /usr/app/app.jar` -. Build the Docker image, for example `$ docker build --tag my-app .` in the project directory. -. Start up the Docker container by giving the `-v` parameter mapping the host folder to the image folder. For example `$ docker run --name=myapp -dp 8080:8080 -v /Users/steve/.vaadin/collaboration-engine:/usr/app/ce myapp` - -When using volumes, you would replace the absolute path to the directory with the name of the volume, for example: -``` -$ docker run --name=myapp -dp 8080:8080 -v myapp-volume:/usr/app/ce myapp -``` - - -[[ce.production.license-events]] -== Notifications for Updating the License - -The licensing model may cause collaborative features to be disabled for some of -your application's users. -To avoid this situation, you need to get a new license if your old license is about to expire, or if your user base increases and the number of end-users exceeds the quota for one month. - -To know when to update the license, you need to implement a license event handler for Collaboration Engine. -Collaboration Engine can fire the following types of license events, each at most once during the license's lifecycle: - -. the first time when exceeding the end-user quota and entering the grace period (more details in <>), -. when the grace period ends, -. 30 days before the license expires, and -. when the license expires. - -If you take care of updating the license when events 1 and 3 are fired, the other -two events shouldn't happen at all. - -One potential way to handle the event is to send a message to any existing application monitoring system you might have. -Another option is to send an email to the relevant people, for example, those who maintain the deployment and those who are responsible of the Collaboration Engine license. -You need to ensure that your application notices and handles the events. - -The listener can be configured in a `VaadinServiceInitListener` in the same way as the `vaadin.ce.dataDir` property, -if you're setting that property in Java code, as described earlier. - -The following example is a Spring project, so the `VaadinServiceInitListener` is registered by adding the `@SpringComponent` annotation. -If you are not using Spring, you can register the service init listener in the same way as described in <>. - -.`com.company.myapp.MyVaadinInitListener.java` -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/MyVaadinInitListener.java[render,tags=init-listener;!send-email,indent=0,group=Java] ----- - -In the above example, the license event handler logs the event messages using the SLF4J logging API, and sends an email. -When it is time to update the license, the message is logged as a warning. -If the license is not updated in time, the message is logged as an error. -The default event messages provide information of what has happened, how it affects the application, and what is the recommended action to take. - -Below is an example implementation of the `sendEmail()` method. -It requires the `javax.mail.mail` package as a dependency. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/MyVaadinInitListener.java[render,tags=send-email,indent=0,group=Java] ----- - -.Exception thrown if events are not handled -NOTE: Collaboration Engine throws an exception in production mode if a configuration has not been defined. -The purpose is to make sure that your application handles the events, -and to avoid situation where the license expires by accident. - -[[ce.production.quota]] -== End-User Quota - -Your license includes a quota for how many unique end users are supported within a month, for example, a limit of 1.000 end users. -Collaboration Engine counts how many end users use its features during each calendar month. -The count of end users starts over on the first day of each month. - -[[ce.production.end-user]] -=== Definition of an End User - -When you use any Collaboration Engine features, you have to provide a -`UserInfo` object with a unique ID. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/ProductionDocumentation.java[render,tags=user-def,indent=0,group=Java] ----- - -Collaboration Engine records the ID of each user that accesses collaborative features in the ongoing month and counts towards your quota for the current month. -Each user ID is counted only once per month. - -[[ce.production.over-quota]] -=== Going Over the Quota - -When you exceed the limit the first time, nothing changes from the end user's perspective. -When that happens, Collaboration Engine starts a 30-day grace period, during which time the quota is ten times bigger. -The grace period gives you time to react to exceeding your limit without impacting your application in any way. -For example, if you have obtained a license for a 500 end-user quota, your effective quota is 5.000 end-users during the grace period. -After 30 days, your effective quota goes back to 500, and you won’t get another grace period until the next billing period. - -If the number of users in a month exceeds the 10x quota during the grace period, or the normal quota after the grace period is over, the collaborative features are disabled for the exceeding users. -Your application stills continues to work, but `CollaborationAvatarGroup` only show the user's own avatar, and forms built with `CollaborationBinder` do not show edits made by other end-users. -The end-users who are registered within the allowed quota have collaborative features available throughout the month. - -Consider, for example, a situation where you have a quota for 500 end-users, you have used your grace period, and 520 end-users have used collaborative features this month. -The first 500 end users can collaborate throughout the month. -Users from 501 through 520 can use the application, but it works as if Collaboration Engine was not in use. -They can only see their own presence and edits. -When the calendar month changes, counting starts over, and the first 500 end-users again get full access for the whole month. - -[[ce.production.when-in-grace]] -=== Entering the Grace Period - -The engine enters the grace period when you have a higher demand than expected when obtaining the license. -It is recommended that you get a new license with a higher quota to have collaborative features available for all your users before the grace period expires. -https://vaadin.com/collaboration/#contact-us[Contact Vaadin] to get a new license file with a higher quota. -You can change your quota at any time. -When you replace the license file with the new one, Collaboration Engine resets your grace period. -If you exceed your new quota in the future, you again receive a 30 day grace period. - -[[ce.production.request-access]] -=== Checking for End User Access - -You can determine whether a user has access or not by passing a callback to the `requestAccess()` method in the `CollaborationEngine` instance. -The callback gets an `AccessResponse` instance as parameter. -You can call its `AccessResponse::hasAccess()` method to find out access. -You can use the status to adapt the UI according to whether the end-user can use collaborative features. - -For example: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/ProductionDocumentation.java[render,tags=request-access,indent=0,group=Java] ----- - -.Cache the results -[TIP] -To avoid calling this method multiple times per user, it is suggested to cache the result during the login process, for example, in the session. - -[[ce.production.restrict-usage]] -=== Limiting Collaborative Features to Some End Users - -Collaboration Engine only counts those end users towards the quota whose `UserInfo` objects are passed to collaborative features. - -You can limit usage to a subset of your users in two different ways: - -. Only use Collaboration Engine in views that you have restricted with user access. -For example, if you only use collaborative features in the admin views, only those users who access the admin views are counted. - -. Check the details of the user before initializing the collaboration features. -For example, by checking the role or privileges or the user, you can decide in code if the users should have collaborative features enabled or not. - -An example of how to enable collaboration by checking user permissions: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/ProductionDocumentation.java[render,tags=restrict-usage,indent=0,group=Java] ----- diff --git a/articles/ce/images/ce-architecture.png b/articles/ce/images/ce-architecture.png deleted file mode 100644 index 5a082f3fbf..0000000000 Binary files a/articles/ce/images/ce-architecture.png and /dev/null differ diff --git a/articles/ce/images/collaboration-avatar-group-example.png b/articles/ce/images/collaboration-avatar-group-example.png deleted file mode 100644 index c1d47107a4..0000000000 Binary files a/articles/ce/images/collaboration-avatar-group-example.png and /dev/null differ diff --git a/articles/ce/images/service-init-listener.png b/articles/ce/images/service-init-listener.png deleted file mode 100644 index 0ed494c0ac..0000000000 Binary files a/articles/ce/images/service-init-listener.png and /dev/null differ diff --git a/articles/ce/index.asciidoc b/articles/ce/index.asciidoc deleted file mode 100644 index 7664f1930d..0000000000 --- a/articles/ce/index.asciidoc +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Collaboration Engine -order: 56 -published: false ---- diff --git a/articles/ce/overview.asciidoc b/articles/ce/overview.asciidoc deleted file mode 100644 index 214610d7f8..0000000000 --- a/articles/ce/overview.asciidoc +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Overview -layout: page -order: 1 ---- - -[[ce.overview]] -= Collaboration Engine - -Collaboration Engine is a solution for building real-time collaboration features into web apps with a few lines of code. -This means that end users can collaboratively edit and communicate in real time, directly within secure Vaadin web applications. - -.Subscription required for production use -[IMPORTANT] -Collaboration Engine is a commercial product that requires a subscription for production use. -You can freely test it out and develop applications with it, without charge. -<>, you need a valid subscription. - -[[ce.overview.use-cases]] -== Currently Supported Use Cases - -Collaboration Engine currently supports the following use-cases: - -Collaborative form editing:: -End users can edit forms together in real time. - -Avatars:: -End users see who else is looking at the same data as they are. -The avatars are automatically updated when users join or leave. - -Low-level API:: -Build your own collaborative experiences by sharing data in a `CollaborationMap` data structure. - -[[ce.overview.work]] -== How Collaboration Engine works - -Collaboration Engine offers an intuitive library that connects to a collaborative backend (the "engine"). - -This backend handles the sharing of data and user-state between application instances in real-time. -It currently runs in-memory on the application server, although a hostable version that you can deploy within your infrastructure is forthcoming. - -.Architecture of a Vaadin application using Collaboration Engine -image::images/ce-architecture.png[Collaboration Engine Architecture] - -[[ce.overview.concepts]] -== Central Concepts - -[[ce.overview.topics]] -=== Topics - -Collaboration between users is managed by collecting data into "topic" instances that are shared between all users interacting with the same part of the application. -A topic can be compared to a chat room - it has an identifier (topic id) that is unique in the context of the application and participating members will receive all updates made to any topic that they're participating in. -Topic ids are freeform strings that the developer may choose, like "app" or "contract-126-address". -When building a topic for a work item, it is a good convention to have the name of the entity, and the identifier for the entity in the topic id. -For example, if you are making a form for editing a `Person` entity, and the `Person` has the id 120, a good topic name would be "person/120". - -[[ce.overview.helpers]] -=== Helpers for Specific Use Cases - -There are two high-level APIs that enable the specific use case of editing a form together. - -`CollaborationBinder` enhances the regular Vaadin `Binder` to share the current value of each field with all other users configured to use the same topic. - -There is also a `CollaborationAvatarGroup` component that shows the avatar of each user who is present in a given topic, for example, all the users currently looking at or editing the same item. - -[[ce.overview.api]] -=== Low-Level API - -The low-level Topic API allows synchronizing arbitrary data between users. -It is used internally by `CollaborationBinder` and `CollaborationAvatarGroup` but can also be used separately to create custom collaborative user experiences. -The entry point to using the Topic API is by opening a `TopicConnection` through `CollaborationEngine.getInstance()`. - -A topic has multiple named maps which are shared across connections. -Each map contains many pairs. - -It is strongly recommended that shared values are immutable instances since subscribers are notified only when the shared value is replaced with another instance but not when the contents of an existing value is updated. - -For complex values, a conditional replace operation is available to prevent overwriting concurrent modifications to other parts of the shared data. - -[[ce.overview.limitations]] -== Feature Limitations -Collaboration Engine is production-ready and stable, however the following features are still under development, and are not currently available: - -* Missing support for complex data structures with nested arrays and maps. -* Topic data is not persisted between server restarts. - Applications can manually persist topic data and repopulate after a restart if necessary. -* There is no support for collaboration between multiple nodes or pods in a cluster of application servers. - A future version will enable running Collaboration Engine as a standalone server or a cloud deployment that can be used from multiple application servers. -* There is only support for Vaadin views implemented with Flow. - Support for Fusion will be added later. diff --git a/articles/ce/topic-api.asciidoc b/articles/ce/topic-api.asciidoc deleted file mode 100644 index 7ad8388944..0000000000 --- a/articles/ce/topic-api.asciidoc +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Topic API -order: 5 -layout: page ---- - -[[ce.topic-tutorial]] -= Getting Started with the Topic API - -This tutorial shows how to use the low-level Collaboration Engine APIs, -by updating and subscribing to a topic. - -To be more productive in creating collaborative applications, it's recommended -to use the high-level APIs as described in the <>. - -[[ce.topic-tutorial.setup]] -== Prepare the Application - -Follow the preparation steps in the -<>. - -[[ce.topic-tutorial.add-collaboration-features]] -== Add Collaboration Features -This tutorial will build a view with a checkbox where the user can choose whether they are in a Friday mood. - -=== Create a Simple View - -First, create the view with a checkbox but not yet any collaborative functionality. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TopicView.java[render,tags=topic-view;add-components;!*,indent=0,group=Java] ----- - -=== Define Topic Connection - -Sharing data between multiple users happens through a `TopicConnection` instance. -By default, the connection is deactivated until its related component is attached to the UI. - -Open a connection to the `tutorial` topic and define the activation callback -which will be triggered when the current `TopicView` component (i.e. `this`) is attached. -The user who is related to the topic connection must be defined. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TopicView.java[render,tags=user-info;open-topic;!*,indent=0,group=Java] ----- - -The activation callback should return a registration that is run when the connection is deactivated. -Since we are not yet registering any own listeners that need cleanup, we can just return `null`. - -=== Define a category in the Topic -The topic stores collaborative data in named maps. In the activation callback, get a map by its name: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TopicView.java[render,tags=open-topic;get-map;!*,indent=0,group=Java] ----- - -=== Pass Values to the Topic - -The first actual step to making the application collaborative is to update the topic whenever the checkbox value changes. -`isFriday` is the key associated with the value of the checkbox. -Add a value change listener that updates the related topic map. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TopicView.java[render,tags=open-topic;get-map;registration;!*,indent=0,group=Java] ----- - -The topic's structure now looks like: - ----- -Topic maps -|_ fieldValues - |_ isFriday: true/false ----- - - -=== Subscribe to Topic Changes - -The final part of the code is to subscribe to updates to the topic map and update the checkbox if the related map is changed. -This is also done in the activation callback so that the subscription is opened only when the view is actually used. - -It's also necessary to return the registration of the listener so -it can be removed when the component is detached to avoid leaking memory. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TopicView.java[render,tags=open-topic,indent=0,group=Java] ----- - -TIP: In case there are many registrations, they can be combined by `Registration.combine(registration1, registration2);`. - -[[ce.topic-tutorial.run]] -== Run the Application -* Follow instructions in the application's `README.md` file to start the application. -* Open http://localhost:8080/ in multiple browser tabs to see how a change made in one tab is automatically shown in the other tabs. diff --git a/articles/ce/tutorial.asciidoc b/articles/ce/tutorial.asciidoc deleted file mode 100644 index e8d1ca72ae..0000000000 --- a/articles/ce/tutorial.asciidoc +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Tutorial -order: 2 -layout: page ---- - -[[ce.tutorial]] -= Getting Started With Collaboration Engine - -This tutorial shows basic steps to set up Collaboration Engine in your Vaadin project -and add the following collaboration features to a simple form: - -* Users can see the avatars of all the users who are using the application at the same time. -* When someone enters a new value to a field, it is propagated to all users. -* Users can see who is currently editing each field (a feature referred to as field highlight). - -.Subscription required for production use -[IMPORTANT] -Collaboration Engine is a commercial product that requires a subscription for production use. -You can try it out and develop applications with it without charge. -<>, you need a valid subscription. - -[[ce.tutorial.setup]] -== Preparing the Application - -=== Setting Up a Vaadin Project - -Download a new Vaadin project from https://start.vaadin.com/?preset=latest. - -[[ce.tutorial.install]] -[role="deprecated:com.vaadin:vaadin@V19"] -=== Installing Collaboration Engine - -Collaboration Engine is a dependency that you add to your Vaadin project. - -In the project's [filename]`pom.xml` file, add Collaboration Engine as a dependency, under the `` tag in the root (and *not* the one under ``): - -[source, xml] ----- - - com.vaadin - collaboration-engine - 3.0.0 - ----- - -Consult the https://github.com/vaadin/collaboration-engine/releases[releases page] to find the version number of the latest release. - -[[ce.tutorial.push]] -=== Enabling Server Push - -Add `@Push` annotation on top of your `AppShellConfigurator`. -This enables the server to propagate updates between clients in real time. -In Spring applications, you can implement the interface in your main application class. - -[source, Java] ----- -@Push -@SpringBootApplication -public class Application extends SpringBootServletInitializer implements AppShellConfigurator { - - public static void main(String... args) { - SpringApplication.run(Application.class, args); - } -} ----- - -.Manual push mode is not supported -[NOTE] -If you explicitly configure push to use `PushMode.MANUAL`, Collaboration Engine does not work, as it doesn't manually invoke `UI.push()` to send the user interactions to the other connected users. -Collaboration Engine works with any of the transport modes for push. - - -[[ce.tutorial.add_collaborative_features]] -== Adding Collaboration Features - -This tutorial shows how to build a form where the users can edit the name and date of birth of a person. - -Consider a `Person` bean class such as follows: - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TutorialView.java[render,tags=person-bean,indent=0,group=Java] ----- - -=== Creating a Simple View - -To start writing the actual application, create a view with a text field -and a date picker but not yet any collaborative functionality. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TutorialView.java[render,tags=tutorial;add-components;!*,indent=0,group=Java] ----- - -=== Providing User Information - -The `UserInfo` class represents an end user of a collaborative application. -It has properties such as `name` and `image`, which are used to display information about who else is currently viewing the same view or editing a field. - -The user id should be the unique identifier of the currently logged-in user. -(Note that this tutorial uses an id based on the UI instance instead of a user-based id. -This allows simulating multiple users by opening the view in multiple browser tabs.) - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TutorialView.java[render,tags=user-info,indent=0,group=Java] ----- - -The name is displayed to other users when editing a field, and the user's avatar contains the abbreviation of the name (as the above example does not provide a user image). - -`UserInfo` also has a `colorIndex` property. -It defines which color is used in the user's avatar as well as in the field highlight when editing a field. -This property is generated automatically, so you don't have to set it explicitly. - -=== Adding User Avatars - -To display the avatars of all users who are currently using the application, create a `CollaborationAvatarGroup` component. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TutorialView.java[render,tags=avatar-group,indent=0,group=Java] ----- - -First of all, the components needs the local user's information (the `UserInfo` -object which was created in the earlier example), to know how to render the user's avatar. - -As a second constructor argument, the component needs a topic id. -A topic can be compared to a chat room - it has an id that is unique in the context of the application. -Participating members receive all updates made to any topic that they are participating in. -Topic ids are freeform strings of your choice, such as "`app`" or "`contract-126-address`". -In this example, there is only one topic to work on, so we can use any hard-coded topic id. - -Note that if the application was expanded so that there would be a view for editing person entities, you'd need to have unique topic ids for each entity. -For example, you could have a topic id "person/123", where "123" would be unique to each person. -In that case, the same `CollaborationAvatarGroup` component could be reused for editing different persons by changing the topic with the `setTopic()` method. - -=== Adding Field Collaboration - -To enable collaboration with the text field and date picker components, we'll use a class called `CollaborationBinder`. -It extends the functionality of the `Binder` class, which binds values between Java beans and Vaadin field components. -ifdef::articles[] -Read <<{articles}/flow/binding-data/components-binder#,Binding Data to Forms>> to learn more about the binder. -endif::articles[] -ifndef::articles[] -Read <<../flow/binding-data/tutorial-components-binder#,Binding Data to Forms>> to learn more about the binder. -endif::articles[] - -To initialize a collaboration binder, we need to provide the type that will be edited, as well as the local user's information. -After initializing, we use the regular binder methods to bind the person object's name property to our text field component, and the date of birth property to our date picker component. - -Finally, we set the topic to connect to (the same as for `CollaborationAvatarGroup`) and a supplier for the initial bean value that will populate the fields when the first user connects to the topic. -The supplier could load the editable item from a backend, but in this example we populate the fields with an empty `Person` object. - -[source, Java] ----- -include::{root}/src/main/java/com/vaadin/demo/ce/TutorialView.java[render,tags=binder,indent=0,group=Java] ----- - -The example takes care of propagating the field values among users, as well as displaying the currently focused user with the field highlight. - -[[ce.tutorial.run]] -== Running the Application - -. Follow instructions in the application's `README.md` file to start the application. - -. Open http://localhost:8080/ in multiple browser tabs and test the application: notice the avatars, focus the fields and notice the field highlight, enter new values and notice how the fields update in the other tabs. diff --git a/articles/charts/charts-overview.asciidoc b/articles/charts/charts-overview.asciidoc new file mode 100644 index 0000000000..cd56cabf7d --- /dev/null +++ b/articles/charts/charts-overview.asciidoc @@ -0,0 +1,127 @@ +--- +title: Overview +order: 1 +layout: page +--- + +[[charts.overview]] += Charts + +Vaadin Charts is a feature-rich interactive charting library for Vaadin. It +provides a [classname]#Chart# component. The +[classname]#Chart# can visualize one- and two-dimensional numeric data in many +available chart types. The charts allow flexible configuration of all the chart +elements as well as the visual style. The library includes a number of built-in +visual themes, which you can extend further. The basic functionalities allow the +user to interact with the chart elements in various ways, and you can define +custom interaction with click events. + +[[figure.charts.overview]] +.Vaadin Charts +image::img/charts-overview.png[] + +The data displayed in a chart can be one- or two dimensional tabular data, or +scatter data with free X and Y values. Data displayed in range charts has +minimum and maximum values instead of singular values. + +This chapter covers the basic use of Vaadin Charts and the chart configuration. +For detailed documentation of the configuration parameters and classes, please +refer to the JavaDoc API documentation of the library. + +In the following basic examples, which we study further in +<> and +<>, we +demonstrate how to display one-dimensional data in a column graph and customize +the X and Y axis labels and titles. + +Java: +[source, java] +---- +Chart chart = new Chart(ChartType.BAR); +chart.setWidth("400px"); +chart.setHeight("300px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Planets"); +conf.setSubTitle("The bigger they are the harder they pull"); +conf.getLegend().setEnabled(false); // Disable legend + +// The data +ListSeries series = new ListSeries("Diameter"); +series.setData(4900, 12100, 12800, + 6800, 143000, 125000, + 51100, 49500); +conf.addSeries(series); + +// Set the category labels on the axis correspondingly +XAxis xaxis = new XAxis(); +xaxis.setCategories("Mercury", "Venus", "Earth", + "Mars", "Jupiter", "Saturn", + "Uranus", "Neptune"); +xaxis.setTitle("Planet"); +conf.addxAxis(xaxis); + +// Set the Y axis title +YAxis yaxis = new YAxis(); +yaxis.setTitle("Diameter"); +yaxis.getLabels().setFormatter( + "function() {return Math.floor(this.value/1000) + \' Mm\';}"); +yaxis.getLabels().setStep(2); +conf.addyAxis(yaxis); + +layout.addComponent(chart); +---- + +Web Components: +[source, html] +---- + + + + + + + +
+ + Planets + The bigger they are the harder they pull + + false + + + Planet + Mercury, Venus, Earth, Mars, + Jupiter, Saturn, Uranus, Neptune + + + Diameter + + 2 + + + + + 4900, 12100, 12800, 6800, + 143000, 125000, 51100, 49500 + + + +
+ + +---- + + +The resulting chart is shown in <>. + +[[figure.charts.overview.basicexample]] +.Basic Chart Example +image::img/charts-basicexample.png[] + +[[charts.overview.licensing]] +== Licensing + +Vaadin Charts is a commercial product licensed under the VCL-2 License (Vaadin Commercial License and Service Terms). +You need a license for all Charts use, including web deployments as well as intranet use. See link:https://vaadin.com/pricing[pricing] for details. diff --git a/articles/charts/examples/webcomponents/basicuse/index.html b/articles/charts/examples/webcomponents/basicuse/index.html new file mode 100644 index 0000000000..262b56e0e8 --- /dev/null +++ b/articles/charts/examples/webcomponents/basicuse/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + X labels + Reindeer Kills by Predators by Counties + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + center + + -45 + 2 + + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + + +
+ + Scatter - In 3D! + + false + + + + + + + + + + Y + -1 + 1 + + + 1 + X + -1 + 1 + + + 1 + Z + false + 1 + + + true + + {x: 0.0, y: 0.0, z:0.0}, + {x:1.0, y:0.0, z:0.0}, + {x:0.0, y:1.0, z:0.0}, + {x:0.0, y:0.0, z:1.0}, + {x:-1.0, y:0.0, z:0.0}, + {x:0.0, y:-1.0, z:0.0}, + {x:0.0, y:0.0, z:-1.0} + + + +
+ + + + Planets - In 3D! + The bigger they are the harder they pull + + false + + + + true + 60 + + 135 + 100 + + + + + 45 + + + + + + Planet + Mercury, Venus, Earth, Mars, + Jupiter, Saturn, Uranus, Neptune + + + + 4900, 12100, 12800, 6800, + 143000, 125000, 51100, 49500 + + + + + + + Combination + Reindeer Kills by Predators by Counties + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + column + blue + 8, 30, 37, 13, 3 + + + line + red + 0, 1, 0, 23, 10 + + + + + Line + Reindeer Kills by Predators by Counties + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + Column + Reindeer Kills by Predators by Counties + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + Stacked column + Reindeer Kills by Predators by Counties + + + normal + + + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + Bar + Reindeer Kills by Predators by Counties + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + diff --git a/articles/charts/examples/webcomponents/charttypes/img/neocreo_Blue_World_Map_640x.png b/articles/charts/examples/webcomponents/charttypes/img/neocreo_Blue_World_Map_640x.png new file mode 100644 index 0000000000..a297d96864 Binary files /dev/null and b/articles/charts/examples/webcomponents/charttypes/img/neocreo_Blue_World_Map_640x.png differ diff --git a/articles/charts/examples/webcomponents/charttypes/img/vaadin-logo.png b/articles/charts/examples/webcomponents/charttypes/img/vaadin-logo.png new file mode 100644 index 0000000000..c2de8a0b6b Binary files /dev/null and b/articles/charts/examples/webcomponents/charttypes/img/vaadin-logo.png differ diff --git a/articles/charts/examples/webcomponents/charttypes/index.html b/articles/charts/examples/webcomponents/charttypes/index.html new file mode 100644 index 0000000000..c723af183f --- /dev/null +++ b/articles/charts/examples/webcomponents/charttypes/index.html @@ -0,0 +1,1014 @@ + + + + + + + + + + Height vs Weight + Polygon series + + + Height (cm) + + + Weight (kg) + + + + + [153, 42], [149, 46], [149, 55], [152, 60], [159, 70], [170, 77], [180, 70], + [180, 60], [173, 52], [166, 45] + + + [161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6], + [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2], + [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0], + [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8], + [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8], + [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0], + [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8], + [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6], + [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3], + [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8], + [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3], + [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3], + [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0], + [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7], + [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5], + [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2], + [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8], + [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9], + [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2], + [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4], + [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4], + [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2], + [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0], + [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0], + [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4], + [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4], + [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5], + [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5], + [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2], + [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2], + [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3], + [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5], + [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4], + [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6], + [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8], + [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1], + [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5], + [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2], + [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6], + [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0], + [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0], + [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9], + [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1], + [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4], + [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7], + [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5], + [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8], + [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0], + [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9], + [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6], + [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8], + [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3] + + + + + Fruit consumption + + + + + + + + + + + + + A + Apples + #EC2500 + + + B + Bananas + #ECE100 + + + O + Oranges + #EC9800 + + + Anne + A + 5 + + + Rick + A + 3 + + + Peter + A + 4 + + + Anne + B + 4 + + + Rick + B + 10 + + + Peter + B + 1 + + + Anne + O + 1 + + + Rick + O + 3 + + + Peter + O + 3 + + + Susanne + Kiwi + 2 + #9EDE00 + + + + + + + +
+ + Heat Data + + + + white + 2 + + + + + + -51.5 + 37.2 + #00FFFF + #FF0000 + + + Month + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + "High °C", "Low °C" + + + + [0, 0, 10.9], + [0, 1, -51.5], + [1, 0, 11.8], + [1, 1, -49.0], + [2, 0, 17.5], + [2, 1, -44.3], + [3, 0, 25.5], + [3, 1, -36.0], + [4, 0, 31.0], + [4, 1, -24.6], + [5, 0, 33.8], + [5, 1, -7.0], + [6, 0, 37.2], + [6, 1, -5.0], + [7, 0, 33.8], + [7, 1, -10.8], + [8, 0, 28.8], + [8, 1, -18.7], + [9, 0, 19.4], + [9, 1, -31.8], + [10, 0, 14.1], + [10, 1, -42.0], + [11, 0, 10.8], + [11, 1, -47] + + + +
+ + +
+ + Changes in Reindeer Population in 2011 + + + + + #0000FF + #FF0000 + 0 + + + + + + + Population (thousands) + 330000 + + + + {x: 0, y: 306503, name: "Start", color: "#000000"}, + {x: 1, y: -3330, name: "Predators"}, + {x: 2, y: -103332, name: "Slaughter"}, + {x: 3, y: 104052, name: "Reproduction"}, + {x: 4, name: "End", isSum: true, color: "#000000"} + + + +
+ +
+ + Monster Food Pyramid + + + + + + + + + + + + ['Monsters Met', 340], + ['Engaged', 235], + ['Killed', 187], + ['Tinned', 70], + ['Eaten', 50] + + + +
+ +
+ + Monster Funnel + + + + + 20% + 20% + + + + + + + + + + ['Monsters Met', 340], + ['Engaged', 235], + ['Killed', 187], + ['Tinned', 70], + ['Eaten', 50] + + + + +
+ +
+ + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + + true + + + + + + 1 + + polygon + + + on + 0 + 0 + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + 10.9, 11.8, 17.5, 25.5, 31.0, 33.8, + 37.2, 33.8, 28.8, 19.4, 14.1, 10.8 + + + +
+ + +
+ + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + true + + + + 1 + + + + + 10.9, 11.8, 17.5, 25.5, 31.0, 33.8, + 37.2, 33.8, 28.8, 19.4, 14.1, 10.8 + + + +
+ +
+ + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + + Temperature °C + + + + 0 + 0 + Month + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + + [-51.5,10.9], + [-49.0,11.8], + [-44.3,17.5], + [-36.0,25.5], + [-24.6,31.0], + [-7.0,33.8], + [-5.0,37.2], + [-10.8,33.8], + [-18.7,28.8], + [-31.8,19.4], + [-42.0,14.1], + [-47.0,10.8] + + + +
+ + +
+ + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + Temperature °C + + + + Month + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + + [-51.5,10.9], + [-49.0,11.8], + [-44.3,17.5], + [-36.0,25.5], + [-24.6,31.0], + [-7.0,33.8], + [-5.0,37.2], + [-10.8,33.8], + [-18.7,28.8], + [-31.8,19.4], + [-42.0,14.1], + [-47.0,10.8] + + + +
+ + + Speed + + + + + + + + 0.1, #55BF3B + 0.5, #DDDF0D + 0.9, #DF5353 + + + + + + + + + + 80 + + + + + + Speedometer + + + + + km/h + + + + + + + + 80 + + + + +
+ + Browser market shares at spesific website, 2011 + The bigger they are the harder they pull + + false + + + + rgb(255,255,255) + + + ["IE", 55.11], + ["Firefox", 21.63], + ["Chrome", 11.94], + ["Safari", 7.15], + ["Opera", 2.14] + + + + + + + + + MSIE 6.0 + 10.85 + rgba(48,144,240,0.65) + + + MSIE 7.0 + 7.35 + + rgba(48,144,240,0.93) + + + + MSIE 8.0 + 33.06 + + rgba(48,144,240,0.54) + + + + MSIE 9.0 + 2.81 + + rgba(48,144,240,0.52) + + + + Firefox 2.0 + 0.20 + rgba(236,100,100,0.85) + + + Firefox 3.0 + 0.83 + + rgba(236,100,100,0.88) + + + + Firefox 3.5 + 1.58 + + rgba(236,100,100,0.76) + + + + Firefox 3.6 + 13.12 + + rgba(236,100,100,0.71) + + + + Firefox 4.0 + 5.43 + rgba(236,100,100,0.74) + + + + Chrome 5.0 + 0.12 + rgba(152,223,88,0.79) + + + Chrome 6.0 + 0.19 + + rgba(152,223,88,0.82) + + + + Chrome 7.0 + 0.12 + + rgba(152,223,88,0.67) + + + + Chrome 8.0 + 0.36 + + rgba(152,223,88,0.88) + + + + Chrome 9.0 + 0.32 + + rgba(152,223,88,0.87) + + + + Chrome 10.0 + 9.91 + + rgba(152,223,88,0.85) + + + + Chrome 11.0 + 0.50 + + rgba(152,223,88,0.64) + + + + Chrome 12.0 + 0.22 + + rgba(152,223,88,0.54) + + + + Safari 5.0 + 4.55 + rgba(249,221,81,0.65) + + + Safari 4.0 + 1.42 + + rgba(249,221,81,0.91) + + + + Safari Win 5.0 + 0.23 + + rgba(249,221,81,0.70) + + + + Safari 4.1 + 0.21 + + rgba(249,221,81,0.63) + + + + Safari/Maxthon + 0.20 + + rgba(249,221,81,0.68) + + + + Safari 3.1 + 0.19 + + rgba(249,221,81,0.79) + + + + Safari 4.1 + 0.14 + + rgba(249,221,81,0.82) + + + + Opera 9.x + 0.12 + rgba(36,220,212,0.67) + + + Opera 10.x + 0.37 + + rgba(36,220,212,0.60) + + + + Opera 11.x + 1.65 + + rgba(36,220,212,0.83) + + + + + +
+ + +
+ + Planets + The bigger they are the harder they pull + + false + + + + 60% + 75% +
50%, 50%
+
+
+ + + ["Mercury", 4900], + ["Venus", 12100], + {name: "Earth", y: 12800, sliced: true}, + ["Mars", 6800], + ["Jupiter", 143000], + ["Saturn", 125000], + ["Uranus", 51100], + ["Neptune", 49500] + + +
+
+ + +
+ + + false + + Champagne Consumption by Country + + + + + img/neocreo_Blue_World_Map_640x.png + + + + + -180 + 180 + + + + + -90 + 90 + + 0 + + + + + + + + 0 + rgba(255, 255, 255, 0.5) + + + 1 + rgba(170, 70, 67, 0.5) + + + + + + + + { x: 1.799, y: 55.200, z: 13.476, name: "France"}, + { x: -1.725, y: 64.800, z: 5.876, name: "United Kingdom"}, + { x: -90.328, y: 45.600, z: 4.401, name: "United States"}, + { x: 7.895, y: 61.200, z: 3.768, name: "Germany"}, + { x: 3.512, y: 60.996, z: 3.092, name: "Belgium"}, + { x: 129.470, y: 43.200, z: 2.811, name: "Japan"}, + { x: 128.355, y: -32.400, z: 2.207, name: "Australia"}, + { x: -78.990, y: 72.000, z: 1.261, name: "Canada"}, + { x: 83.147, y: 72.000, z: 1.158, name: "Russia"}, + { x: 98.862, y: 42.000, z: 1.149, name: "China"} + + + +
+ + + + + + +
+ + + false + + Orienteering Split Times + + Check Point + S-1, 1-2, 2-3, 3-4, 4-5, 5-6, 6-7, 7-8 + + + Time (s) + + + + #0000FF + 3 + + + + [63.0,108.25,154.0,180.5,463.0], + [107.0,149.0,281.5,333.25,520.0], + [56.0,112.0,151.5,157.75,483.0], + [194.0,319.75,371.0,451.0,885.0], + [63.0,101.5,155.5,162.25,371.0], + [72.0,95.25,136.5,155.75,217.0], + [158.0,217.25,304.0,359.75,733.0], + [80.0,105.5,120.0,144.25,240.0] + + --> + + + + { low: 63.0, q1: 108.25, median: 154.0, q3: 180.5, high: 463.0 }, + { low: 107.0, q1: 149.0, median: 281.5, q3: 333.25, high: 520.0 }, + { low: 56.0, q1: 112.0, median: 151.5, q3: 157.75, high: 483.0 }, + { low: 194.0, q1: 319.75, median: 371.0, q3: 451.0, high: 885.0 }, + { low: 63.0, q1: 101.5, median: 155.5, q3: 162.25, high: 371.0 }, + { low: 72.0, q1: 95.25, median: 136.5, q3: 155.75, high: 217.0 }, + { low: 158.0, q1: 217.25, median: 304.0, q3: 359.75, high: 733.0 }, + { low: 80.0, q1: 105.5, median: 120.0, q3: 144.25, high: 240.0 } + + + +
+ + +
+ + + false + + Average and Extreme Tempetures in Turku + + Month + Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + + + Temperature °C + + + + #808080 + 2 + Dash + #A52A2A + 80% + 2 + + + + + [-9, -3], [-10, -3], [-8, 1], [-2, 7], [3, 14], [8, 19], [12, 22], + [11, 21], [7, 15], [2, 9], [-1, 4], [-5, 0] + + + + + -6, -6.5, -4, 3, 9, 14, 17, 16, 11, 6, 2, -2.5 + + + +
+ + + Stacking area + Reindeer Kills by Predators by Counties + + + normal + + + + Muddusjärvi, Ivalo, Oraniemi, Salla, Alakitka + + + Kills + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + + + + + + diff --git a/articles/charts/examples/webcomponents/overview/index.html b/articles/charts/examples/webcomponents/overview/index.html new file mode 100644 index 0000000000..68e31cbe64 --- /dev/null +++ b/articles/charts/examples/webcomponents/overview/index.html @@ -0,0 +1,40 @@ + + + + + + + +
+ + Planets + The bigger they are the harder they pull + + false + + + + + + + + Planet + Mercury, Venus, Earth, Mars, + Jupiter, Saturn, Uranus, Neptune + + + Diameter + + 2 + + + + + 4900, 12100, 12800, 6800, + 143000, 125000, 51100, 49500 + + + +
+ + diff --git a/articles/charts/img/charts-basicexample.png b/articles/charts/img/charts-basicexample.png new file mode 100644 index 0000000000..a99febad95 Binary files /dev/null and b/articles/charts/img/charts-basicexample.png differ diff --git a/articles/ds/components/charts/img/charts-overview.png b/articles/charts/img/charts-overview.png similarity index 100% rename from articles/ds/components/charts/img/charts-overview.png rename to articles/charts/img/charts-overview.png diff --git a/articles/charts/index.asciidoc b/articles/charts/index.asciidoc new file mode 100644 index 0000000000..8774f3fd91 --- /dev/null +++ b/articles/charts/index.asciidoc @@ -0,0 +1,5 @@ +--- +title: Charts +order: 3 +--- + diff --git a/articles/charts/java-api/charts-advanced.asciidoc b/articles/charts/java-api/charts-advanced.asciidoc new file mode 100644 index 0000000000..0339301744 --- /dev/null +++ b/articles/charts/java-api/charts-advanced.asciidoc @@ -0,0 +1,91 @@ +--- +title: Advanced Uses +order: 7 +layout: page +--- + +[[charts.advanced]] += Advanced Uses + +[[charts.advanced.export]] +== Server-Side Rendering and Exporting + +In addition to using charts in Vaadin UIs, you may also need to provide them as +images or in downloadable documents. Vaadin Charts can be rendered on the +server-side using a headless JavaScript execution environment, such as +link:https://phantomjs.org/[PhantomJS]. + +Vaadin Charts supports a HighCharts remote export service, but the SVG Generator +based on PhantomJS is almost as easy to use and allows much more powerful uses. + +[[charts.advanced.export.exporting]] +=== Using a Remote Export Service + +Vaadin Charts has a simple built-in export functionality that does the export in a +remote export server. Vaadin Charts provides a default export service, but you can +also configure your own. + +You can enable the built-in export function by setting +[methodname]#setExporting(true)# in the chart configuration. + +[source,java] +---- +chart.getConfiguration().setExporting(true); +---- + +To configure it further, you can provide a [classname]#Exporting# object with +custom settings. + +[source,java] +---- +// Create the export configuration +Exporting exporting = new Exporting(true); + +// Customize the file name of the download file +exporting.setFilename("mychartfile"); + +// Use the exporting configuration in the chart +chart.getConfiguration().setExporting(exporting); +---- + +The functionality uses a HighCharts export service by default. To use your own, +you need to set up one and then configure it in the exporting configuration as +follows: + +[source,java] +---- +exporting.setUrl("https://my.own.server.com"); +---- + + +[[charts.advanced.export.svggenerator]] +=== Using the SVG Generator + +The [classname]#SVGGenerator# in Vaadin Charts provides an advanced way to +render the Chart into SVG format on the server-side. SVG is well supported by +many applications, can be converted to virtually any other graphics format, and +can be passed to PDF report generators. + +The generator uses PhantomJS to render the chart on the server-side. You need to +install it from link:https://phantomjs.org/[phantomjs.org]. After installation, +PhantomJS should be in your system path. If not, you can set the +[parameter]#phantom.exec# system property for the JRE to point to the PhantomJS +binary. + +To generate the SVG image content as a string (it's XML), simply call the +[methodname]#generate()# method in the [classname]#SVGGenerator# singleton and +pass it the chart configuration. + +[source,java] +---- +String svg = SVGGenerator.getInstance() + .generate(chart.getConfiguration()); +---- + +You can then use the SVG image as you like, for example, for download from a +[classname]#StreamResource#, or include it in a HTML, PDF, or other document. +You can use SVG tools such as the +link:https://xmlgraphics.apache.org/batik/[Batik] or +link:https://itextpdf.com/[iText] libraries to generate documents. For a complete +example, you can check out the Charts Export Demo from the Subversion repository +at [uri]#https://github.com/vaadin/charts/tree/master/chart-export-demo#. diff --git a/articles/charts/java-api/charts-basic-use.asciidoc b/articles/charts/java-api/charts-basic-use.asciidoc new file mode 100644 index 0000000000..b47020b88b --- /dev/null +++ b/articles/charts/java-api/charts-basic-use.asciidoc @@ -0,0 +1,485 @@ +--- +title: Basic Use +order: 3 +layout: page +--- + +[[charts.basic-use]] += Basic Use + +The [classname]#Chart# is a regular Vaadin component, which you can add to a +layout. You can give the chart type in the constructor or set it later in the +chart model. A chart has a height of 400 pixels and takes full width by default, +which settings you may often need to customize. + +[source, java] +---- +Chart chart = new Chart(ChartType.COLUMN); +chart.setWidth("400px"); // 100% by default +chart.setHeight("300px"); // 400px by default +... +layout.addComponent(chart); +---- + +The chart types are described in +<>. The +main parts of a chart are illustrated in <>. + +[[figure.charts.overview.elements]] +.Chart Elements +image::img/charts-elements-lo.png[] + +To actually display something in a chart, you typically need to configure the +following aspects: + +* Basic chart configuration +* Configure __plot options__ for the chart type +* Configure one or more __data series__ to display +* Configure __axes__ + +The plot options can be configured for each data series individually, or for +different chart types in mixed-type charts. + +[[charts.basic-use.configuration]] +== Basic Chart Configuration + +After creating a chart, you need to configure it further. At the least, you need +to specify the data series to be displayed in the configuration. + +Most methods available in the [classname]#Chart# object handle its basic Vaadin +component properties. All the chart-specific properties are in a separate +[classname]#Configuration# object, which you can access with the +[methodname]#getConfiguration()# method. + +[source, java] +---- +Configuration conf = chart.getConfiguration(); +conf.setTitle("Reindeer Kills by Predators"); +conf.setSubTitle("Kills Grouped by Counties"); +---- + +The configuration properties are described in more detail in +<>. + + +[[charts.basic-use.plotoptions]] +== Plot Options + +Many chart settings can be configured in the __plot options__ of the chart or +data series. Some of the options are chart type specific, as described later for +each chart type, while many are shared. + +For example, for line charts, you could disable the point markers as follows: + +[source, java] +---- +// Disable markers from lines +PlotOptionsLine plotOptions = new PlotOptionsLine(); +plotOptions.setMarker(new Marker(false)); +conf.setPlotOptions(plotOptions); +---- + +You can set the plot options for the entire chart or for each data series +separately, allowing also mixed-type charts, as described in +<>. + +The shared plot options are described in +<>. + + +[[charts.basic-use.data]] +== Chart Data Series + +The data displayed in a chart is stored in the chart configuration as a list of +[classname]#Series# objects. A new data series is added in a chart with the +[methodname]#addSeries()# method. + +[source, java] +---- +ListSeries series = new ListSeries("Diameter"); +series.setData(4900, 12100, 12800, + 6800, 143000, 125000, + 51100, 49500); +conf.addSeries(series); +---- + +The data can be specified with a number of different series types +[classname]#DataSeries#, [classname]#ListSeries#, [classname]#AreaListSeries#, +[classname]#RangeSeries#, and [classname]#ContainerDataSeries#. + +Data point features, such as color and size, can be defined in the versatile +[classname]#DataSeries#, which contains [classname]#DataSeriesItem# items. +Special chart types, such as box plots and 3D scatter charts require using their +own special data point type. + +The data series configuration is described in more detail in +<>. + + +[[charts.basic-use.axis]] +== Axis Configuration + +One of the most common tasks for charts is customizing its axes. At the least, +you usually want to set the axis titles. Usually you also want to specify labels +for data values in the axes. + +When an axis is categorical rather than numeric, you can define category labels +for the items. They must be in the same order and the same number as you have +values in your data series. + +[source, java] +---- +XAxis xaxis = new XAxis(); +xaxis.setCategories("Mercury", "Venus", "Earth", + "Mars", "Jupiter", "Saturn", + "Uranus", "Neptune"); +xaxis.setTitle("Planet"); +conf.addxAxis(xaxis); +---- + +Formatting of numeric labels can be done with JavaScript expressions, for +example as follows: + +[source, java] +---- +// Set the Y axis title +YAxis yaxis = new YAxis(); +yaxis.setTitle("Diameter"); +yaxis.getLabels().setFormatter( + "function() {return Math.floor(this.value/1000) + \'Mm\';}"); +yaxis.getLabels().setStep(2); +conf.addyAxis(yaxis); +---- + + +[[charts.basic-use.two-dimensional]] +== Displaying Multiple Series + +The simplest data, which we saw in the examples earlier in this chapter, is +one-dimensional and can be represented with a single data series. Most chart +types support multiple data series, which are used for representing +two-dimensional data. For example, in line charts, you can have multiple lines +and in column charts the columns for different series are grouped by category. +Different chart types can offer alternative display modes, such as stacked +columns. The legend displays the symbols for each series. + +[source, java] +---- +// The data +// Source: V. Maijala, H. Norberg, J. Kumpula, M. Nieminen +// Calf production and mortality in the Finnish +// reindeer herding area. 2002. +String predators[] = {"Bear", "Wolf", "Wolverine", "Lynx"}; +int kills[][] = { // Location: + {8, 0, 7, 0}, // Muddusjarvi + {30, 1, 30, 2}, // Ivalo + {37, 0, 22, 2}, // Oraniemi + {13, 23, 4, 1}, // Salla + {3, 10, 9, 0}, // Alakitka +}; + +// Create a data series for each numeric column in the table +for (int predator = 0; predator < 4; predator++) { + ListSeries series = new ListSeries(); + series.setName(predators[predator]); + + // The rows of the table + for (int location = 0; location < kills.length; location++) + series.addData(kills[location][predator]); + conf.addSeries(series); +} +---- + +The result for both regular and stacked column chart is shown in +<>. Stacking is enabled with +[methodname]#setStacking()# in [classname]#PlotOptionsColumn#. + +[[figure.charts.basic-use.two-dimensional]] +.Multiple Series in a Chart +image::img/charts-twodimensional.png[] + + +[[charts.basic-use.mixed]] +== Mixed Type Charts + +You can enable mixed charts by setting the chart type in the +[classname]#PlotOptions# object for a data series, which overrides the default +chart type set in the [classname]#Chart# object. You can also make color and +other settings for the series in the plot options. + +For example, to get a line chart, you need to use [classname]#PlotOptionsLine#. + +[source, java] +---- +// A data series as column graph +DataSeries series1 = new DataSeries(); +PlotOptionsColumn options1 = new PlotOptionsColumn(); +options1.setColor(SolidColor.BLUE); +series1.setPlotOptions(options1); +series1.setData(4900, 12100, 12800, + 6800, 143000, 125000, 51100, 49500); +conf.addSeries(series1); + +// A data series as line graph +ListSeries series2 = new ListSeries("Diameter"); +PlotOptionsLine options2 = new PlotOptionsLine(); +options2.setColor(SolidColor.RED); +series2.setPlotOptions(options2); +series2.setData(4900, 12100, 12800, + 6800, 143000, 125000, 51100, 49500); +conf.addSeries(series2); +---- + +In the above case, where we set the chart type for each series, the overall +chart type is irrelevant. + + +[[charts.basic-use.3d]] +== 3D Charts + +Most chart types can be made 3-dimensional by adding 3D options to the chart. +You can rotate the charts, set up the view distance, and define the thickness of +the chart features, among other things. You can also set up a 3D axis frame +around a chart. + +[[figure.charts.basic-use.3d.pie]] +.3D Charts +image::img/charts-3d-pie.png[] + +[[charts.basic-use.3d.options]] +=== 3D Options + +3D view has to be enabled in the [classname]#Options3d# configuration, along +with other parameters. Minimally, to have some 3D effect, you need to rotate the +chart according to the __alpha__ and __beta__ parameters. + +Let us consider a basic scatter chart for an example. The basic configuration +for scatter charts is described elsewhere, but let us look how to make it 3D. + +[source, java] +---- +Chart chart = new Chart(ChartType.SCATTER); +Configuration conf = chart.getConfiguration(); +... other chart configuration ... + +// In 3D! +Options3d options3d = new Options3d(); +options3d.setEnabled(true); +options3d.setAlpha(10); +options3d.setBeta(30); +options3d.setDepth(135); // Default is 100 +options3d.setViewDistance(100); // Default +conf.getChart().setOptions3d(options3d); +---- + +The 3D options are as follows: + +[parameter]#alpha#:: The vertical tilt (pitch) in degrees. + +[parameter]#beta#:: The horizontal tilt (yaw) in degrees. + +[parameter]#depth#:: Depth of the third (Z) axis in pixel units. + +[parameter]#enabled#:: Whether 3D plot is enabled. Default is [parameter]#false#. + +[parameter]#frame#:: Defines the 3D frame, which consists of a back, bottom, and side panels that +display the chart grid. + +[source, java] ++ +---- +Frame frame = new Frame(); +Back back=new Back(); +back.setColor(SolidColor.BEIGE); +back.setSize(1); +frame.setBack(back); +options3d.setFrame(frame); +---- +[parameter]#viewDistance#:: View distance for creating perspective distortion. Default is 100. + + + + +[[charts.basic-use.3d.plotoptions]] +=== 3D Plot Options + +The above sets up the general 3D view, but you also need to configure the 3D +properties of the actual chart type. The 3D plot options are chart type +specific. For example, a pie has __depth__ (or thickness), which you can +configure as follows: + +[source, java] +---- +// Set some plot options +PlotOptionsPie options = new PlotOptionsPie(); +... Other plot options for the chart ... + +options.setDepth(45); // Our pie is quite thick + +conf.setPlotOptions(options); +---- + + +[[charts.basic-use.3d.data]] +=== 3D Data + +For some chart types, such as pies and columns, the 3D view is merely a visual +representation for one- or two-dimensional data. Some chart types, such as +scatter charts, also feature a third, __depth axis__, for data points. Such data +points can be given as [classname]#DataSeriesItem3d# objects. + +The Z parameter is __depth__ and is not scaled; there is no configuration for +the depth or Z axis. Therefore, you need to handle scaling yourself as is done +in the following. + +[source, java] +---- +// Orthogonal data points in 2x2x2 cube +double[][] points = { {0.0, 0.0, 0.0}, // x, y, z + {1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}, + {-1.0, 0.0, 0.0}, + {0.0, -1.0, 0.0}, + {0.0, 0.0, -1.0}}; + +DataSeries series = new DataSeries(); +for (int i=0; i>. + +[[figure.charts.basic-use.3d.scatter]] +.3D Scatter Chart +image::img/charts-3d-scatter.png[] + + +ifdef::web[] +[[charts.basic-use.3d.distance]] +=== Distance Fade + +To add a bit more 3D effect, you can do some tricks, such as calculate the +distance of the data points from a viewpoint and set the marker size and color +according to the distance. + +[source, java] +---- +public double distanceTo(double[] point, double alpha, + double beta, double viewDist) { + final double theta = alpha * Math.PI / 180; + final double phi = beta * Math.PI / 180; + double x = viewDist * Math.sin(theta) * Math.cos(phi); + double y = viewDist * Math.sin(theta) * Math.sin(phi); + double z = - viewDist * Math.cos(theta); + return Math.sqrt(Math.pow(x - point[0], 2) + + Math.pow(y - point[1], 2) + + Math.pow(z - point[2], 2)); +} +---- + +Using the distance requires some assumptions about the scaling and such, but for +the data points (as defined earlier) in range -1.0 to +1.0 we could do as +follows: + +[source, java] +---- +... +DataSeriesItem3d item = new DataSeriesItem3d(x, y, + z * options3d.getDepth().doubleValue()); + +double distance = distanceTo(new double[]{x,y,z}, + alpha, beta, 2); + +int gr = (int) (distance*75); // Grayness +Marker marker = new Marker(true); +marker.setRadius(1 + 10 / distance); +marker.setFillColor(new SolidColor(gr, gr, gr)); +item.setMarker(marker); + +series.add(item); +---- + +Note that here the view distance is in the scale of the data coordinates, while +the distance defined in the 3D options has different definition and scaling. +With the above settings, which are somewhat exaggerated to illustrate the +effect, the result is shown in <>. + +[[figure.charts.basic-use.3d.fade]] +.3D Distance Fade +image::img/charts-3d-fade.png[] + +endif::web[] + + +[[charts.basic-use.themes]] +== Chart Themes + +The visual style and essentially any other chart configuration can be defined in +a __theme__. All charts shown in a UI may have only one theme, which can be set +with [methodname]#setTheme()# in the [classname]#ChartOptions#. + +The [classname]#ChartOptions# is a [classname]#UI# extension that is created and +referenced by calling the [methodname]#get()# as follows: + +[source, java] +---- +// Set Charts theme for the current UI +ChartOptions.get().setTheme(new SkiesTheme()); +---- + +The [classname]#VaadinTheme# is the default chart theme in Vaadin Charts. Other +available themes are [classname]#GrayTheme#, [classname]#GridTheme#, +[classname]#SkiesTheme#, and [classname]#HighChartsDefaultTheme#. + +A theme is a Vaadin Charts configuration that is used as a template for the +configuration when rendering the chart. + +[[charts.basic-use.lang-option]] +== Chart Language + +[classname]#Lang# class provides an opportunity for internationalizing charts. +You can specify a custom decimal point, names of months, weekdays and their abbreviated forms. +You can also specify the text to display when the chart contains no data. + +[source, java] +---- +final Lang fi = new Lang(); + +// Set language properties +fi.setDecimalPoint(","); + +fi.setMonths(new String[] { "Tammikuu", "Helmikuu", "Maaliskuu", + "Huhtikuu", "Toukokuu", "Kesäkuu", + "Heinäkuu", "Elokuu", "Syyskuu", + "Lokakuu", "Marraskuu", "Joulukuu" }); + +fi.setShortMonths(new String[] { "Tammi", "Helmi", "Maalis", + "Huhti", "Touko", "Kesä", + "Heinä", "Elo", "Syys", + "Loka", "Marras","Joulu" }); + +fi.setWeekdays(new String[] { "Ma", "Ti", "Ke", "To", "Pe", "La", "Su" }); +fi.setNoData("Data puuttuu"); +---- + +[classname]#Lang# option is global and can be set with [methodname]#setLang()# in the [classname]#ChartOptions#: + +[source, java] +---- +ChartOptions.get().setLang(fi); +---- \ No newline at end of file diff --git a/articles/charts/java-api/charts-charttypes.asciidoc b/articles/charts/java-api/charts-charttypes.asciidoc new file mode 100644 index 0000000000..6c7ab25a98 --- /dev/null +++ b/articles/charts/java-api/charts-charttypes.asciidoc @@ -0,0 +1,1751 @@ +--- +title: Chart Types +order: 4 +layout: page +--- + +[[charts.charttypes]] += Chart Types + +Vaadin Charts comes with over a dozen different chart types. You normally +specify the chart type in the constructor of the [classname]#Chart# object. The +available chart types are defined in the [classname]#ChartType# enum. You can +later read or set the chart type with the [literal]#++chartType++# property of +the chart model, which you can get with +[methodname]#getConfiguration().getChart()#. + +The supported chart types are: + +|=== +| <> | <> | <> | <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| `sparkline` +| <> +| <> +| <> +| +|=== + +Each chart type has its specific plot options and support its specific +collection of chart features. They also have specific requirements for the data +series. + +The basic chart types and their variants are covered in the following +subsections. + +[[charts.charttypes.line]] +== Line and Spline Charts + +Line charts connect the series of data points with lines. In the basic line +charts the lines are straight, while in spline charts the lines are smooth +polynomial interpolations between the data points. + +[[table.charttypes.line.subtypes]] +.Line Chart Subtypes +[options="header"] +|=============== +|ChartType|Plot Options Class +|[parameter]#LINE#|[classname]#PlotOptionsLine# +|[parameter]#SPLINE#|[classname]#PlotOptionsSpline# + +|=============== + + + +[[charts.charttypes.line.plotoptions]] +=== Plot Options + +The [parameter]#color# property in the line plot options defines the line color, +[parameter]#lineWidth# the line width, and [parameter]#dashStyle# the dash +pattern for the lines. + +See <> for plot options regarding markers and other +data point properties. The markers can also be configured for each data point. + + + +[[charts.charttypes.area]] +== Area Charts + +Area charts are like line charts, except that they fill the area between the line and some +threshold value on Y axis. The threshold depends on the chart type. In addition to the base type, chart +type combinations for spline interpolation and ranges are supported. + +[[table.charttypes.area.subtypes]] +.Area Chart Subtypes +[options="header"] +|=============== +|ChartType|Plot Options Class +|[parameter]#AREA#|[classname]#PlotOptionsArea# +|[parameter]#AREASPLINE#|[classname]#PlotOptionsAreaSpline# +|[parameter]#AREARANGE#|[classname]#PlotOptionsAreaRange# +|[parameter]#AREASPLINERANGE#|[classname]#PlotOptionsAreaSplineRange# + +|=============== + + + +In area range charts, the area between a lower and upper value is painted with a +transparent color. The data series must specify the minimum and maximum values +for the Y coordinates, defined either with [classname]#RangeSeries#, as +described in <>, or with [classname]#DataSeries#, described in +<>. + +[[charts.charttypes.area.plotoptions]] +=== Plot Options + +Area charts support __stacking__, so that multiple series are piled on top of +each other. You enable stacking from the plot options with +[methodname]#setStacking()#. The [parameter]#Stacking.NORMAL# stacking mode does +a normal summative stacking, while the [parameter]#Stacking.PERCENT# handles +them as proportions. + +The fill color for the area is defined with the [parameter]#fillColor# property +and its transparency with [parameter]#fillOpacity# (the opposite of +transparency) with a value between 0.0 and 1.0. + +The [parameter]#color# property in the line plot options defines the line color, +[parameter]#lineWidth# the line width, and [parameter]#dashStyle# the dash +pattern for the lines. + +See <> for plot options regarding markers and other +data point properties. The markers can also be configured for each data point. + + + +[[charts.charttypes.columnbar]] +== Column and Bar Charts + +Column and bar charts illustrate values as vertical or horizontal bars, +respectively. The two chart types are essentially equivalent, just as if the +orientation of the axes was inverted. + +Multiple data series, that is, two-dimensional data, are shown with thinner bars +or columns grouped by their category, as described in +<>. Enabling stacking with [methodname]#setStacking()# in plot +options stacks the columns or bars of different series on top of each other. + +You can also have [parameter]#COLUMNRANGE# charts that illustrate a range +between a lower and an upper value, as described in +<>. They require the use of +[classname]#RangeSeries# for defining the lower and upper values. + +[[table.charttypes.columnbar.subtypes]] +.Column and Bar Chart Subtypes +[options="header"] +|=============== +|ChartType|Plot Options Class +|[parameter]#COLUMN#|[classname]#PlotOptionsColumn# +|[parameter]#COLUMNRANGE#|[classname]#PlotOptionsColumnRange# +|[parameter]#BAR#|[classname]#PlotOptionsBar# + +|=============== + + + +See the API documentation for details regarding the plot options. + + +[[charts.charttypes.errorbar]] +== Error Bars + +An error bars visualize errors, or high and low values, in statistical data. +They typically represent high and low values in data or a multitude of standard +deviation, a percentile, or a quantile. The high and low values are represented +as horizontal lines, or "whiskers", connected by a vertical stem. + +While error bars technically are a chart type ( +[literal]#++ChartType.ERRORBAR++#), you normally use them together with some +primary chart type, such as a scatter or column chart. + +[[figure.charts.charttypes.errorbar]] +.Error Bars in a Scatter Chart +image::img/charts-errorbar.png[width="60%"] + +To display the error bars for data points, you need to have a separate data +series for the low and high values. The data series needs to use the +[classname]#PlotOptionsErrorBar# plot options type. + +[source, java] +---- +// Create a chart of some primary type +Chart chart = new Chart(ChartType.SCATTER); +chart.setWidth("600px"); +chart.setHeight("400px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Average Temperatures in Turku"); +conf.getLegend().setEnabled(false); + +// The primary data series +ListSeries averages = new ListSeries( + -6, -6.5, -4, 3, 9, 14, 17, 16, 11, 6, 2, -2.5); + +// Error bar data series with low and high values +DataSeries errors = new DataSeries(); +errors.add(new DataSeriesItem(0, -9, -3)); +errors.add(new DataSeriesItem(1, -10, -3)); +errors.add(new DataSeriesItem(2, -8, 1)); +... + +// Configure the stem and whiskers in error bars +PlotOptionsErrorbar barOptions = new PlotOptionsErrorbar(); +barOptions.setStemColor(SolidColor.GREY); +barOptions.setStemWidth(2); +barOptions.setStemDashStyle(DashStyle.DASH); +barOptions.setWhiskerColor(SolidColor.BROWN); +barOptions.setWhiskerLength(80, Sizeable.Unit.PERCENTAGE); // 80% of category width +barOptions.setWhiskerWidth(2); // Pixels +errors.setPlotOptions(barOptions); + +// The errors should be drawn lower +conf.addSeries(errors); +conf.addSeries(averages); +---- + +Note that you should add the error bar series first, to have it rendered lower +in the chart. + +[[charts.charttypes.errorbar.plotoptions]] +=== Plot Options + +Plot options for error bar charts have type [classname]#PlotOptionsErrorBar#. It +has the following chart-specific plot option properties: + +[parameter]#whiskerColor#, [parameter]#whiskerWidth#, and [parameter]#whiskerLength#:: + The color, width (vertical thickness), and length of the horizontal "whiskers" that indicate high and low values. + +[parameter]#stemColor#, [parameter]#stemWidth#, and [parameter]#stemDashStyle#:: + The color, width (thickness), and line style of the vertical "stems" that connect the whiskers. In box plot charts, which also have stems, they extend from the quadrintile box. + +[[charts.charttypes.boxplot]] +== Box Plot Charts + +Box plot charts display the distribution of statistical variables. A data point +has a median, represented with a horizontal line, upper and lower quartiles, +represented by a box, and a low and high value, represented with T-shaped +"whiskers". The exact semantics of the box symbols are up to you. + +Box plot chart is closely related to the error bar chart described in +<>, sharing the box and whisker elements. + +[[figure.charts.charttypes.boxplot]] +.Box Plot Chart +image::img/charts-boxplot.png[width="60%"] + +The chart type for box plot charts is [literal]#++ChartType.BOXPLOT++#. You +normally have just one data series, so it is meaningful to disable the legend. + +[source, java] +---- +Chart chart = new Chart(ChartType.BOXPLOT); +chart.setWidth("400px"); +chart.setHeight("300px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Orienteering Split Times"); +conf.getLegend().setEnabled(false); +---- + +[[charts.charttypes.boxplot.plotoptions]] +=== Plot Options + +The plot options for box plots have type [classname]#PlotOptionsBoxPlot#, which +extends the slightly more generic [classname]#PlotOptionsErrorBar#. They have +the following plot option properties: + +[parameter]#medianColor#,[parameter]#medianWidth#:: Color and width (vertical thickness) of the horizontal median indicator line. + +For example: + +[source, java] +---- +// Set median line color and thickness +PlotOptionsBoxplot plotOptions = new PlotOptionsBoxplot(); +plotOptions.setMedianColor(SolidColor.BLUE); +plotOptions.setMedianWidth(3); +conf.setPlotOptions(plotOptions); +---- + + +[[charts.charttypes.boxplot.datamodel]] +=== Data Model + +As the data points in box plots have five different values instead of the usual +one, they require using a special [classname]#BoxPlotItem#. You can give the +different values with the setters, or all at once in the constructor. + +[source, java] +---- +// Orienteering control point times for runners +double data[][] = orienteeringdata(); + +DataSeries series = new DataSeries(); +for (double cpointtimes[]: data) { + StatAnalysis analysis = new StatAnalysis(cpointtimes); + series.add(new BoxPlotItem(analysis.low(), + analysis.firstQuartile(), + analysis.median(), + analysis.thirdQuartile(), + analysis.high())); +} +conf.setSeries(series); +---- + +If the "low" and "high" attributes represent an even smaller quantile, or a +larger multiple of standard deviation, you can have outliers. You can plot them +with a separate data series, with + + + +[[charts.charttypes.scatter]] +== Scatter Charts + +Scatter charts display a set of unconnected data points. The name refers to +freely given X and Y coordinates, so the [classname]#DataSeries# or +[classname]#ContainerSeries# are usually the most meaningful data series types +for scatter charts. + +[[figure.charts.charttypes.scatter]] +.Scatter Chart +image::img/charts-scatter.png[width="60%"] + +The chart type of a scatter chart is [parameter]#ChartType.SCATTER#. Its options +can be configured in a [classname]#PlotOptionsScatter# object, although it does +not have any chart-type specific options. + +[source, java] +---- +Chart chart = new Chart(ChartType.SCATTER); +chart.setWidth("500px"); +chart.setHeight("500px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Random Sphere"); +conf.getLegend().setEnabled(false); // Disable legend + +PlotOptionsScatter options = new PlotOptionsScatter(); +// ... Give overall plot options here ... +conf.setPlotOptions(options); + +DataSeries series = new DataSeries(); +for (int i=0; i<300; i++) { + double lng = Math.random() * 2 * Math.PI; + double lat = Math.random() * Math.PI - Math.PI/2; + double x = Math.cos(lat) * Math.sin(lng); + double y = Math.sin(lat); + double z = Math.cos(lng) * Math.cos(lat); + + DataSeriesItem point = new DataSeriesItem(x,y); + Marker marker = new Marker(); + // Make settings as described later + point.setMarker(marker); + series.add(point); +} +conf.addSeries(series); +---- + +The result was shown in <>. + +[[charts.charttypes.scatter.markers]] +=== Data Point Markers + +Scatter charts and other charts that display data points, such as line and +spline charts, visualize the points with __markers__. The markers can be +configured with the [classname]#Marker# property objects available from the plot +options of the relevant chart types, as well as at the level of each data point, +in the [classname]#DataSeriesItem#. You need to create the marker and apply it +with the [methodname]#setMarker()# method in the plot options or the data series +item. + +For example, to set the marker for an individual data point: + +[source, java] +---- +DataSeriesItem point = new DataSeriesItem(x,y); +Marker marker = new Marker(); +// ... Make any settings ... +point.setMarker(marker); +series.add(point); +---- + + +[[charts.charttypes.scatter.markerproperties]] +=== Marker Shape Properties + +A marker has a [parameter]#lineColor# and a [parameter]#fillColor#, which are +set using a [classname]#Color# object. Both solid colors and gradients are +supported. You can use a [classname]#SolidColor# to specify a solid fill color +by RGB values or choose from a selection of predefined colors in the class. + +[source, java] +---- +// Set line width and color +marker.setLineWidth(1); // Normally zero width +marker.setLineColor(SolidColor.BLACK); + +// Set RGB fill color +int level = (int) Math.round((1-z)*127); +marker.setFillColor( + new SolidColor(255-level, 0, level)); +point.setMarker(marker); +series.add(point); +---- + +You can also use a color gradient with [classname]#GradientColor#. Both linear +and radial gradients are supported, with multiple color stops. + +Marker size is determined by the [parameter]#radius# parameter, which is given +in pixels. The actual visual radius includes also the line width. + +[source, java] +---- +marker.setRadius((z+1)*5); +---- + + +[[charts.charttypes.scatter.markersymbols]] +=== Marker Symbols + +Markers are visualized either with a shape or an image symbol. You can choose +the shape from a number of built-in shapes defined in the +[classname]#MarkerSymbolEnum# enum ( [parameter]#CIRCLE#, [parameter]#SQUARE#, +[parameter]#DIAMOND#, [parameter]#TRIANGLE#, or [parameter]#TRIANGLE_DOWN#). +These shapes are drawn with a line and fill, which you can set as described +above. + +[source, java] +---- +marker.setSymbol(MarkerSymbolEnum.DIAMOND); +---- + +You can also use any image accessible by a URL by using a +[classname]#MarkerSymbolUrl# symbol. If the image is deployed with your +application, such as in a theme folder, you can determine its URL as follows: + +[source, java] +---- +String url = VaadinServlet.getCurrent().getServletContext() + .getContextPath() + "/VAADIN/themes/mytheme/img/smiley.png"; +marker.setSymbol(new MarkerSymbolUrl(url)); +---- + +The line, radius, and color properties are not applicable to image symbols. + + + +[[charts.charttypes.bubble]] +== Bubble Charts + +Bubble charts are a special type of scatter charts for representing +three-dimensional data points with different point sizes. We demonstrated the +same possibility with scatter charts in <>, but the +bubble charts make it easier to define the size of a point by its third (Z) +dimension, instead of the radius property. The bubble size is scaled +automatically, just like for other dimensions. The default point style is also +more bubbly. + +[[figure.charts.charttypes.bubble]] +.Bubble Chart +image::img/charts-bubble.png[width="60%"] + +The chart type of a bubble chart is [parameter]#ChartType.BUBBLE#. Its options +can be configured in a [classname]#PlotOptionsBubble# object, which has a single +chart-specific property, [parameter]#displayNegative#, which controls whether +bubbles with negative values are displayed at all. More typically, you want to +configure the bubble [parameter]#marker#. The bubble tooltip is configured in +the basic configuration. The Z coordinate value is available in the formatter +JavaScript with [literal]#++this.point.z++# reference. + +The bubble radius is scaled linearly between a minimum and maximum radius. If +you would rather scale by the area of the bubble, you can approximate that by +taking square root of the Z values. + +ifdef::web[] +In the following example, we overlay a bubble chart over a world map background. +We customize the bubbles to be more round with spherical color gradient. Note +that square root is taken of the Z coordinate to +endif::web[] + +ifdef::web[] +[source, java] +---- +// Create a bubble chart +Chart chart = new Chart(ChartType.BUBBLE); +chart.setWidth("640px"); chart.setHeight("350px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Champagne Consumption by Country"); +conf.getLegend().setEnabled(false); // Disable legend +conf.getTooltip().setFormatter("this.point.name + ': ' + " + + "Math.round(100*(this.point.z * this.point.z))/100.0 + " + + "' M bottles'"); + +// World map as background +String url = VaadinServlet.getCurrent().getServletContext() + .getContextPath() + "/VAADIN/themes/mytheme/img/map.png"; +conf.getChart().setPlotBackgroundImage(url); + +// Show more bubbly bubbles with spherical color gradient +PlotOptionsBubble plotOptions = new PlotOptionsBubble(); +Marker marker = new Marker(); +GradientColor color = GradientColor.createRadial(0.4, 0.3, 0.7); +color.addColorStop(0.0, new SolidColor(255, 255, 255, 0.5)); +color.addColorStop(1.0, new SolidColor(170, 70, 67, 0.5)); +marker.setFillColor(color); +plotOptions.setMarker(marker); +conf.setPlotOptions(plotOptions); + +// Source: CIVC - Les expeditions de vins de Champagne en 2011 +DataSeries series = new DataSeries("Countries"); +Object data[][] = { + {"France", 181.6}, + {"United Kingdom", 34.53}, + {"United States", 19.37}, + ... +}; +for (Object[] country: data) { + String name = (String) country[0]; + double amount = (Double) country[1]; + Coordinate pos = getCountryCoordinates(name); + + DataSeriesItem3d item = new DataSeriesItem3d(); + item.setX(pos.longitude * Math.cos(pos.latitude/2.0 * + (Math.PI/160))); + item.setY(pos.latitude * 1.2); + item.setZ(Math.sqrt(amount)); + item.setName(name); + series.add(item); +} +conf.addSeries(series); + +// Set the category labels on the axis correspondingly +XAxis xaxis = new XAxis(); +xaxis.setExtremes(-180, 180); +... +conf.addxAxis(xaxis); + +// Set the Y axis title +YAxis yaxis = new YAxis(); +yaxis.setExtremes(-90, 90); +... +conf.addyAxis(yaxis); +---- +endif::web[] + + +[[charts.charttypes.pie]] +== Pie Charts + +A pie chart illustrates data values as sectors of size proportionate to the sum +of all values. The pie chart is enabled with [parameter]#ChartType.PIE# and you +can make type-specific settings in the [classname]#PlotOptionsPie# object as +described later. + +[source, java] +---- +Chart chart = new Chart(ChartType.PIE); +Configuration conf = chart.getConfiguration(); +... +---- + +A ready pie chart is shown in <>. + +[[figure.charts.charttypes.pie]] +.Pie Chart +image::img/charts-pie.png[width="60%"] + +[[charts.charttypes.pie.plotoptions]] +=== Plot Options + +The chart-specific options of a pie chart are configured with a +[classname]#PlotOptionsPie#. + +[source, java] +---- +PlotOptionsPie options = new PlotOptionsPie(); +options.setInnerSize("0"); +options.setSize("75%"); // Default +options.setCenter("50%", "50%"); // Default +conf.setPlotOptions(options); +---- + +[parameter]#innerSize#:: A pie with inner size greater than zero is a "donut". The inner size can be expressed either as number of pixels or as a relative percentage of the chart area with a string (such as "60%") See the section later on donuts. +[parameter]#size#:: The size of the pie can be expressed either as number of pixels or as a relative percentage of the chart area with a string (such as "80%"). The default size is 75%, to leave space for the labels. +[parameter]#center#:: The X and Y coordinates of the center of the pie can be expressed either as numbers of pixels or as a relative percentage of the chart sizes with a string. The default is "50%", "50%". + + + +[[charts.charttypes.pie.data]] +=== Data Model + +The labels for the pie sectors are determined from the labels of the data +points. The [classname]#DataSeries# or [classname]#ContainerSeries#, which allow +labeling the data points, should be used for pie charts. + +[source, java] +---- +DataSeries series = new DataSeries(); +series.add(new DataSeriesItem("Mercury", 4900)); +series.add(new DataSeriesItem("Venus", 12100)); +... +conf.addSeries(series); +---- + +If a data point, as defined as a [classname]#DataSeriesItem# in a +[classname]#DataSeries#, has the __sliced__ property enabled, it is shown as +slightly cut away from the pie. + +[source, java] +---- +// Slice one sector out +DataSeriesItem earth = new DataSeriesItem("Earth", 12800); +earth.setSliced(true); +series.add(earth); +---- + + +[[charts.charttypes.pie.donut]] +=== Donut Charts + +Setting the [parameter]#innerSize# of the plot options of a pie chart to a +larger than zero value results in an empty hole at the center of the pie. + +[source, java] +---- +PlotOptionsPie options = new PlotOptionsPie(); +options.setInnerSize("60%"); +conf.setPlotOptions(options); +---- + +As you can set the plot options also for each data series, you can put two pie +charts on top of each other, with a smaller one fitted in the "hole" of the +donut. This way, you can make pie charts with more details on the outer rim, as +done in the example below: + +[source, java] +---- +// The inner pie +DataSeries innerSeries = new DataSeries(); +innerSeries.setName("Browsers"); +PlotOptionsPie innerPieOptions = new PlotOptionsPie(); +innerPieOptions.setSize("60%"); +innerSeries.setPlotOptions(innerPieOptions); +... + +DataSeries outerSeries = new DataSeries(); +outerSeries.setName("Versions"); +PlotOptionsPie outerSeriesOptions = new PlotOptionsPie(); +outerSeriesOptions.setInnerSize("60%"); +outerSeries.setPlotOptions(outerSeriesOptions); +... +---- + +The result is illustrated in <>. + +[[figure.charts.charttypes.pie.donut]] +.Overlaid Pie and Donut Chart +image::img/charts-donut.png[width="60%"] + + + +[[charts.charttypes.gauge]] +== Gauges + +A gauge is an one-dimensional chart with a circular Y-axis, where a rotating +pointer points to a value on the axis. A gauge can, in fact, have multiple +Y-axes to display multiple scales. + +A __solid gauge__ is otherwise like a regular gauge, except that a solid color +arc is used to indicate current value instead of a pointer. The color of the +indicator arc can be configured to change according to color stops. + +Let us consider the following gauge: + +[source, java] +---- +Chart chart = new Chart(ChartType.GAUGE); +chart.setWidth("400px"); +chart.setHeight("400px"); +---- + +After the settings done in the subsequent sections, it will show as in +<>. + +[[figure.charts.charttypes.gauge]] +.A Gauge +image::img/charts-gauge.png[width="40%"] + +[[charts.charttypes.gauge.conf]] +=== Gauge Configuration + +The start and end angles of the gauge can be configured in the [classname]#Pane# +object of the chart configuration. The angles can be given as -360 to 360 +degrees, with 0 at the top of the circle. + +[source, java] +---- +Configuration conf = chart.getConfiguration(); +conf.setTitle("Speedometer"); +conf.getPane().setStartAngle(-135); +conf.getPane().setEndAngle(135); +---- + + +[[charts.charttypes.gauge.axis]] +=== Axis Configuration + +A gauge has only an Y-axis. You need to provide both a minimum and maximum value +for it. + +[source, java] +---- +YAxis yaxis = new YAxis(); +yaxis.setTitle("km/h"); + +// The limits are mandatory +yaxis.setMin(0); +yaxis.setMax(100); + +// Other configuration +yaxis.getLabels().setStep(1); +yaxis.setTickInterval(10); +yaxis.setTickLength(10); +yaxis.setTickWidth(1); +yaxis.setMinorTickInterval("1"); +yaxis.setMinorTickLength(5); +yaxis.setMinorTickWidth(1); +yaxis.setPlotBands(new PlotBand[]{ + new PlotBand(0, 60, SolidColor.GREEN), + new PlotBand(60, 80, SolidColor.YELLOW), + new PlotBand(80, 100, SolidColor.RED)}); +yaxis.setGridLineWidth(0); // Disable grid + +conf.addyAxis(yaxis); +---- + +You can do all kinds of other configuration to the axis - please see the API +documentation for all the available parameters. + + +[[charts.charttypes.gauge.data]] +=== Setting and Updating Gauge Data + +A gauge only displays a single value, which you can define as a data series of +length one, such as as follows: + +[source, java] +---- +ListSeries series = new ListSeries("Speed", 80); +conf.addSeries(series); +---- + +Gauges are especially meaningful for displaying changing values. You can use the +[methodname]#updatePoint()# method in the data series to update the single +value. + +[source, java] +---- +final TextField tf = new TextField("Enter a new value"); +layout.addComponent(tf); + +Button update = new Button("Update", new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + Integer newValue = new Integer((String)tf.getValue()); + series.updatePoint(0, newValue); + } +}); +layout.addComponent(update); +---- + + + +[[charts.charttypes.solidgauge]] +== Solid Gauges + +A solid gauge is much like a regular gauge described previously; a +one-dimensional chart with a circular Y-axis. However, instead of a rotating +pointer, the value is indicated by a rotating arc with solid color. The color of +the indicator arc can be configured to change according to the value using color +stops. + +Let us consider the following gauge: + +[source, java] +---- +Chart chart = new Chart(ChartType.SOLIDGAUGE); +chart.setWidth("400px"); +chart.setHeight("400px"); +---- + +After the settings done in the subsequent sections, it will show as in +<>. + +[[figure.charts.charttypes.solidgauge]] +.A Solid Gauge +image::img/charts-solidgauge.png[width="40%"] + +While solid gauge is much like a regular gauge, the configuration differs + +[[charts.charttypes.solidgauge.conf]] +=== Configuration + +The solid gauge must be configured in the drawing [classname]#Pane# of the chart +configuration. The gauge arc spans an angle, which is specified as -360 to 360 +degrees, with 0 degrees at the top of the arc. Typically, a semi-arc is used, +where you use -90 and 90 for the angles, and move the center lower than you +would have with a full circle. You can also adjust the size of the gauge pane; +enlargening it allows positioning tick labels better. + +[source, java] +---- +Configuration conf = chart.getConfiguration(); +conf.setTitle("Solid Gauge"); + +Pane pane = conf.getPane(); +pane.setSize("125%"); // For positioning tick labels +pane.setCenter("50%", "70%"); // Move center lower +pane.setStartAngle(-90); // Make semi-circle +pane.setEndAngle(90); // Make semi-circle +---- + +The shape of the gauge display is defined as the background of the pane. You at +least need to set the shape as either " [literal]#++arc++#" or " +[literal]#++solid++#". You typically also want to set background color and inner +and outer radius. + +[source, java] +---- +Background bkg = new Background(); +bkg.setBackgroundColor(new SolidColor("#eeeeee")); // Gray +bkg.setInnerRadius("60%"); // To make it an arc and not circle +bkg.setOuterRadius("100%"); // Default - not necessary +bkg.setShape("arc"); // solid or arc +pane.setBackground(bkg); +---- + + +[[charts.charttypes.solidgauge.axis]] +=== Axis Configuration + +A gauge only has an Y-axis. You must define the value range ( __min__ and +__max__). + +[source, java] +---- +YAxis yaxis = new YAxis(); +yaxis.setTitle("Pressure GPa"); +yaxis.getTitle().setY(-80); // Move 70 px upwards from center + +// The limits are mandatory +yaxis.setMin(0); +yaxis.setMax(200); + +// Configure ticks and labels +yaxis.setTickInterval(100); // At 0, 100, and 200 +yaxis.getLabels().setY(-16); // Move 16 px upwards +yaxis.setGridLineWidth(0); // Disable grid +---- + +You can configure color stops for the indicator arc. The stops are defined with +[classname]#Stop# objects having stop points from 0.0 to 1.0 and color values. + +[source, java] +---- +yaxis.setStops(new Stop(0.1f, SolidColor.GREEN), + new Stop(0.5f, SolidColor.YELLOW), + new Stop(0.9f, SolidColor.RED)); + +conf.addyAxis(yaxis); +---- + +Setting [methodname]#yaxis.getLabels().setRotationPerpendicular()# makes gauge +labels rotate perpendicular to the center. + +You can do all kinds of other configuration to the axis - please see the API +documentation for all the available parameters. + + +[[charts.charttypes.solidgauge.plotoptions]] +=== Plot Options + +Solid gauges do not currently have any chart type specific plot options. See +<> for common options. + +[source, java] +---- +PlotOptionsSolidgauge options = new PlotOptionsSolidgauge(); + +// Move the value display box at the center a bit higher +Labels dataLabels = new Labels(); +dataLabels.setY(-20); +options.setDataLabels(dataLabels); + +conf.setPlotOptions(options); +---- + + +[[charts.charttypes.solidgauge.data]] +=== Setting and Updating Gauge Data + +A gauge only displays a single value, which you can define as a data series of +length one, such as as follows: + +[source, java] +---- +ListSeries series = new ListSeries("Pressure MPa", 80); +conf.addSeries(series); +---- + +Gauges are especially meaningful for displaying changing values. You can use the +[methodname]#updatePoint()# method in the data series to update the single +value. + +[source, java] +---- +final TextField tf = new TextField("Enter a new value"); +layout.addComponent(tf); + +Button update = new Button("Update", new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + Integer newValue = new Integer((String)tf.getValue()); + series.updatePoint(0, newValue); + } +}); +layout.addComponent(update); +---- + + + +[[charts.charttypes.rangecharts]] +== Area and Column Range Charts + +Ranged charts display an area or column between a minimum and maximum value, +instead of a singular data point. They require the use of +[classname]#RangeSeries#, as described in +<>. An +area range is created with [parameter]#AREARANGE# chart type, and a column range +with [parameter]#COLUMNRANGE# chart type. + +Consider the following example: + +[source, java] +---- +Chart chart = new Chart(ChartType.AREARANGE); +chart.setWidth("400px"); +chart.setHeight("300px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Extreme Temperature Range in Finland"); +... + +// Create the range series +// Source: https://ilmatieteenlaitos.fi/lampotilaennatyksia +RangeSeries series = new RangeSeries("Temperature Extremes", + new Double[]{-51.5,10.9}, + new Double[]{-49.0,11.8}, + ... + new Double[]{-47.0,10.8});// +conf.addSeries(series); +---- + +The resulting chart, as well as the same chart with a column range, is shown in +<>. + +[[figure.charts.charttypes.rangecharts]] +.Area and Column Range Chart +image::img/charts-arearange.png[width="80%"] + + +[[charts.charttypes.polar]] +== Polar, Wind Rose, and Spiderweb Charts + +Most chart types having two axes can be displayed in __polar__ coordinates, +where the X axis is curved on a circle and Y axis from the center of the circle +to its rim. Polar chart is not a chart type in itself, but can be enabled for +most chart types with [methodname]#setPolar(true)# in the chart model +parameters. Therefore all chart type specific features are usable with polar +charts. + +Vaadin Charts allows many sorts of typical polar chart types, such as __wind +rose__, a polar column graph, or __spiderweb__, a polar chart with categorical +data and a more polygonal visual style. + +[source, java] +---- +// Create a chart of some type +Chart chart = new Chart(ChartType.LINE); + +// Enable the polar projection +Configuration conf = chart.getConfiguration(); +conf.getChart().setPolar(true); +---- + +You need to define the sector of the polar projection with a [classname]#Pane# +object in the configuration. The sector is defined as degrees from the north +direction. You also need to define the value range for the X axis with +[methodname]#setMin()# and [methodname]#setMax()#. + +[source, java] +---- +// Define the sector of the polar projection +Pane pane = new Pane(0, 360); // Full circle +conf.addPane(pane); + +// Define the X axis and set its value range +XAxis axis = new XAxis(); +axis.setMin(0); +axis.setMax(360); +---- + +The polar and spiderweb charts are illustrated in +<>. + +[[figure.charts.charttypes.polar]] +.Wind Rose and Spiderweb Charts +image::img/charts-polarspiderweb.png[width="80%"] + +[[charts.charttypes.polar.spiderweb]] +=== Spiderweb Charts + +A __spiderweb__ chart is a commonly used visual style of a polar chart with a +polygonal shape rather than a circle. The data and the X axis should be +categorical to make the polygonal interpolation meaningful. The sector is +assumed to be full circle, so no angles for the pane need to be specified. + +ifdef::web[Note the style settings done in the axis in the example below:] + +ifdef::web[] +[source, java] +---- +Chart chart = new Chart(ChartType.LINE); +... + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.getChart().setPolar(true); +... + +// Create the range series +// Source: https://ilmatieteenlaitos.fi/lampotilaennatyksia +ListSeries series = new ListSeries("Temperature Extremes", + 10.9, 11.8, 17.5, 25.5, 31.0, 33.8, + 37.2, 33.8, 28.8, 19.4, 14.1, 10.8); +conf.addSeries(series); + +// Set the category labels on the X axis correspondingly +XAxis xaxis = new XAxis(); +xaxis.setCategories("Jan", "Feb", "Mar", + "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"); +xaxis.setTickmarkPlacement(TickmarkPlacement.ON); +xaxis.setLineWidth(0); +conf.addxAxis(xaxis); + +// Configure the Y axis +YAxis yaxis = new YAxis(); +yaxis.setGridLineInterpolation("polygon"); // Webby look +yaxis.setMin(0); +yaxis.setTickInterval(10); +yaxis.getLabels().setStep(1); +conf.addyAxis(yaxis); +---- +endif::web[] + + + +[[charts.charttypes.funnel]] +== Funnel and Pyramid Charts + +Funnel and pyramid charts are typically used to visualize stages in a sales +processes, and for other purposes to visualize subsets of diminishing size. A +funnel or pyramid chart has layers much like a stacked column: in funnel from +top-to-bottom and in pyramid from bottom-to-top. The top of the funnel has width +of the drawing area of the chart, and dinimishes in size down to a funnel "neck" +that continues as a column to the bottom. A pyramid diminishes from bottom to +top and does not have a neck. + +[[figure.charts.charttypes.funnel]] +.Funnel and Pyramid Charts +image::img/charts-funnel.png[width="80%"] + +Funnels have chart type [parameter]#FUNNEL#, pyramids have [parameter]#PYRAMID#. + +The labels of the funnel blocks are by default placed on the right side of the +blocks, together with a connector. You can configure their style in the plot +options. +ifdef::web[] +See the following example. +[source, java] +---- +Chart chart = new Chart(ChartType.FUNNEL); +chart.setWidth("500px"); +chart.setHeight("350px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Monster Utilization"); +conf.getLegend().setEnabled(false); + +// Give more room for the labels +conf.getChart().setSpacingRight(120); + +// Configure the funnel neck shape +PlotOptionsFunnel options = new PlotOptionsFunnel(); +options.setNeckHeight(20, Sizeable.Unit.PERCENTAGE); +options.setNeckWidth(20, Sizeable.Unit.PERCENTAGE); + +// Style the data labels +DataLabelsFunnel dataLabels = new DataLabelsFunnel(); +dataLabels.setFormat("{point.name} ({point.y:,.0f})"); +dataLabels.setSoftConnector(false); +dataLabels.setColor(SolidColor.BLACK); +options.setDataLabels(dataLabels); + +conf.setPlotOptions(options); + +// Create the range series +DataSeries series = new DataSeries(); +series.add(new DataSeriesItem("Monsters Met", 340)); +series.add(new DataSeriesItem("Engaged", 235)); +series.add(new DataSeriesItem("Killed", 187)); +series.add(new DataSeriesItem("Tinned", 70)); +series.add(new DataSeriesItem("Eaten", 55)); +conf.addSeries(series); +---- +endif::web[] + +ifdef::web[] +[[charts.charttypes.funnel.plotoptions]] +=== Plot Options + +The funnel and pyramid options are configured with +[classname]#PlotOptionsFunnel# or [classname]#PlotOptionsFunnel#, respectively. + +In addition to common chart options, the chart types support the following +shared options: [parameter]#width#, [parameter]#height#, [parameter]#depth#, +[parameter]#allowPointSelect#, [parameter]#borderColor#, +[parameter]#borderWidth#, [parameter]#center#, [parameter]#slicedOffset#, and +[parameter]#visible#. See +<> for detailed descriptions. + +They have the following chart type specific properties: + +[parameter]#neckHeight#or[parameter]#neckHeightPercentage# (only funnel):: Height of the neck part of the funnel either as pixels or as percentage of the entire funnel height. +[parameter]#neckWidth#or[parameter]#neckWidthPercentage# (only funnel):: Width of the neck part of the funnel either as pixels or as percentage of the top of the funnel. +[parameter]#reversed#:: Whether the chart is reversed upside down from the normal direction from diminishing from the top to bottom. The default is __false__ for funnel and __true__ for pyramid. + + +endif::web[] + + +[[charts.charttypes.waterfall]] +== Waterfall Charts + +Waterfall charts are used for visualizing level changes from an initial level to +a final level through a number of changes in the level. The changes are given as +delta values, and you can have a number of intermediate totals, which are +calculated automatically. + +[[figure.charts.charttypes.waterfall]] +.Waterfall Charts +image::img/charts-waterfall.png[width="60%"] + +Waterfall charts have chart type [literal]#++WATERFALL++#. + +ifdef::web[For example:] + +ifdef::web[] +[source, java] +---- +Chart chart = new Chart(ChartType.WATERFALL); +chart.setWidth("500px"); +chart.setHeight("350px"); + +// Modify the default configuration a bit +Configuration conf = chart.getConfiguration(); +conf.setTitle("Changes in Reindeer Population in 2011"); +conf.getLegend().setEnabled(false); + +// Configure X axis +XAxis xaxis = new XAxis(); +xaxis.setCategories("Start", "Predators", "Slaughter", + "Reproduction", "End"); +conf.addxAxis(xaxis); + +// Configure Y axis +YAxis yaxis = new YAxis(); +yaxis.setTitle("Population (thousands)"); +conf.addyAxis(yaxis); +... +---- +endif::web[] + +ifdef::web[] +The example continues in the following subsections. +endif::web[] + +ifdef::web[] +[[charts.charttypes.waterfall.plotoptions]] +=== Plot Options + +Waterfall charts have plot options type [classname]#PlotOptionsWaterfall#, which +extends the more general options defined in [classname]#PlotOptionsColumn#. It +has the following chart type specific properties: + +[parameter]#upColor#:: Color for the positive values. +[parameter]#color#:: Default color for all the points. If [propertyname]#upColor# is +defined, [propertyname]#color# is used only for the negative values. + +In the following, we define the colors, as well as the style and placement of +the labels for the columns: + +ifdef::web[] +[source, java] +---- +// Define the colors +final Color balanceColor = SolidColor.BLACK; +final Color positiveColor = SolidColor.BLUE; +final Color negativeColor = SolidColor.RED; + +// Configure the colors +PlotOptionsWaterfall options = new PlotOptionsWaterfall(); +options.setUpColor(positiveColor); +options.setColor(negativeColor); + +// Configure the labels +Labels labels = new Labels(true); +labels.setVerticalAlign(VerticalAlign.TOP); +labels.setY(-20); +labels.setFormatter("Math.floor(this.y/1000) + 'k'"); +Style style = new Style(); +style.setColor(SolidColor.BLACK); +style.setFontWeight(FontWeight.BOLD); +labels.setStyle(style); +options.setDataLabels(labels); +options.setPointPadding(0); +conf.setPlotOptions(options); +---- +endif::web[] + +endif::web[] + +ifdef::web[] +[[charts.charttypes.waterfall.datamodel]] +=== Data Series + +The data series for waterfall charts consists of changes (deltas) starting from +an initial value and one or more cumulative sums. There should be at least a +final sum, and optionally intermediate sums. The sums are represented as +[classname]#WaterFallSum# data items, and no value is needed for them as they +are calculated automatically. For intermediate sums, you should set the +[parameter]#intermediate# property to [literal]#++true++#. + +ifdef::web[] +[source, java] +---- +// The data +DataSeries series = new DataSeries(); + +// The beginning balance +DataSeriesItem start = new DataSeriesItem("Start", 306503); +start.setColor(balanceColor); +series.add(start); + +// Deltas +series.add(new DataSeriesItem("Predators", -3330)); +series.add(new DataSeriesItem("Slaughter", -103332)); +series.add(new DataSeriesItem("Reproduction", +104052)); + +WaterFallSum end = new WaterFallSum("End"); +end.setColor(balanceColor); +end.setIntermediate(false); // Not intermediate (default) +series.add(end); + +conf.addSeries(series); +---- +endif::web[] + +endif::web[] + + +[[charts.charttypes.heatmap]] +== Heat Maps + +A heat map is a two-dimensional grid, where the color of a grid cell indicates a +value. + +[[figure.charts.charttypes.heatmap]] +.Heat Maps +image::img/charts-heatmap.png[width="60%"] + +Heat maps have chart type [literal]#++HEATMAP++#. + +ifdef::web[For example:] + +ifdef::web[] +[source, java] +---- + +Chart chart = new Chart(ChartType.HEATMAP); +chart.setWidth("600px"); +chart.setHeight("300px"); + +Configuration conf = chart.getConfiguration(); +conf.setTitle("Heat Data"); + +// Set colors for the extremes +conf.getColorAxis().setMinColor(SolidColor.AQUA); +conf.getColorAxis().setMaxColor(SolidColor.RED); + +// Set up border and data labels +PlotOptionsHeatmap plotOptions = new PlotOptionsHeatmap(); +plotOptions.setBorderColor(SolidColor.WHITE); +plotOptions.setBorderWidth(2); +plotOptions.setDataLabels(new DataLabels(true)); +conf.setPlotOptions(plotOptions); + +// Create some data +HeatSeries series = new HeatSeries(); +series.addHeatPoint( 0, 0, 10.9); // Jan High +series.addHeatPoint( 0, 1, -51.5); // Jan Low +series.addHeatPoint( 1, 0, 11.8); // Feb High +... +series.addHeatPoint(11, 1, -47.0); // Dec Low +conf.addSeries(series); + +// Set the category labels on the X axis +XAxis xaxis = new XAxis(); +xaxis.setTitle("Month"); +xaxis.setCategories("Jan", "Feb", "Mar", + "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"); +conf.addxAxis(xaxis); + +// Set the category labels on the Y axis +YAxis yaxis = new YAxis(); +yaxis.setTitle(""); +yaxis.setCategories("High C", "Low C"); +conf.addyAxis(yaxis); +---- +endif::web[] + +ifdef::web[] +[[charts.charttypes.heatmap.dataseries]] +=== Heat Map Data Series + +Heat maps require two-dimensional tabular data. The easiest way is to use +[classname]#HeatSeries#, as was done in the example earlier. You can add data +points with the [methodname]#addHeatPoint()# method, or give all the data at +once in an array with [methodname]#setData()# or in the constructor. + +If you need to use other data series type for a heat map, notice that the +semantics of the heat map data points are currently not supported by the +general-purpose series types, such as [classname]#DataSeries#. You can work +around this semantic limitation by specifying the [methodname]#X# (column), +[methodname]#Y# (row), and [methodname]#heatScore# by using the respective +[methodname]#X#, [methodname]#low#, and [methodname]#high# properties of the +general-purpose data series. + +Also note that while some other data series types allow updating the values one +by one, updating all the values in a heat map is very inefficient; it is faster +to simply replace the data series and then call [methodname]#chart.drawChart()#. + +endif::web[] + + +[[charts.charttypes.treemap]] +== Tree Maps + +A tree map is used to display hierarchical data. It consists of a group of +rectangles that contains other rectangles, where the size of a rectangle +indicates the item value. + +// This image is way too big and labels too small. +[[figure.charts.charttypes.treemap]] +.Tree Maps +image::img/charts-treemap.png[width="100%"] + +Tree maps have chart type [literal]#++TREEMAP++#. + +ifdef::web[For example:] + +ifdef::web[] +[source, java] +---- +Chart chart = new Chart(); + +PlotOptionsTreemap plotOptions = new PlotOptionsTreemap(); +plotOptions.setLayoutAlgorithm(TreeMapLayoutAlgorithm.STRIPES); +plotOptions.setAlternateStartingDirection(true); + +Level level = new Level(); +level.setLevel(1); +level.setLayoutAlgorithm(TreeMapLayoutAlgorithm.SLICEANDDICE); + +DataLabels dataLabels = new DataLabels(); +dataLabels.setEnabled(true); +dataLabels.setAlign(HorizontalAlign.LEFT); +dataLabels.setVerticalAlign(VerticalAlign.TOP); + +Style style = new Style(); +style.setFontSize("15px"); +style.setFontWeight(FontWeight.BOLD); + +dataLabels.setStyle(style); +level.setDataLabels(dataLabels); +plotOptions.setLevels(level); + +TreeSeries series = new TreeSeries(); + +TreeSeriesItem apples = new TreeSeriesItem("A", "Apples"); +apples.setColor(new SolidColor("#EC2500")); + +TreeSeriesItem bananas = new TreeSeriesItem("B", "Bananas"); +bananas.setColor(new SolidColor("#ECE100")); + +TreeSeriesItem oranges = new TreeSeriesItem("O", "Oranges"); +oranges.setColor(new SolidColor("#EC9800")); + +TreeSeriesItem anneA = new TreeSeriesItem("Anne", apples, 5); +TreeSeriesItem rickA = new TreeSeriesItem("Rick", apples, 3); +TreeSeriesItem paulA = new TreeSeriesItem("Paul", apples, 4); + +TreeSeriesItem anneB = new TreeSeriesItem("Anne", bananas, 4); +TreeSeriesItem rickB = new TreeSeriesItem("Rick", bananas, 10); +TreeSeriesItem paulB = new TreeSeriesItem("Paul", bananas, 1); + +TreeSeriesItem anneO = new TreeSeriesItem("Anne", oranges, 1); +TreeSeriesItem rickO = new TreeSeriesItem("Rick", oranges, 3); +TreeSeriesItem paulO = new TreeSeriesItem("Paul", oranges, 3); + +TreeSeriesItem susanne = new TreeSeriesItem("Susanne", 2); +susanne.setParent("Kiwi"); +susanne.setColor(new SolidColor("#9EDE00")); + +series.addAll(apples, bananas, oranges, anneA, rickA, paulA, + anneB, rickB, paulB, anneO, rickO, paulO, susanne); + +series.setPlotOptions(plotOptions); + +chart.getConfiguration().addSeries(series); + +chart.getConfiguration().setTitle("Fruit consumption"); +---- +endif::web[] + +ifdef::web[] +[[charts.charttypes.treemap.plotoptions]] +=== Plot Options + +Tree map charts have plot options type [classname]#PlotOptionsTreeMap#, which +extends the more general options defined in +[classname]#AbstractCommonOptionsColumn#. It has the following chart type +specific properties: + +[parameter]#allowDrillToNode#:: When enabled the user can click on a point which is a parent and zoom in on its children. Defaults to false. +[parameter]#alternateStartingDirection#:: Enabling this option will make the treemap alternate the drawing direction between vertical and horizontal. The next levels starting direction will always be the opposite of the previous. Defaults value is [literal]#++false++#. +[parameter]#layoutAlgorithm#:: This option decides which algorithm is used for setting position and dimensions of the points. Available algorithms are defined in [classname]##TreeMapLayoutAlgorithm## enum: [literal]#++SLICEANDDICE++#, [literal]#++STRIPES++#, [literal]#++SQUARIFIED++# and [literal]#++STRIP++#. Default value is [literal]#++SLICEANDDICE++#. +[parameter]#layoutStartingDirection#:: Defines which direction the layout algorithm will start drawing. Possible values are defined in [classname]##TreeMapLayoutStartingDirection## enum: [literal]#++HORIZONTAL++# and [literal]#++VERTICAL++#. Default value is [literal]#++VERTICAL++#. +[parameter]#levelIsConstant#:: Used together with the [methodname]#setLevels()# and [methodname]#setAllowDrillToNode()# options. When set to [literal]#++false++# the first level visible when drilling is considered to be level one. Otherwise the level will be the same as the tree structure. Defaults value is [literal]#++true++#. +[parameter]#levels#:: Set options on specific levels. Takes precedence over series options, but not point options. + + +endif::web[] + +ifdef::web[] +[[charts.charttypes.treemap.dataseries]] +=== Tree Map Data Series + +Tree maps require hierarchical data. The easiest way is to use +[classname]#TreeSeries# and [classname]#TreeSeriesItem#, as was done in the +example earlier. You can add data points with the [methodname]#add()# method, or +give all the data at once in a [classname]#Collection# with +[methodname]#setData()# or in the constructor. + +The item hierarchy is defined with the [methodname]#setParent()# method in the +[classname]#TreeSeriesItem# instance or in the constructor. Parent argument can +be either a [classname]#String# identifier or a [classname]#TreeSeriesItem# with +a non-null ID. If no [classname]#TreeSeriesItem# with matching ID is found or if +value is null then the parent will be rendered as a root item. + +endif::web[] + + +[[charts.charttypes.polygon]] +== Polygons + +A polygon can be used to draw any freeform filled or stroked shape in the +Cartesian plane. + +Polygons consist of connected data points. The [classname]#DataSeries# or +[classname]#ContainerSeries# are usually the most meaningful data series types +for polygon charts. In both cases, the [parameter]#x# and [parameter]#y# +properties should be set. + +[[figure.charts.charttypes.polygon]] +.Polygon combined with Scatter +image::img/charts-polygon.png[width="100%"] + +Polygons have chart type [literal]#++POLYGON++#. + +ifdef::web[For example:] + +ifdef::web[] +[source, java] +---- +Chart chart = new Chart(); +Configuration conf = chart.getConfiguration(); +conf.setTitle("Height vs Weight"); + +XAxis xAxis = conf.getxAxis(); +xAxis.setStartOnTick(true); +xAxis.setEndOnTick(true); +xAxis.setShowLastLabel(true); +xAxis.setTitle("Height (cm)"); + +YAxis yAxis = conf.getyAxis(); +yAxis.setTitle("Weight (kg)"); + +PlotOptionsScatter optionsScatter = new PlotOptionsScatter(); +DataSeries scatter = new DataSeries(); +scatter.setPlotOptions(optionsScatter); +scatter.setName("Observations"); + +scatter.add(new DataSeriesItem(160, 67)); +... +scatter.add(new DataSeriesItem(180, 75)); +conf.addSeries(scatter); + +DataSeries polygon = new DataSeries(); +PlotOptionsPolygon optionsPolygon = new PlotOptionsPolygon(); +optionsPolygon.setEnableMouseTracking(false); +polygon.setPlotOptions(optionsPolygon); +polygon.setName("Target"); + +polygon.add(new DataSeriesItem(153, 42)); +polygon.add(new DataSeriesItem(149, 46)); +... +polygon.add(new DataSeriesItem(173, 52)); +polygon.add(new DataSeriesItem(166, 45)); +conf.addSeries(polygon); +---- +endif::web[] + +ifdef::web[] +[[charts.charttypes.polygon.plotoptions]] +=== Plot Options + +Polygon charts options can be configured in a [classname]#PlotOptionsPolygon# +object, although it does not have any chart-type specific options. + +endif::web[] + + +[[charts.charttypes.flags]] +== Flags + +_Flags_ is a special chart type for annotating a series or the X axis with callout labels. Flags indicate interesting points or events on the series or axis. The flags are defined as items in a data series separate from the annotated series or axis. + +[[figure.charts.charttypes.flags]] +.Flags placed on an axis and a series +image::img/charts-flags.png[] + +Flags are normally used in a chart that has one or more normal data series. + +[[charts.charttypes.flags.plotoptions]] +=== Plot Options + +The flags are defined in a series that has its chart type specified by setting its plot options as [classname]#PlotOptionsFlags#. In addition to the common plot options properties, flag charts also have the following properties: + +[parameter]#shape#:: defines the shape of the marker. It can be one of `FLAG`, `CIRCLEPIN`, `SQUAREPIN`, or `CALLOUT`. +[parameter]#stackDistance#:: defines the vertical offset between flags on the same value in the same series. Defaults to 12. +[parameter]#onSeries#:: defines the ID of the series where the flags should be drawn on. If no ID is given, the flags are drawn on the X axis. +[parameter]#onKey#:: in chart types that have multiple keys (Y values) for a data point, the property defines on which key the flag is placed. Line and column series have only one key, `y`. In range, OHLC, and candlestick series, the flag can be placed on the `open`, `high`, `low`, or `close` key. Defaults to `y`. + +[[charts.charttypes.flags.data]] +=== Data + +The data for flags series require [propertyname]#x# and [propertyname]#title# properties, but can also have [propertyname]#text# property indicating the tooltip text. +The easiest way to set these properties is to use [classname]#FlagItem#. + +ifdef::web[] +[[charts.charttypes.flags.example]] +=== Example + +In the following, we annotate a time series as well as the axis with flags: + +[source,java] +---- +Chart chart = new Chart(ChartType.SPLINE); + +Configuration configuration = chart.getConfiguration(); +configuration.getTitle().setText("USD to EUR exchange rate"); +configuration.getxAxis().setType(AxisType.DATETIME); + +// A data series to annotate with flags +DataSeries dataSeries = new DataSeries(); +dataSeries.setId("dataseries"); +dataSeries.addData(new Number[][] { { 1434499200000l, 0.8821 }, + { 1434585600000l, 0.8802 }, { 1434672000000l, 0.8808 }, + { 1434844800000l, 0.8794 }, { 1434931200000l, 0.8818 }, + { 1435017600000l, 0.8952 }, { 1435104000000l, 0.8924 }, + { 1435190400000l, 0.8925 }, { 1435276800000l, 0.8955 } }); + +// Flags on the data series +DataSeries flagsOnSeries = new DataSeries(); +flagsOnSeries.setName("Flags on series"); +PlotOptionsFlags plotOptionsFlags = new PlotOptionsFlags(); +plotOptionsFlags.setShape(FlagShape.SQUAREPIN); +plotOptionsFlags.setOnSeries("dataseries"); +flagsOnSeries.setPlotOptions(plotOptionsFlags); +flagsOnSeries.add(new FlagItem(1434585600000l, "First Series Flag", + "First Series Flag Tooltip Text")); +flagsOnSeries.add(new FlagItem(1435017600000l, "Second Series Flag")); + +// Flags on the X axis +DataSeries flagsOnAxis = new DataSeries(); +flagsOnAxis.setPlotOptions(new PlotOptionsFlags()); +flagsOnAxis.setName("Flags on axis"); +flagsOnAxis.add(new FlagItem(1434844800000l, "First Axis Flag", + "First Axis Flag Tooltip Text")); +flagsOnAxis.add(new FlagItem(1435190400000l, "Second Axis Flag")); + +configuration.setSeries(dataSeries, flagsOnSeries, flagsOnAxis); + +---- +endif::web[] + +[[charts.charttypes.ohlc]] +== OHLC and Candlestick Charts + +An Open-High-Low-Close (OHLC) chart displays the change in price over a +period of time. The OHLC charts have chart type [literal]#++OHLC++#. An OHLC +chart consist of vertical lines, each having a horizontal +tickmark both on the left and the right side. The top and bottom ends of the +vertical line indicate the highest and lowest prices during the time period. The +tickmark on the left side of the vertical line shows the opening price and +the tickmark on the right side the closing price. + +[[figure.charts.charttypes.ohlc]] +.OHLC Chart. +image::img/charts-ohlc.png[] + +A candlestick chart is another way to visualize OHLC data. A candlestick has +a body and two vertical lines, called _wicks_. The body represents the +opening and closing prices. If the body is filled, the top edge of the body +shows the opening price and the bottom edge shows the closing price. If the +body is unfilled, the top edge shows the closing price and the bottom edge +the opening price. In other words, if the body is filled, the opening price +is higher than the closing price, and if not, lower. The upper wick +represents the highest price during the time period and the lower +wick represents the lowest price. A candlestick chart +has chart type [literal]#++CANDLESTICK++#. + +[[figure.charts.charttypes.candlestick]] +.Candlestick Chart. +image::img/charts-candlestick.png[] + +To attach data to an OHLC or a candlestick chart, you need to use a +[classname]#DataSeries# or a [classname]#ContainerSeries#. See +<> for more details. A data +series for an OHLC chart must contain [classname]#OhlcItem# objects. An +[classname]#OhlcItem# contains a date and the open, highest, lowest, + and close price on that date. + +[source, java] +---- +Chart chart = new Chart(ChartType.OHLC); +chart.setTimeline(true); + +Configuration configuration = chart.getConfiguration(); +configuration.getTitle().setText("AAPL Stock Price"); +DataSeries dataSeries = new DataSeries(); +for (StockPrices.OhlcData data : StockPrices.fetchAaplOhlcPrice()) { + OhlcItem item = new OhlcItem(); + item.setX(data.getDate()); + item.setLow(data.getLow()); + item.setHigh(data.getHigh()); + item.setClose(data.getClose()); + item.setOpen(data.getOpen()); + dataSeries.add(item); +} +configuration.setSeries(dataSeries); +chart.drawChart(configuration); + +---- + +When using [classname]#DataProviderSeries#, you need to specify the functions used for retrieving OHLC properties: +[methodName]#setX()#, [methodName]#setOpen()#, +[methodName]#setHigh()# [methodname]#setLow()#, and +[methodName]#setClose()#. + +[source, java] +---- +Chart chart = new Chart(ChartType.OHLC); +Configuration configuration = chart.getConfiguration(); + +// Create a DataProvider filled with stock price data +DataProvider dataProvider = initDataProvider(); +// Wrap the container in a data series +DataProviderSeries dataSeries = new DataProviderSeries<>(dataProvider); +dataSeries.setX(OhlcData::getDate); +dataSeries.setLow(OhlcData::getLow); +dataSeries.setHigh(OhlcData::getHigh); +dataSeries.setClose(OhlcData::getClose); +dataSeries.setOpen(OhlcData::getOpen); + +PlotOptionsOhlc plotOptionsOhlc = new PlotOptionsOhlc(); +plotOptionsOhlc.setTurboThreshold(0); +dataSeries.setPlotOptions(plotOptionsOhlc); + +configuration.setSeries(dataSeries); +---- + +Typically the OHLC and candlestick charts contain a lot of data, so it is +useful to use them with the timeline feature enabled. The timeline feature is + described in <>. + +[[charts.charttypes.ohlc.plotoptions]] +=== Plot Options +You can use a [classname]#DataGrouping# object to configure data grouping +properties. You set it in the plot options with [methodname]#setDataGrouping()#. +If the data points in a series are so dense that the spacing between two or +more points is less than value of the [propertyname]#groupPixelWidth# +property in the [classname]#DataGrouping#, the points will be grouped into +appropriate groups so that each group is more or less two pixels wide. +The [propertyname]#approximation# property in [classname]#DataGrouping# +specifies which data point value should represent the group. The +possible values are: [literal]#average#, [literal]#open#, +[literal]#high#, [literal]#low#, [literal]#close#, and +[literal]#sum#. + +Using [methodName]#setUpColor()# and [methodName]#setUpLineColor()# allow +setting the fill and border colors of the candlestick that indicate rise in +the values. The default colors are white. diff --git a/articles/charts/java-api/charts-configuration.asciidoc b/articles/charts/java-api/charts-configuration.asciidoc new file mode 100644 index 0000000000..64e1a39e10 --- /dev/null +++ b/articles/charts/java-api/charts-configuration.asciidoc @@ -0,0 +1,389 @@ +--- +title: Chart Configuration +order: 5 +layout: page +--- + +[[charts.configuration]] += Chart Configuration + +All the chart content configuration of charts is defined in a __chart model__ in +a [classname]#Configuration# object. You can access the model with the +[methodname]#getConfiguration()# method. + +The configuration properties in the [classname]#Configuration# class are +summarized in the following: + +* [methodname]#credits#: [classname]#Credits# (text, position, href, enabled) + +* [methodname]#labels#: [classname]#HTMLLabels# (html, style) + +* [methodname]#lang#: [classname]#Lang# (decimalPoint, thousandsSep, loading) + +* [methodname]#legend#: [classname]#Legend# (see <>) + +* [methodname]#pane#: [classname]#Pane# + +* [methodname]#plotoptions#: [classname]#PlotOptions# (see +<>) + +* [methodname]#series#: [interfacename]#Series# + +* [methodname]#subTitle#: [classname]#SubTitle# + +* [methodname]#title#: [classname]#Title# + +* [methodname]#tooltip#: [classname]#Tooltip# + +* [methodname]#xAxis#: [classname]#XAxis# (see <>) + +* [methodname]#yAxis#: [classname]#YAxis# (see <>) + + +For data configuration, see <>. + +[[charts.configuration.plotoptions]] +== Plot Options + +The plot options are used to configure the data series in the chart. +For example, line color could be specified for each line series. +Plot options can be set in the configuration of the entire chart or for each data series separately with [methodname]#setPlotOptions()#. +When the plot options are set to the entire chart, it will be applied to all the series in the chart. + +For example, the following enables stacking in column charts: + +[source,java] +---- +Chart chart = new Chart(); +Configuration configuration = chart.getConfiguration(); +PlotOptionsColumn plotOptions = new PlotOptionsColumn(); +plotOptions.setStacking(Stacking.NORMAL); +configuration.setPlotOptions(plotOptions); +---- + +Chart can contain multiple plot options which can be added dynamically with [methodname]#addPlotOptions()#. + +The developer can specify also the plot options for the particular data series as follows: + +[source,java] +---- +ListSeries series = new ListSeries(50, 60, 70, 80); +PlotOptionsColumn plotOptions = new PlotOptionsColumn(); +plotOptions.setStacking(Stacking.NORMAL); +series.setPlotOptions(plotOptions); +---- + +The plot options are defined in type-specific options classes or in a [classname]#PlotOptionsSeries# class which contains general options for all series types. +Type specific classes are applied to all the series with the same type in the chart. +If [classname]#PlotOptionsSeries# is used, it will be applied to all the series in the chart regardless of the type. + +Chart types are divided into several groups with common properties. +These groups are presented as abstract classes, that allow to use polymorphism for setting common properties for specific implementations. +The abstract classes and groups are the following: + +* [classname]#AreaOptions# -> [classname]#PlotOptionsArea#, [classname]#PlotOptionsArearange#, +[classname]#PlotOptionsAreaspline#, [classname]#PlotOptionsAreasplinerange# +* [classname]#ColumnOptions# -> [classname]#PlotOptionsBar#, [classname]#PlotOptionsColumn#, +[classname]#PlotOptionsColumnrange# +* [classname]#GaugeOptions# -> [classname]#PlotOptionsGauge#, [classname]#PlotOptionsSolidgauge# +* [classname]#PointOptions# -> [classname]#PlotOptionsLine#, [classname]#PlotOptionsSpline#, +[classname]#PlotOptionsScatter# +* [classname]#PyramidOptions# -> [classname]#PlotOptionsPyramid#, [classname]#PlotOptionsFunnel# +* [classname]#OhlcOptions# -> [classname]#PlotOptionsOhlc#, [classname]#PlotOptionsCandlestick# + +For example, to set the same [propertyname]#lineWidth# for [classname]#PlotOptionsLine# and [classname]#PlotOptionsSpline# use [classname]#PointOptions#. +[source, java] +---- +private void setCommonProperties(PointOptions options) { + options.setLineWidth(5); + options.setColor(SolidColor.RED); + options.setAnimation(false); +} +... +PlotOptionsSpline lineOptions = new PlotOptionsSpline(); +PlotOptionsLine splineOptions = new PlotOptionsLine(); +setCommonProperties(lineOptions); +setCommonProperties(splineOptions); +configuration.setPlotOptions(lineOptions, splineOptions); +---- + +See the API documentation of each chart type and its plot options class for more information about the chart-specific options. + +[[charts.configuration.plotoptions.other]] +=== Other Options + +The following options are supported by some chart types. + +[parameter]#width#:: Defines the width of the chart either by pixels or as a percentual proportion of the drawing area. +[parameter]#height#:: Defines the height of the chart either by pixels or as a percentual proportion of the drawing area. +[parameter]#depth#:: Specifies the thickness of the chart in 3D mode. +[parameter]#allowPointSelect#:: Specifies whether data points, in whatever way they are visualized in the particular chart type, can be selected by clicking on them. Defaults to __false__. +[parameter]#borderColor#:: Defines the border color of the chart elements. +[parameter]#borderWidth#:: Defines the width of the border in pixels. +[parameter]#center#:: Defines the center of the chart within the chart area by left and top coordinates, which can be specified either as pixels or as a percentage (as string) of the drawing area. The default is top 50% and left 50%. +[parameter]#slicedOffset#:: In chart types that support slices, such as pie and pyramid charts, specifies the offset for how far a slice is detached from other items. The amount is given in pixels and defaults to 10 pixels. +[parameter]#visible#:: Specifies whether or not a chart is visible. Defaults to __true__. + + + + +[[charts.configuration.axes]] +== Axes + +Different chart types may have one, two, or three axes; in addition to X and Y +axes, some chart types may have a color axis. These are represented by +[classname]#XAxis#, [classname]#YAxis#, and [classname]#ColorAxis#, +respectively. The X axis is usually horizontal, representing the iteration over +the data series, and Y vertical, representing the values in the data series. +Some chart types invert the axes and they can be explicitly inverted with +[methodname]#getChart().setInverted()# in the chart configuration. An axis has a +caption and tick marks at intervals indicating either numeric values or symbolic +categories. Some chart types, such as gauge, have only Y-axis, which is circular +in the gauge, and some such as a pie chart have none. + +The basic elements of X and Y axes are illustrated in +<>. + +[[figure.charts.configuration.axes.elements]] +.Chart Axis Elements +image::img/charts-axes-lo.png[] + +Axis objects are created and added to the configuration object with +[methodname]#addxAxis()# and [methodname]#addyAxis()#. + +[source,java] +---- +XAxis xaxis = new XAxis(); +xaxis.setTitle("Axis title"); +conf.addxAxis(xaxis); +---- + +A chart can have more than one Y-axis, usually when different series displayed +in a graph have different units or scales. The association of a data series with +an axis is done in the data series object with [methodname]#setyAxis()#. + +For a complete reference of the many configuration parameters for the axes, +please refer to the JavaDoc API documentation of Vaadin Charts. + +[[charts.configuration.axes.type]] +=== Axis Type + +Axes can be one of the following types, which you can set with +[methodname]#setType()#. The axis types are enumerated under +[classname]#AxisType#. [parameter]#LINEAR# is the default. + +[parameter]#LINEAR#(default):: For numeric values in linear scale. +[parameter]#LOGARITHMIC#:: For numerical values, as in the linear axis, but the axis will be scaled in the logarithmic scale. The minimum for the axis __must__ be a positive non-zero value ( [methodname]#log(0)# is not defined, as it has limit at negative infinity when the parameter approaches zero). +[parameter]#DATETIME#:: Enables date/time mode in the axis. The date/time values are expected to be given either as a [classname]#Date# object or in milliseconds since the Java (or Unix) date epoch on January 1st 1970 at 00:00:00 GMT. You can get the millisecond representation of Java [classname]#Date# with [methodname]#getTime()#. +[parameter]#CATEGORY#:: Enables using categorical data for the axis, as described in more detail later. With this axis type, the category labels are determined from the labels of the data points in the data series, without need to set them explicitly with [methodname]##setCategories()##. + + + +[[charts.configuration.axes.categories]] +=== Categories + +The axes display, in most chart types, tick marks and labels at some numeric +interval by default. If the items in a data series have a symbolic meaning +rather than numeric, you can associate __categories__ with the data items. The +category label is displayed between two axis tick marks and aligned with the +data point. In certain charts, such as column chart, where the corresponding +values in different data series are grouped under the same category. You can set +the category labels with [methodname]#setCategories()#, which takes the +categories as (an ellipsis) parameter list, or as an iterable. The list should +match the items in the data series. + +[source,java] +---- +XAxis xaxis = new XAxis(); +xaxis.setCategories("Mercury", "Venus", "Earth", + "Mars", "Jupiter", "Saturn", + "Uranus", "Neptune"); +---- + +You can only set the category labels from the data point labels by setting the +axis type to [parameter]#CATEGORY#, as described earlier. + + +[[charts.configuration.axes.labels]] +=== Labels + +The axes display, in most chart types, tick marks and labels at some numeric +interval by default. The format and style of labels in an axis is defined in a +[classname]#Labels# object, which you can get with [methodname]#getLabels()# +from the axis. + +[source,java] +---- +XAxis xaxis = new XAxis(); +... +Labels xlabels = xaxis.getLabels(); +xlabels.setAlign(HorizontalAlign.CENTER); // Default +xlabels.getStyle().setColor(SolidColor.GREEN); +xlabels.getStyle().setFontWeight(FontWeight.BOLD); +xlabels.setRotation(-45); +xlabels.setStep(2); // Every 2 major tick +---- + +Axis labels have the following configuration properties: + +[parameter]#align#:: Defines the alignment of the labels relative to the centers of the ticks. On left alignment, the left edges of labels are aligned at the tickmarks, and correspondingly the right side on right alignment. The default is determined automatically based on the direction of the axis and rotation of the labels. +[parameter]#distance#(only in polar charts):: Distance of labels from the perimeter of the plot area, in pixels. +[parameter]#enabled#:: Whether labels are enabled or not. Defaults to [parameter]#true#. +[parameter]#format#:: Formatting string for labels, as described in <>. Defaults to " [literal]#++{value}++#". +[parameter]#formatter#:: A JavaScript formatter for the labels, as described in +<>. The value is available in the +[literal]#++this.value++# property. The [literal]#++this++# object also has +[literal]#++axis++#, [literal]#++chart++#, [literal]#++isFirst++#, and +[literal]#++isLast++# properties. Defaults to: + + +[source,java] +---- +function() {return this.value;} +---- +[parameter]#maxStaggerLines#(only horizontal axis):: When labels on the horizontal (usually X) axis are displayed so densely that they would overlap, they are automatically placed on alternating lines in "staggered" fashion. When number of lines is not set manually with [parameter]##staggerLines##, this parameter defines the maximum number of such lines; value 1 disables automatic staggering. Default is 5 lines. +[parameter]#rotation#:: Defines rotation of labels in degrees. A positive value indicates rotation in +clockwise direction. Labels are rotated at their alignment point. Defaults to 0. + + +[source,java] +---- +Labels xlabels = xaxis.getLabels(); +xlabels.setAlign(HorizontalAlign.RIGHT); +xlabels.setRotation(-45); // Tilt 45 degrees CCW +---- +[parameter]#staggerLines#:: Defines number of lines for placing the labels to avoid overlapping. By default undefined, and the number of lines is automatically determined up to [parameter]#maxStaggerLines#. +[parameter]#step#:: Defines tick interval for showing labels, so that labels are shown at every +__n__th tick. The default step is automatically determined, along with +staggering, to avoid overlap. + + +[source,java] +---- +Labels xlabels = xaxis.getLabels(); +xlabels.setStep(2); // Every 2 major tick +---- +[parameter]#style#:: Defines style for labels. The property is a [classname]#Style# object, which has +to be created and set. + + +[source,java] +---- +Labels xlabels = xaxis.getLabels(); +Style xlabelsstyle = new Style(); +xlabelsstyle.setColor(SolidColor.GREEN); +xlabels.setStyle(xlabelsstyle); +---- +[parameter]#useHTML#:: Allows using HTML in custom label formats. Otherwise, HTML is quoted. Defaults to [literal]#false#. +[parameter]#x#,[parameter]#y#:: Offsets for the label's position, relative to the tick position. +X offset defaults to 0, but Y to [literal]#++null++#, which enables automatic positioning based on font size. + + +Gauge, pie, and polar charts allow additional properties. + +For a complete reference of the many configuration parameters for the labels, +please refer to the JavaDoc API documentation of Vaadin Charts. + + +[[charts.configuration.axes.extremes]] +=== Axis Range + +The axis range is normally set automatically to fit the data, but can also be +set explicitly. The __extremes__ property in the axis configuration defines the +minimum and maximum values of the axis range. You can set them either +individually with [methodname]#setMin()# and [methodname]#setMax()#, or together +with [methodname]#setExtremes()#. Changing the extremes programmatically +requires redrawing the chart with [methodname]#drawChart()#. + + + +[[charts.configuration.legend]] +== Legend + +The legend is a box that describes the data series shown in the chart. It is +enabled by default and is automatically populated with the names of the data +series as defined in the series objects, and the corresponding color symbol of +the series. + +[parameter]#alignment#:: Specifies the horizontal alignment of the legend box within the chart area. +Defaults to [constant]#HorizontalAlign.CENTER#. +[parameter]#enabled#:: Enables or disables the legend. Defaults to [literal]#true#. +[parameter]#layout#:: Specifies the layout direction of the legend items. Defaults to [constant]#LayoutDirection.HORIZONTAL#. +[parameter]#title#:: Specifies the title of the legend. +[parameter]#verticalAlign#:: Specifies the vertical alignment of the legend box within the chart area. +Defaults to [constant]#VerticalAlign.BOTTOM#. + +[source,java] +---- +Legend legend = configuration.getLegend(); +legend.getTitle().setText("City"); +legend.setLayout(LayoutDirection.VERTICAL); +legend.setAlign(HorizontalAlign.LEFT); +legend.setVerticalAlign(VerticalAlign.TOP); +---- + +The result can be seen in <>. + +[[figure.charts.configuration.legend]] +.Legend example +image::img/charts-configuration-legend.png[] + +[[charts.configuration.format]] +== Formatting Labels + +Data point values, tooltips, and tick labels are formatted according to +formatting configuration for the elements, with configuration properties +described earlier for each element. Formatting can be set up in the overall +configuration, for a data series, or for individual data points. The format can +be defined either by a format string or by JavaScript formatter, which are +described in the following. + +[[charts.configuration.format.string]] +=== Using Format Strings + +A formatting string contain free-form text mixed with variables. Variables are +enclosed in brackets, such as " [literal]#++Here {point.y} is a value at +{point.x}++#". In different contexts, you have at least the following variables +available: + +* [parameter]#value# in axis labels +* [parameter]#point.x#, [parameter]#point.x# in data points and tooltips +* [parameter]#series.name# in data points and tooltips +* [parameter]#series.color# in data points and tooltips + +Values can be formatted according to a formatting string, separated from the +variable name by a colon. + +For numeric values, a subset of C printf formatting specifiers is supported. For +example, " [literal]#++{point.y:%02.2f}++# would display a floating-point value +with two decimals and two leading zeroes, such as [literal]#++02.30++#. + +For dates, you can use a subset of PHP [methodname]#strftime()# formatting +specifiers. For example, " [literal]#++{value:%Y-%m-%d %H:%M:%S}++#" would +format a date and time in the ISO 8601 format. + + +[[charts.configuration.format.formatter]] +=== Using a JavaScript Formatter + +A JavaScript formatter is given in a string that defines a JavaScript function +that returns the formatted string. The value to be formatted is available in +[parameter]#this.value# for axis labels, or [parameter]#this.x#, +[parameter]#this.y# for data points. + +For example, to format tick labels on a chart axis, you could have: + +[source,java] +---- +YAxis yaxis = new YAxis(); +Labels ylabels = yaxis.getLabels(); +ylabels.setFormatter("function() {return this.value + ' km';}"); +---- + + +[[charts.configuration.format.simplified]] +=== Simplified Formatting + +Some contexts that display labels allow defining simple formatting for the +labels. For example, data point tooltips allow defining prefix, suffix, and +floating-point precision for the values. diff --git a/articles/charts/java-api/charts-data.asciidoc b/articles/charts/java-api/charts-data.asciidoc new file mode 100644 index 0000000000..52e37a9d85 --- /dev/null +++ b/articles/charts/java-api/charts-data.asciidoc @@ -0,0 +1,342 @@ +--- +title: Chart Data +order: 6 +layout: page +--- + +[[charts.data]] += Chart Data + +Chart data is stored in a data series model that contains information about the +visual representation of the data points in addition to their values. There are +a number of different types of series - [classname]#DataSeries#, +[classname]#ListSeries#, [classname]#AreaListSeries#, and +[classname]#RangeSeries#. + +[[charts.data.listseries]] +== List Series + +The [classname]#ListSeries# is essentially a helper type that makes the handling +of simple sequential data easier than with [classname]#DataSeries#. The data +points are assumed to be at a constant interval on the X axis, starting from the +value specified with the [literal]#++pointStart++# property (default is 0) at +intervals specified with the [literal]#++pointInterval++# property (default is +1.0). The two properties are defined in the [classname]#PlotOptions# for the +series. + +The Y axis values are given as constructor parameters or using the [methodname]#setData()# method. + +[source, java] +---- +ListSeries series = new ListSeries( + "Total Reindeer Population", + 181091, 201485, 188105); +PlotOptionsLine plotOptions = new PlotOptionsLine(); +plotOptions.setPointStart(1959); +series.setPlotOptions(plotOptions); +conf.addSeries(series); +---- + +You can also add them one by one with the [methodname]#addData()# method. + +If the chart has multiple Y axes, you can specify the axis for the series by its +index number using [methodname]#setyAxis()#. + + +[[charts.data.dataseries]] +== Generic Data Series + +The [classname]#DataSeries# can represent a sequence of data points at an +interval as well as scatter data. Data points are represented with the +[classname]#DataSeriesItem# class, which has [parameter]#x# and [parameter]#y# +properties for representing the data value. Each item can be given a category +name. + +[source, java] +---- +DataSeries series = new DataSeries(); +series.setName("Total Reindeer Population"); +series.add(new DataSeriesItem(1959, 181091)); +series.add(new DataSeriesItem(1960, 201485)); +series.add(new DataSeriesItem(1961, 188105)); +series.add(new DataSeriesItem(1962, 177206)); + +// Modify the color of one point +series.get(2).getMarker().setFillColor(SolidColor.RED); +conf.addSeries(series); +---- + +Data points are associated with some visual representation parameters: marker +style, selected state, legend index, and dial style (for gauges). Most of them +can be configured at the level of individual data series items, the series, or +in the overall plot options for the chart. The configuration options are +described in +<>. Some parameters, such as the sliced option for pie charts is +only meaningful to configure at item level. + +[[charts.data.dataseries.add]] +=== Adding and Removing Data Items + +New [classname]#DataSeriesItem# items are added to a series with the +[methodname]#add()# method. The basic method takes just the data item, but the +other method takes also two boolean parameters. If the [parameter]#updateChart# +parameter is [literal]#++false++#, the chart is not updated immediately. This is +useful if you are adding many points in the same request. + +The [parameter]#shift# parameter, when [literal]#++true++#, causes removal of +the first data point in the series in an optimized manner, thereby allowing an +animated chart that moves to left as new points are added. This is most +meaningful with data with even intervals. + +You can remove data points with the [methodname]#remove()# method in the series. +Removal is generally not animated, unless a data point is added in the same +change, as is caused by the [parameter]#shift# parameter for the +[methodname]#add()#. + + +[[charts.data.dataseries.update]] +=== Updating Data Items + +If you update the properties of a [classname]#DataSeriesItem# object, you need +to call the [methodname]#update()# method for the series with the item as the +parameter. Changing data in this way causes animation +of the change. + + +[[charts.data.dataseries.range]] +=== Range Data + +Range charts expect the Y values to be specified as minimum-maximum value pairs. +The [classname]#DataSeriesItem# provides [methodname]#setLow()# and +[methodname]#setHigh()# methods to set the minimum and maximum values of a data +point, as well as a number of constructors that accept the values. + +[source, java] +---- +RangeSeries series = + new RangeSeries("Temperature Extremes"); + +// Give low-high values in constructor +series.add(new DataSeriesItem(0, -51.5, 10.9)); +series.add(new DataSeriesItem(1, -49.0, 11.8)); + +// Set low-high values with setters +DataSeriesItem point = new DataSeriesItem(); +point.setX(2); +point.setLow(-44.3); +point.setHigh(17.5); +series.add(point); +---- + +The [classname]#RangeSeries# offers a slightly simplified way of adding ranged +data points, as described in <>. + +[[charts.data.rangeseries]] +== Range Series + +The [classname]#RangeSeries# is a helper class that extends +[classname]#DataSeries# to allow specifying interval data a bit easier, with a +list of minimum-maximum value ranges in the Y axis. You can use the series in +range charts, as described in +<>. + +For the X axis, the coordinates are generated at fixed intervals starting from the +value specified with the [literal]#++pointStart++# property (default is 0) at +intervals specified with the [literal]#++pointInterval++# property (default is +1.0). + +[[charts.data.rangeseries.data]] +=== Setting the Data + +The data in a [classname]#RangeSeries# is given as an array of minimum-maximum +value pairs for the Y value axis. The pairs are also represented as arrays. You +can pass the data using the ellipsis in the constructor or using +[methodname]#setData()#: + +[source, java] +---- +RangeSeries series = + new RangeSeries("Temperature Ranges", + new Double[]{-51.5,10.9}, + new Double[]{-49.0,11.8}, + ... + new Double[]{-47.0,10.8}); +conf.addSeries(series); +---- + +[[charts.data.dataproviderseries]] +== Data Provider Series + +[classname]#DataProviderSeries# is an adapter for using a Vaadin [interfacename]#DataProvider# as a [classname]#DataSeries# in a chart. Using [methodname]#setPointName()#, [methodname]#setX()#, and [methodname]#setY()# you can define which parts of the bean in the [interfacename]#DataProvider# are used in the chart. + +[NOTE] +[classname]#DataProviderSeries# is based on the data model in Vaadin Framework 8. +It replaces [classname]#ContainerDataSeries#, which allowed binding to a [interfacename]#Container# data model in Vaadin Framework 7. + +Let us consider an example, where we have a [interfacename]#DataProvider# which provides items of type [classname]#Order#. +The [classname]#Order# class has `getDescription()`, `getUnitPrice()`, and `getQuantity()` to be used for the chart: + +[source, java] +---- +public class Order { + private String description; + private int quantity; + private double unitPrice; + + public Order(String description, int quantity, double unitPrice) { + this.description = description; + this.quantity = quantity; + this.unitPrice = unitPrice; + } + + public String getDescription() { + return description; + } + + public int getQuantity() { + return quantity; + } + + public double getUnitPrice() { + return unitPrice; + } + + public double getTotalPrice() { + return unitPrice * quantity; + } +} +---- + +If we have a data provider containing a list of [classname]#Order# instances: + +[source, java] +---- +// The data +List orders = new ArrayList<>(); +orders.add(new Order("Domain Name", 3, 7.99)); +orders.add(new Order("SSL Certificate", 1, 119.00)); +orders.add(new Order("Web Hosting", 1, 19.95)); +orders.add(new Order("Email Box", 20, 0.15)); +orders.add(new Order("E-Commerce Setup", 1, 25.00)); +orders.add(new Order("Technical Support", 1, 50.00)); + +DataProvider dataProvider = new ListDataProvider<>(orders); +---- + +We can display the data in a [classname]#Chart# as follows: + +[source, java] +---- +// Create a chart and use the data provider +Chart chart = new Chart(ChartType.COLUMN); +Configuration configuration = chart.getConfiguration(); +DataProviderSeries series = new DataProviderSeries<>(dataProvider, Order::getTotalPrice); +configuration.addSeries(series); +---- + +[NOTE] +The [classname]#DataProviderSeries# constructor takes the `y` value provider as an optional argument. It can also be set using [methodname]#setY#. + +To make the chart look nicer, we can add a name for the series and show the order description when hovering points: +[source, java] +---- +series.setName("Order item quantities"); +series.setX(Order::getDescription); +---- + +To show the description also as x axis labels, we need to set the x axis type to category as the labels are strings: +[source, java] +---- +configuration.getxAxis().setType(AxisType.CATEGORY); +---- + +The result, with some added titles, is shown in <>. + +[[figure.charts.data.containerseries]] +.Chart Bound to a [interfacename]#DataProvider# +image::img/charts-dataprovider.png[] + +[NOTE] +Dynamic changes to the data will be loaded in the data series after calling the [methodname]#refreshAll()# method in the [classname]#DataProvider#. +This behavior can be disabled by setting the [propertyname]#automaticChartUpdateEnabled# property to [literal]#false# in [classname]#DataProviderSeries#. + +[[charts.data.drilldown]] +== Drill-Down + +Vaadin Charts allows drilling down from a chart to a more detailed view by +clicking an item in the top-level view. To enable the feature, you need to +provide a separate data series for each of the detailed views by calling the +[methodname]#addItemWithDrilldown()# method. When the user clicks on a +drill-down item, the current series is animated into the the linked drill-down +series. A customizable back button is provided to navigate back to the main +series, as shown in <>. + +[[figure.charts.data.drilldown.drilldown-details]] +.Detailed series after a drill-down +image::img/charts-drilldown-details.png[] + +There are two ways to use drill-down: synchronous and asynchronous. + +[[charts.data.drilldown.sync]] +=== Synchronous + +When using synchronous drill-down, you provide the top-level series and all the +series below it beforehand. The data is transferred to the client-side at the +same time and no client-server communication needs to happen for the drill-down. +The drill-down series must have an identifier, set with [methodname]#setId()#, +as shown below. + +[source, java] +---- +DataSeries series = new DataSeries(); + +DataSeriesItem mainItem = new DataSeriesItem("MSIE", 55.11); + +DataSeries drillDownSeries = new DataSeries("MSIE versions"); +drillDownSeries.setId("MSIE"); + +drillDownSeries.add(new DataSeriesItem("MSIE 6.0", 10.85)); +drillDownSeries.add(new DataSeriesItem("MSIE 7.0", 7.35)); +drillDownSeries.add(new DataSeriesItem("MSIE 8.0", 33.06)); +drillDownSeries.add(new DataSeriesItem("MSIE 9.0", 2.81)); + +series.addItemWithDrilldown(mainItem, drillDownSeries); +---- + + +[[charts.data.drilldown.async]] +=== Asynchronous + +When using asynchronous drill-down, you omit the drill-down series parameter. +Instead, you provide a callback method with +[methodname]#Chart.setDrillDownCallback()#. When the user clicks an item in the +series, the callback is called to provide a drill-down series. + +[source, java] +---- +DataSeries series = new DataSeries(); + +DataSeriesItem mainItem = new DataSeriesItem("MSIE", 55.11); + +series.addItemWithDrilldown(mainItem); + +chart.setDrilldownCallback(new DrilldownCallback() { + @Override + public Series handleDrilldown(DrilldownEvent event) { + DataSeries drillDownSeries = new DataSeries("MSIE versions"); + + drillDownSeries.add(new DataSeriesItem("MSIE 6.0", 10.85)); + drillDownSeries.add(new DataSeriesItem("MSIE 7.0", 7.35)); + drillDownSeries.add(new DataSeriesItem("MSIE 8.0", 33.06)); + drillDownSeries.add(new DataSeriesItem("MSIE 9.0", 2.81)); + + return drillDownSeries; + } +}); +---- + +You can use the event to decide what kind of series you want to return. The +event contains, for example, a reference to the item that was clicked. Note that +the same callback is used for all items. The callback can also return null, which will prevent a drilldown. diff --git a/articles/charts/java-api/charts-declarative.asciidoc b/articles/charts/java-api/charts-declarative.asciidoc new file mode 100644 index 0000000000..a17ec50b0b --- /dev/null +++ b/articles/charts/java-api/charts-declarative.asciidoc @@ -0,0 +1,325 @@ +--- +title: Declarative +order: 10 +layout: page +--- + +ifdef::web[] + +[[charts.declarative]] += Designing Charts Declaratively + +[[charts.declarative.introduction]] +== Introduction + +Vaadin UIs can be defined in a declarative way, as described in <>. +Vaadin Charts also supports this format. +In this tutorial, we go through how https://demo.vaadin.com/sampler/#addons/vaadin-charts/line-and-scatter/line[the Basic Line example] in the Vaadin Charts demo can be implemented using the declarative format. +The result is shown in <>. +[[figure.charts.declarative.basicline]] +.Basic line example +image::img/charts-declarative-basic-line.png[width=80%] + +[[charts.declarative.java]] +== Java Implementation + +Let us first consider a Java implementation of the example. +After creating the [classname]#Chart# object, you can configure it by using a [classname]#Configuration# object. +The configuration object itself contains various kinds of objects which can be used to configure different parts of the chart. +For example, [classname]#Legend# is used for configuring the chart legend. +The following code has been commented to indicate what kinds of configuration objects it uses. + +[source,java] +---- +// Chart +Chart chart = new Chart(); +chart.setHeight("450px"); +chart.setWidth("100%"); + +// Chart configuration +Configuration configuration = chart.getConfiguration(); +configuration.getChart().setType(ChartType.LINE); +configuration.getChart().setMarginRight(130); +configuration.getChart().setMarginBottom(25); + +// Title and tooltip configuration +configuration.getTitle().setText("Monthly Average Temperature"); +configuration.getSubTitle().setText("Source: WorldClimate.com"); +configuration.getTooltip() + .setFormatter( + "''+ this.series.name +'
'+this.x +': '+ this.y +'°C'"); + +// Axis configuration +configuration.getxAxis().setCategories("Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); +YAxis yAxis = configuration.getyAxis(); +yAxis.setMin(-5d); +yAxis.setTitle(new AxisTitle("Temperature (°C)")); +yAxis.getTitle().setAlign(VerticalAlign.MIDDLE); + +// Plot options +PlotOptionsLine plotOptions = new PlotOptionsLine(); +plotOptions.setDataLabels(new DataLabels(true)); +configuration.setPlotOptions(plotOptions); + +// Legend configuration +Legend legend = configuration.getLegend(); +legend.setLayout(LayoutDirection.VERTICAL); +legend.setAlign(HorizontalAlign.RIGHT); +legend.setVerticalAlign(VerticalAlign.TOP); +legend.setX(-10d); +legend.setY(100d); +legend.setBorderWidth(0); + +// Create data +ListSeries ls = new ListSeries(); +ls.setName("Tokyo"); +ls.setData(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6); +myChart.getConfiguration().addSeries(ls); +ls = new ListSeries(); +... +myChart.getConfiguration().addSeries(ls); +---- + +[[charts.declarative.separation]] +== Separation to Configuration and Data series + +When the declarative format is used, the chart is configured declaratively in an HTML file. +Java code is needed for some tasks, such as for handling events and data binding. +It can be used to provide any dynamic configuration, such as to populate the chart with dynamic data. +The `_id` attribute is used to map the design to a Java object, as described in <>. + +The first element in the HTML should be the same type as the design root, as described in <>. +In the following example, [elementname]#vaadin-vertical-layout# is used as the first element, so the design root must extend the corresponding [classname]#VerticalLayout# class. +Also, the `:expand` attribute is a parent setting of the [elementname]#vaadin-vertical-layout# element, as described in <>. + +The Java example presented earlier could then be separated into HTML design and Java code. +The HTML design would be as follows: + +[source,html] +---- + + + + + + + + + + +---- + +Let us then consider how to use it from Java code. +Before using declarative designs that contain charts, you need to configure the design reader for Vaadin Charts. +You need to set [classname]#ChartComponentMapper# as the component mapper. +Then, call [methodname]#Design.read()# to read the design. +You also need to define the chart data series in Java. + +[source,java] +---- +// Bind the root component +@DesignRoot(value="basic_line.html") +public class BasicLine extends VerticalLayout { + + Chart myChart; + + public BasicLine() { + // Configure the declarative design reader to read Vaadin Charts tags + Design.setComponentMapper(new ChartComponentMapper()); + + // Read the HTML file specified in the @DesignRoot annotation + Design.read(this); + + // Populate the chart with some data + ListSeries ls = new ListSeries(); + ls.setName("Tokyo"); + ls.setData(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, + 13.9, 9.6); + myChart.getConfiguration().addSeries(ls); + ls = new ListSeries(); + ... + myChart.getConfiguration().addSeries(ls); + } +} +---- + +[[charts.declarative.syntax]] +== Charts Declarative Syntax + +In the Charts design format, each configuration object is defined in its own element and the properties for the object are defined as the attributes of the element. +The naming convention of attributes is the same as described in <> + +The following elements are reserved in the HTML specification: [elementname]#title#, [elementname]#style#, [elementname]#area# and [elementname]#frame#. +These elements should be prefixed by `chart-` to make parsing behave correctly. +For example, title configuration is specified inside [elementname]#chart-title# element. +Another exception is with the `on-key` and `on-series` properties. They require `draw-` prefix. + +For example, [classname]#Legend# object could be defined in Java as follows: + +[source,java] +---- +Legend legend = configuration.getLegend(); +legend.setLayout(LayoutDirection.VERTICAL); +legend.setAlign(HorizontalAlign.RIGHT); +legend.setVerticalAlign(VerticalAlign.TOP); +legend.setX(-10d); +legend.setY(100d); +legend.setBorderWidth(0); +---- + +With the declarative format, the same legend configuration looks as follows: + +[source,html] +---- + +---- + +If the property is a list, the values are defined in its own element. +For example, category labels for the X axis can be defined as follows: + +[source,html] +---- + + Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + +---- + +In title elements, namely [elementname]#chart-title# and [elementname]#subtitle#, you can give the title text simply as the inner text of the element. +[source,html] +---- +Monthly Average Temperature +Source: WorldClimate.com +---- + +If a property is a configuration object itself, it is defined as a child element. +For example, the title of the Y axis is defined as follows: +[source,html] +---- + + Temperature (°C) + +---- + +Plot options are defined in a bit different way from other configuration objects. +They are given inside a [elementname]#plot-options# element. +The element must have a child element of the same name as the chart type to which they apply. +The plot options are then defined in the inner element. +For example, [classname]#PlotOptionsLine# is configured as follows: +[source,html] +---- + + + + + +---- + +[[charts.declarative.complete]] +== Complete Example + +When all the configuration objects in the example in <> are defined in the declarative format, the final design will look as follows: + +[source,html] +---- + + + + + + + Monthly Average Temperature + Source: WorldClimate.com + + + Temperature (°C) + + + Jan, Feb, Mar, Apr, May, Jun, + Jul, Aug, Sep, Oct, Nov, Dec + + + + + + + + + + + + +---- + +[[charts.declarative.howto]] +== How to Use It? + +Declaratively defined charts can be used like any other declarative design with Vaadin. +This is explained in more detail in <>. + +To use the declarative chart example presented earlier, you need to do the following steps: + +. Create a file named [filename]#basic_line.html# with the same content as described in <>. +. Add the [classname]#@DesignRoot# annotation to a class that extends [classname]#VerticalLayout#. +[source,java] +---- +// Bind the root component +@DesignRoot(value="basic_line.html") +---- +[start=3] +. Add a member field `Chart myChart` to the same class. +. Set the custom component mapper. +[source,java] +---- +// Set custom component mapper to read tags +Design.setComponentMapper(new ChartComponentMapper()); +---- +[start=5] +. Read the design. +[source,java] +---- +// Read the HTML file specified in the @DesignRoot annotation +Design.read(this); +---- +[start=6] +. Add code to populate `myChart` with data. +[source,java] +---- +// Populate data +ListSeries ls = new ListSeries(); +ls.setName("Tokyo"); +ls.setData(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6); +myChart.getConfiguration().addSeries(ls); +ls = new ListSeries(); +ls.setName("New York"); +ls.setData(-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5); +myChart.getConfiguration().addSeries(ls); +ls = new ListSeries(); +ls.setName("Berlin"); +ls.setData(-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0); +myChart.getConfiguration().addSeries(ls); +ls = new ListSeries(); +ls.setName("London"); +ls.setData(3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8); +myChart.getConfiguration().addSeries(ls); +---- + +After these steps, you can deploy your application with the chart. +You should see a similar chart as the one shown in <> + +[[charts.declarative.write]] +== Writing the Declarative format + +Vaadin Charts is also able to write its current content in the declarative format. +To see your chart as a declarative design, you can do the following steps. + +. Open the debug window as described in <>. +. Select from the tab [guilabel]#Examine component hierarchy# the sub-tab [guilabel]#Generate a declarative design# +. Select the chart in your UI. +. View the server console log to see the declarative design listing. + +endif::web[] diff --git a/articles/charts/java-api/charts-getting-started.asciidoc b/articles/charts/java-api/charts-getting-started.asciidoc new file mode 100644 index 0000000000..1ea057ef79 --- /dev/null +++ b/articles/charts/java-api/charts-getting-started.asciidoc @@ -0,0 +1,470 @@ +--- +title: Getting Started +order: 1 +layout: page +--- + +// Should the tutorial be included in the print edition? +// It has quite a bit redundancy with other content. +// If it's needed in some training or such, then include. +// Otherwise, maybe not. += Getting Started with Vaadin Charts + +// General notes: +// The tutorial has no screenshots. They would make it more visual. + +[[introduction]] +== Introduction + +This tutorial walks you through the steps needed to create a new Vaadin application and show some elegant charts in it. +We use Maven to set up the project and handle the dependencies. + +In this tutorial, you will learn how to: + +. Add Vaadin Charts to a project +. Create a simple line chart +. Create a combined chart with dual Y-axes +. Configure settings to change the look of a chart + +The final result of this tutorial can be explored in GitHub at https://github.com/vaadin/charts-tutorial/tree/master/server[github.com/vaadin/charts-tutorial/tree/master/server]. +Let us get to it. + +[[setup]] +== Project Setup + +To start off, we need to create a new project where we can add the charts. +For more details on this topic, please refer to <> and link:../../framework/addons/addons-overview[Vaadin Add-ons]. + +Here we use Maven to set up a project, using the command-line. +You can then be import the project into your IDE. +You can use the IDE to generate a new maven project using the `vaadin-archetype-application` archetype, but in the following example we do it on command-line. + +[subs="normal"] +---- +[prompt]#+++$+++# [command]#mvn# archetype:generate -DarchetypeGroupId=com.vaadin \ + -DarchetypeArtifactId=vaadin-archetype-application \ + -DarchetypeVersion=[replaceable]#8.0.0# +---- + +[NOTE] +Replace the version with the latest available. + +Archetype generation asks you a few parameters to set up the project. +You need to give at least [parameter]#groupId# and [parameter]#artifactId#. +You could answer as follows: + +[subs="normal"] +---- +Define value for property 'groupId': : [replaceable]#com.vaadin# +Define value for property 'artifactId': : [replaceable]#charts-tutorial# +Define value for property 'version': 1.0-SNAPSHOT: : kbd:[Enter] +Define value for property 'package': com.vaadin: : kbd:[Enter] +[INFO] Using property: theme = mytheme +Confirm properties configuration: +groupId: com.vaadin +artifactId: charts-tutorial +version: 1.0-SNAPSHOT +package: com.vaadin +theme: mytheme +Y: : kbd:[Enter] +---- + +You now should have a project generated for you. +It was created in a directory with the same name as the [parameter]#artifactId# parameter that you specified, such as, [filename]#charts-tutorial#. + +You can run the new project by issuing the following command: + +[subs="normal"] +---- +[prompt]#+++$+++# [command]#cd# [replaceable]#charts-tutorial# +[prompt]#+++$+++# [command]#mvn# vaadin:compile jetty:run +---- + +The command will compile all sources and start a local web server. +Wait until it says “Started Jetty Server” and navigate to http://localhost:8080 with your browser. +Note that you do not usually need to call [parameter]#vaadin:compile#. +It is only the needed in the following cases: +the first time you compile a new project created with the application archetype, +when you have changed the widget set somehow, or +if you add an add-on to your project, as we will see later. + +In the browser, you should see a button titled [guibutton]#Click Me#. +When you click it, the text [guilabel]#Thank you for clicking# appears below the button. +Great! +We can now move on to replace this button with a pretty chart! +Stop the web server by pressing kbd:[Ctrl+C] in the window where you started it. + +Let us then add the Vaadin Charts dependency to the project. +Open the [filename]#pom.xml# file and find the `` tag. +Add the following dependency declaration just before the end tag (``): + +[source,xml] +---- +... + + com.vaadin + vaadin-charts + 4.0.5 + +
+... +---- + +_You need to have a license for Vaadin Charts in order to be able to compile the widget set._ +You can get a free trial key from https://vaadin.com/directory#!addon/vaadin-charts[Vaadin Directory]. +Click the large orange [guibutton]#Free trial key# button on the right. +Then copy and paste the key into a file named [filename]#.vaadin.charts.developer.license# in your https://en.wikipedia.org/wiki/Home_directory#Default_home_directory_per_operating_system[home directory]. + +Once the key is in place, you can issue the following command to compile the widget set: + +[subs="normal"] +---- +[prompt]#+++$+++# [command]#mvn# clean vaadin:update-widgetset vaadin:compile +---- + +You have now created a new project and enabled Vaadin Charts in it. +You can now move on to create your charts. + +[[first.chart]] +== Creating Your First Chart + +On to actual programming! +Let us replace the button with an empty chart. +Open the [classname]#com.vaadin.MyVaadinUI# class and change the [methodname]#init()# method to the following: + +[source,java] +---- +protected void init(VaadinRequest request) { + final VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + setContent(layout); + + Chart chart = new Chart(); + layout.addComponent(chart); +} +---- + +Now run it by issuing 'mvn jetty:run' on the command line and load http://localhost:8080 in a browser. +You should see an empty white box with the title [guilabel]#Chart title# and a small [guilabel]#Vaadin Charts# in the bottom right corner. + +Let us make the title say something else. +Add the following lines at the end of the [methodname]#init()# method: + +[source,java] +---- +Configuration conf = chart.getConfiguration(); +conf.setTitle("Hello Charts!"); +---- + +Stop the old jetty process by pressing kbd:[Ctrl+C] and restart it by issuing 'mvn jetty:run' once more. +Reload the page in the browser. +The title of the chart should now read [guilabel]#Hello Charts!#. +As you see, changing the properties of a chart is done through an instance of the [classname]#Configuration# class. +When creating a chart, it automatically creates an instance of the [classname]#Configuration# class. +You can get a reference to it by calling [methodname]#getConfiguration()#. + +For more details, see <>. + +[[bind.data]] +=== Adding Some Data + +Let us add some real data! +Like any good TV chef, we have prepared a Java class that provides some example data for us to create charts from. +// This is a rather nuisance +Download the file from the https://raw.githubusercontent.com/vaadin/charts-tutorial/master/server/src/main/java/com/vaadin/ChartsData.java[tutorial repository in GitHub] and save it in the same package as the [classname]#MyVaadinUI# class. +Good, now we have some data to use. + +Next, we will turn our chart to a line chart. +This is done by altering the configuration. +Just add it to the end of the [methodname]#init()# method as follows: + +[source,java] +---- +conf.getChart().setType(ChartType.LINE); +---- + +The [classname]#ChartData# class contains data for the average shoe size per age for girls and boys. +Let us add the shoe size data for girls. +Data can be added to a chart by creating a [interfacename]#Series# object. +We use [classname]#DataSeries# and create individual [classname]##DataSeriesItem##s for each (shoe size, age) value pair. + +Continue the [methodname]#init()# method as follows: + +[source,java] +---- +ChartsData data = new ChartsData(); +DataSeries girls = new DataSeries("Girls"); +for(ShoeSizeInfo shoeSizeInfo : data.getGirlsData()) { + // Shoe size on the X-axis, age on the Y-axis + girls.add(new DataSeriesItem( + shoeSizeInfo.getSize(), + shoeSizeInfo.getAgeMonths()/12.0f)); +} +conf.addSeries(girls); +---- + +Now restart the server again (kbd:[Ctrl+C], `mvn jetty:run`), refresh your browser, and see that we now have a nice line chart! + +However, there is still something missing. +We have no units or labels for the X or Y axes. +This needs to be fixed. Add the following: + +[source,java] +---- +conf.getxAxis().setTitle("Shoe size (EU)"); +conf.getyAxis().setTitle("Age (Years)"); +---- + +Restart the server and refresh your browser. +Now the axes are labeled and we are well on our way! + +For more details on data series, see <>. + +[[bind.another.data]] +=== Adding Another Data Set to the Same Chart + +Now, let us add the same data for boys to the same chart. +This is as easy as adding a second series to the chart configuration. +We duplicate the code above and add the boy’s data series: + +[source,java] +---- +DataSeries boys = new DataSeries("Boys"); +for(ShoeSizeInfo shoeSizeInfo : data.getBoysData()) { + // Shoe size on the X-axis, age on the Y-axis + boys.add(new DataSeriesItem( + shoeSizeInfo.getSize(), + shoeSizeInfo.getAgeMonths()/12.0f)); +} +conf.addSeries(boys); +---- + +Restart the server and refresh your browser. +We now have two data sets, shown with two different colors and shapes. +The identifiers for both are shown in the legend below the chart. +Try clicking on any of the legend items – it toggles the visibility of the series! + +Finally, change the title of the chart to something that describes it, for example, "Shoe size per age for boys and girls". + +See also <>. + +[[configure.colors]] +=== Configuring the Colors + +Our chart looks OK, but it would be more intuitive to read if the data for girls is rendered using a color normally associated with girls, would it not? +Let us make the the girl data pink and the boy data light blue. + +The colors of the lines can be changed in two ways: + +. By modifying the theme, which specifies the colors for different series. +The first series will get the first color specified in the theme, the second will get the second color, and so on. + +. By specifying plot options for a specific series and setting the color in the plot options. + +In the following we specify the color by configuring plot options for the series. +Add the following to the end of the [methodname]#init# method: + +[source,java] +---- +PlotOptionsLine girlsOpts = new PlotOptionsLine(); +girlsOpts.setColor(SolidColor.HOTPINK); +girls.setPlotOptions(girlsOpts); + +PlotOptionsLine boysOpts = new PlotOptionsLine(); +boysOpts.setColor(SolidColor.BLUE); +boys.setPlotOptions(boysOpts); +---- + +Great! +Restart the server and reload your browser to see the finished chart. + +[[combination.chart]] +== Creating a Combination Chart + +We can now go ahead doing something more complex. +The [methodname]#ChartData# class also has historical weather data for Turku, Finland, during most of the year 2013. +Let us plot the temperature as a line chart and add columns for humidity to the same chart to create a combination chart. + +For more details on combination charts, see <>. + +[[combination.chart.preparations]] +=== Preparations + +To clean up our code a bit, let us extract the creation of the shoe size chart to a method called [methodname]#getShoeSizeChart(ChartsData)#. +This way, we can add the new weather chart without getting really messy code. +Go ahead and extract the method, after which the [methodname]#init()# method should look something as follows: + +[source,java] +---- +protected void init(VaadinRequest request) { + final VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + setContent(layout); + + ChartsData data = new ChartsData(); + layout.addComponent(getShoeSizeChart(data)); +} +---- + +Now create another new method, let us call it [methodname]#getWeatherChart(ChartsData)# and call it in the same way as the +[methodname]#getShoeSizeChart()# method in the [methodname]#init()# method: + +[source,java] +---- +layout.addComponent(getWeatherChart(data)); +---- + +As the temperature data is supposed to be shown as a line chart, we can start in much the same way as the shoe size chart, with just a few differences. +This time, we use a different kind of data series object, a [classname]#DataProviderSeries#, and configure the X-axis to be a date/time axis. +The result looks as follows: + +[source,java] +---- +private Chart getWeatherChart(ChartsData data) { + Chart chart = new Chart(); + Configuration conf = chart.getConfiguration(); + conf.setTitle("Turku, Finland 2013"); + + conf.getChart().setType(ChartType.LINE); + ListDataProvider dataProvider = new ListDataProvider<>(data.getWeatherData()); + DataProviderSeries temp = new DataProviderSeries<>(dataProvider); + + temp.setName("Temperature"); + temp.setX(WeatherInfo::getInstant); + temp.setY(WeatherInfo::getMaxTemp); + conf.addSeries(temp); + + conf.getxAxis().setTitle("Date"); + conf.getxAxis().setType(AxisType.DATETIME); + conf.getyAxis().setTitle("Temperature (°C)"); + return chart; +} +---- + +Let us look a little closer at the new series type. +The [classname]#DataProviderSeries# is bound to a normal [interfacename]#DataProvider# from Vaadin Framework. +In this case, we create a [classname]#ListDataProvider# that contains [classname]#WeatherInfo# beans. +We then create a [classname]#DataProviderSeries# instance, set the name of the series, and define the functions used for retrieving the X and Y data. +In this case, the value returned from a call to the [methodname]#getInstant()# method in [classname]#WeatherInfo# will be used as the value of X for each data point. +Similarly, the value returned by calling [methodname]#getMaxTemp()# will be used as the value of Y. + +Configuring the X-axis should be fairly self-explanatory. +It just sets the title and type of the axis. + +Restart the server and refresh your browser to see the new chart. +Awesome! We are well on our way. + +[[add.columns]] +=== Adding Columns and a Second Y-axis + +Let us continue by adding the humidity data to the chart. +For this set of data, we want to show it using columns instead of lines, which can be done by configuring suitable plot options for the series. +We will use the same provider bound to a new [classname]#DataProviderSeries# to provide the data: + +[source,java] +---- +ListDataProvider dataProvider = new ListDataProvider<>(weatherInfo); +DataProviderSeries humidity = new DataProviderSeries<>(dataProvider); + +humidity.setName("Humidity"); +humidity.setX(WeatherInfo::getInstant); +humidity.setY(WeatherInfo::getMeanHumidity); +humidity.setPlotOptions(new PlotOptionsColumn()); +conf.addSeries(humidity); +---- + +You can restart and refresh to see the results. +Now the chart does not look too nice, as the columns completely overlap the +temperature chart. + +Two things need to be done to make this chart better: + +. Change the order of the data series to make the temperature line render on top of the columns. +. Add a second Y-axis for the humidity, as it is in percent, while the temperature is in Celsius. + +Changing the order of the series is simple, just switch the order of the [methodname]#addSeries()# calls. +Adding a second Y-axis that scales the humidity data in a meaningful way can be done as follows: + +[source,java] +---- +YAxis humidityYAxis = new YAxis(); +humidityYAxis.setTitle("Humidity (%)"); +humidityYAxis.setMin(0); +humidityYAxis.setOpposite(true); +conf.addyAxis(humidityYAxis); +humidity.setyAxis(humidityYAxis); +---- + +Here we create a new [classname]#YAxis#, configure the title, set the minimum value, and move the axis to the opposite side of the chart. + +The final method should look something as follows: + +[source,java] +---- +private Chart getWeatherChart(ChartsData data) { + Chart chart = new Chart(); + Configuration conf = chart.getConfiguration(); + conf.setTitle("Turku, Finland 2013"); + + conf.getChart().setType(ChartType.LINE); + + ListDataProvider dataProvider = new ListDataProvider<>(data.getWeatherData()); + + DataProviderSeries temp = new DataProviderSeries<>(dataProvider); + + temp.setName("Temperature"); + temp.setX(WeatherInfo::getInstant); + temp.setY(WeatherInfo::getMaxTemp); + + conf.getxAxis().setTitle("Date"); + conf.getxAxis().setType(AxisType.DATETIME); + conf.getyAxis().setTitle("Temperature (°C)"); + + DataProviderSeries humidity = new DataProviderSeries<>(dataProvider); + + humidity.setName("Humidity"); + humidity.setX(WeatherInfo::getInstant); + humidity.setY(WeatherInfo::getMeanHumidity); + humidity.setPlotOptions(new PlotOptionsColumn()); + + conf.addSeries(humidity); + conf.addSeries(temp); + + YAxis humidityYAxis = new YAxis(); + humidityYAxis.setTitle("Humidity (%)"); + humidityYAxis.setMin(0); + humidityYAxis.setOpposite(true); + conf.addyAxis(humidityYAxis); + humidity.setyAxis(humidityYAxis); + + return chart; +} +---- + +Restart, refresh, and enjoy a better looking chart! + +== Downsampling Data + +One issue remains. +Drawing the chart is a bit slow, because of the huge amount of data packed into it. +To make it more efficient, we need to downsample the data in some way. +For very simple downsampling, we can use the Vaadin DataProvider filtering API. +Try something like the following filter to show only the values for each Sunday: + +[source,java] +---- +dataProvider.addFilter(point -> { + LocalDateTime date = LocalDateTime.ofInstant(point.getInstant(), ZoneId.of("Europe/Helsinki")); + return date.getDayOfWeek() == DayOfWeek.SUNDAY; +}); +---- + +This will make the data more sparse by only taking one data point every seven days. +Play around with the filter to see what you can accomplish! + +[[summary]] +== Summary + +Congratulations! +You now know the basics of how to get charts in your Vaadin application. +For further examples, please see the on-line demo at https://demo.vaadin.com/charts4[demo.vaadin.com/charts4]. diff --git a/articles/charts/java-api/charts-installing.asciidoc b/articles/charts/java-api/charts-installing.asciidoc new file mode 100644 index 0000000000..1c026c2e71 --- /dev/null +++ b/articles/charts/java-api/charts-installing.asciidoc @@ -0,0 +1,59 @@ +--- +title: Installing Vaadin Charts +order: 2 +layout: page +--- + +[[charts.installing]] += Installing Vaadin Charts + +As with most Vaadin add-ons, you can install Vaadin Charts as a Maven or Ivy +dependency in your project, or from an installation package. For general +instructions on installing add-ons, please see +<>. + +Vaadin Charts 4 requires Vaadin 8. + +Using Vaadin Charts requires a license key, which you must install before +compiling the widget set. The widget set must be compiled after setting up the +dependency or library JARs. + +For instructions on installing a license key, see <>. + +[[charts.installing.maven]] +== Maven Dependency + +The Maven dependency for Vaadin Charts is as follows: + +[subs="normal"] +---- +<dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-charts</artifactId> + <version>[replaceable]##4.0.5##</version> +</dependency> +---- +You also need to define the Vaadin add-ons repository if not already defined: + +[source,xml] +---- + + vaadin-addons + https://maven.vaadin.com/vaadin-addons + +---- + + +[[charts.installing.ivy]] +== Ivy Dependency + +The Ivy dependency, to be defined in [filename]#ivy.xml#, would be as follows: + +[subs="normal"] +---- +<dependency org="com.vaadin" name="vaadin-charts" + rev="**4.0.5**" /> +---- +It is generally recommended to use a fixed version number, but you can also use +[literal]#++latest.release++# to get the latest release. diff --git a/articles/charts/java-api/charts-migration-vaadin8.asciidoc b/articles/charts/java-api/charts-migration-vaadin8.asciidoc new file mode 100644 index 0000000000..8477a1019f --- /dev/null +++ b/articles/charts/java-api/charts-migration-vaadin8.asciidoc @@ -0,0 +1,45 @@ +--- +title: Charts 3 to Charts 4 Migration Guide +order: 10 +layout: page +--- + +[[charts4.migration]] += Charts 3 to Charts 4 Migration Guide + +[[charts4.migration.introduction]] +== Introduction + +Charts 4 is using Vaadin Framework 8. +Before migrating from Charts 3 to Charts 4, you need to migrate your application to Vaadin 8, see Vaadin Framework 8 migration guide. + +[[charts4.migration.changes]] +== Changes in Charts 4 + +Most of Vaadin Charts 3 API is compatible with Vaadin Charts 4.x. +There are two main changes: + +* Methods that use [classname]#Date# were deprecated, use [classname]#Instant# instead. +* [classname]#ContainerDataSeries# is deprecated, use [classname]#DataProviderSeries# instead, see <>. + +[[charts4.migration.using.compatibility]] +== Using Vaadin Charts compatibility package + +During migration from Charts 3 to Charts 4 you may want to use [classname]#ContainerDataSeries#. +To do that, add a dependency to the vaadin-charts-compatibility package: + +[subs="normal"] +---- +<dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-charts-compatibility</artifactId> + <version>[replaceable]##4.0.5##</version> +</dependency> +---- + +Afterwards, change the import statement for ContainerDataSeries to: + +[source, java] +---- +import com.vaadin.v7.addon.charts.model.ContainerDataSeries; +---- diff --git a/articles/charts/java-api/charts-migration.asciidoc b/articles/charts/java-api/charts-migration.asciidoc new file mode 100644 index 0000000000..a25c7c9236 --- /dev/null +++ b/articles/charts/java-api/charts-migration.asciidoc @@ -0,0 +1,311 @@ +--- +title: Charts 2 to 3 Migration Guide +order: 9 +layout: page +--- + +[[charts.migration]] += Charts 2 to Charts 3 Migration Guide + +[[charts.migration.introduction]] +== Introduction + +Most of Vaadin Charts 3 API is compatible with Vaadin Charts 2.x. It can thus be used as a drop-in replacement for any 2.x version with some minor fixes. +The objective of this document is to make the transition from Vaadin Charts 2.x to Vaadin Charts 3.x easier. + +[[charts.migration.nonmaven]] +== Note for non-Maven Users +Vaadin Charts 3 was restructured and now has a new JAR: [filename]#vaadin-charts-model-VERSION.jar#, which includes the model classes. If dependencies are managed manually the [filename]#vaadin-charts-model-VERSION.jar# can be found in [filename]#addon/lib/# folder of the ZIP file downloaded from https://vaadin.com/directory#!addon/vaadin-charts[Vaadin Directory] and needs to be added to the project. + +[[charts.migration.timeline]] +== Timeline +One of the big features of Vaadin Charts 3 for Java is dropping the old [classname]#Timeline# component. +The widgeset needs to be updated because the timeline was removed. To update the widgetset, run +[literal]#mvn vaadin:update-widgetset# or delete a reference to the timeline widgetset in a +project [filename]#gwt.xml# file. Vaadin Charts 3 introduced the new timeline mode that can be used in regular charts with time-typed X axis. +You can find out more about this feature in <>. + +[[charts.migration.abstractclass]] +== Changes in Abstract Classes + +[[charts.migration.abstractclass.axis]] +=== Axis +[classname]#Axis# has three properties, [propertyname]#min#, +[propertyname]#max#, and [propertyname]#axisIndex#, common for all axes. +All other properties were moved to concrete implementations. Use concrete +implementations ([classname]#XAxis#, [classname]#YAxis#, [classname]#ZAxis#) +instead of [classname]#Axis#. + +[[charts.migration.abstractclass.plotoptions]] +=== PlotOptions +Some properties in [classname]#AbstractPlotOptions# in Vaadin Charts 2.x were not +supported by all the subclasses. For example, setting [propertyname]#animation# in +[classname]#PlotOptionsPyramid# had no effect. In Vaadin Charts 3, properties +from [classname]#AbstractPlotOptions# were moved to concrete implementations, +that support the properties. In Vaadin Charts 3, instead of using +[classname]#AbstractPlotOptions#, use a specific implementation, such as [classname]#PlotOptionsArea#, +[classname]#PlotOptionsBar#, etc. + +All the chart types in Vaadin Charts 3 are divided into several groups with +common properties. These groups are presented as abstract classes, that allow to use polymorphism for setting common +properties for specific implementations. For example, to set the same [propertyname]#lineWidth# for +[classname]#PlotOptionsLine# and [classname]#PlotOptionsSpline# use [classname]#PointOptions#. +[source, java] +---- +private void setCommonProperties(PointOptions options) { + options.setLineWidth(5); + options.setColor(SolidColor.RED); + options.setAnimation(false); +} +... +PlotOptionsSpline plotOptions=new PlotOptionsSpline(); +PlotOptionsLine plotOptions2=new PlotOptionsLine(); +setCommonProperties(plotOptions); +setCommonProperties(plotOptions2); +series.setPlotOptions(plotOptions); +series2.setPlotOptions(plotOptions2); +---- +This is the list of abstract classes with their specific implementations: + +* [classname]#AreaOptions# -> [classname]#PlotOptionsArea#, [classname]#PlotOptionsArearange#, +[classname]#PlotOptionsAreaspline#, [classname]#PlotOptionsAreasplinerange# +* [classname]#ColumnOptions# -> [classname]#PlotOptionsBar#, [classname]#PlotOptionsColumn#, +[classname]#PlotOptionsColumnrange# +* [classname]#GaugeOptions# -> [classname]#PlotOptionsGauge#, [classname]#PlotOptionsSolidgauge# +* [classname]#PointOptions# -> [classname]#PlotOptionsLine#, [classname]#PlotOptionsSpline#, +[classname]#PlotOptionsScatter# +* [classname]#PyramidOptions# -> [classname]#PlotOptionsPyramid#, [classname]#PlotOptionsFunnel# +* [classname]#OhlcOptions# -> [classname]#PlotOptionsOhlc#, [classname]#PlotOptionsCandlestick# + +In other words, to set common properties for [classname]#PlotOptionsBar# and [classname]#PlotOptionsColumn# you +can use [classname]#ColumnOptions#, for [classname]#PlotOptionsArea# and [classname]#PlotOptionsArearange# you can use +[classname]#AreaOptions#, and so on. + + +[[charts.migration.classnamedif]] +== Changes in Class Names + +[[charts.migration.classnamedif.plotoptions]] +=== PlotOptions + +Apart from the new plot options for the new chart types ([classname]#PlotOptionsCandlestick#, [classname]#PlotOptionsFlags#, +and [classname]#PlotOptionsOhlc#), there has been the following changes in the names of the existing plot options: + +* [classname]#PlotOptionsAreaRange# -> [classname]#PlotOptionsArearange# +* [classname]#PlotOptionsAreaSpline# -> [classname]#PlotOptionsAreaspline# +* [classname]#PlotOptionsAreaSplineRange# -> [classname]#PlotOptionsAreasplinerange# +* [classname]#PlotOptionsColumnRange# -> [classname]#PlotOptionsColumnrange# +* [classname]#PlotOptionsHeatMap# -> [classname]#PlotOptionsHeatmap# +* [classname]#PlotOptionsSolidGauge# -> [classname]#PlotOptionsSolidgauge# +* [classname]#PlotOptionsTreeMap# -> [classname]#PlotOptionsTreemap# + +[[charts.migration.classnamedif.labels]] +=== Labels + +The [classname]#Labels# class was used in: + +* [classname]#PlotOptions# as data labels +* [classname]#XAxis# and [classname]#YAxis# as labels +* [classname]#DataSeriesItem# as data labels +* [classname]#TreeMapLevel# as data labels + +Given that not all [classname]#Labels# properties were useful in all the places where it was used, the class was split and the following classes have been created: + +* [classname]#DataLabelsFunnel# used in [classname]#PlotOptionsFunnel# and [classname]#PlotOptionsPyramid# +* [classname]#DataLabelsRange# used in [classname]#PlotOptionsArearange#, [classname]#PlotOptionsAreasplinerange# and [classname]#PlotOptionsColumnrange# +* [classname]#DataLabels# used in the rest of plot options implementations +* [classname]#Labels# used in [classname]#XAxis# and [classname]#YAxis# +* [classname]#Label# used in [classname]#Crosshair#, [classname]#PlotBand# and [classname]#Plotline# + +[[charts.migration.classnamedif.tooltips]] +=== Tooltips +[classname]#Tooltip# was split into two classes: [classname]#Tooltip# +and [classname]#SeriesTooltip#. The [classname]#Tooltip# class contains all the properties to configure tooltips in a chart. +These properties are used in every series in the chart. The [classname]#SeriesTooltip# class is a subset of tooltip properties +which can only be defined on the series level. For example, [propertyname]#useHTML# can only be defined on the chart level. +[classname]#Tooltip# should be used in the chart configuration object. +[classname]#SeriesTooltip# should be used in plot options implementations: +[classname]#PlotOptionsArea#, [classname]#PlotOptionsBar#, etc. + +[[charts.migration.classnamedif.other]] +=== Other + +* [classname]#MarkerStates# -> [classname]#States# +* [classname]#State# -> [classname]#Hover# and [classname]#Select# +* [classname]#CrosshairStyle# -> [classname]#Crosshair# +* [classname]#TreeMapLevel# -> [classname]#Level# +* [classname]#CreditPosition# -> [classname]#Position# +* [classname]#FramePanel# -> [classname]#Back#, [classname]#Bottom#, and [classname]#Side# + +[[charts.migration.methodnamedif]] +== Changes in Method Names + +[[charts.migration.methodnamedif.align]] +=== Align Properties + +The [propertyname]#align# property accepts values defined in the [classname]#HorizontalAlign# enum in all cases with the exception of [classname]#AxisTitle#. +In the [classname]#AxisTitle# class, the [propertyname]#align# property accepts values defined in the [classname]#VerticalAlign# enum. + +[[charts.migration.classnamedif.color]] +=== Color Properties +Setters of color properties now accept a [classname]#SolidColor# or +[classname]#GradientColor# parameter. A setter that accepts a +[classname]#String# parameter was removed. Instead of it use a +[classname]#SolidColor# constructor. +[source, java] +---- +plotOptions.setFillColor(new SolidColor("#ff0000")); +---- + +[[charts.migration.methodnamedif.crosshair]] +=== Crosshair +The crosshair definitions have been moved to the axis object for a better separation from the tooltip. +The [methodname]#setCrosshairs(CrosshairStyle)# method in [classname]#Tooltip# class is now +[methodname]#setCrosshair(Crosshair)# method in [classname]#XAxis# and [classname]#YAxis# classes. + +[[charts.migration.methodnamedif.plotoptions]] +=== Plot Options + +The API to configure plot options in [classname]#Configuration# class has changed. + +Renamed methods: + +* [methodname]#setPlotOptions()# -> [methodname]#addPlotOptions()# +* [methodname]#getAllPlotOptions()# -> [methodname]#getPlotOptions()# + +New methods: + +* [methodname]#setPlotOptions(AbstractPlotOptions ...)# +* [methodname]#getPlotOptions(ChartType)# + +The previous [methodname]#setPlotOptions()# method added new plot options to existing ones but the new method will reset the plot options. + +[[charts.migration.methodnamedif.size]] +=== Size related properties + +In order to follow Vaadin Framework standards, properties related to size ([propertyname]#size#, +[propertyname]#innerRadius#, [propertyname]#outerRadius#, [propertyname]#thickness#, +[propertyname]#whiskerLength#, and so forth) now have two different setters. +One of the setters has a single [classname]#String# parameter. +The other setter has a float and a [classname]#Unit# enum parameter. The [methodname]#setSizeAsPercentage()# +method was removed. + +As shown in the following example, a percentage width can be defined using both setters + +[source, java] +---- +PlotOptionsPyramid options = new PlotOptionsPyramid(); + +// Old setter +// options.setWidthAsPercentage(70); + +// Using float and Unit +options.setWidth(70, Unit.PERCENTAGE); + +// Using String setter +options.setWidth("70%"); +---- +* In [classname]#Pane#, [methodName]#setCenterXY(String, String)# is now [methodname]#setCenter(String, String)#. +The method [methodName]#setCenterXY(Number, Number)# was removed. +* In [classname]#PlotOptionsFunnel#, [classname]#PlotOptionsPie#, and [classname]#PlotOptionsPyramid#, +the method [methodname]#setCenter(Number, Number)# was removed. Use [methodname]#setCenter(Number, Number)# instead. + +[[charts.migration.methodnamedif.other]] +=== Other +* In [classname]#PlotOptionsLine#, [methodname]#setStepType()# is now [methodname]#setStep()#. +* In [classname]#XAxis#, [methodname]#setShowLastTickLabel()# is now [methodname]#setShowLastLabel()#. +* In [classname]#YAxis#, [methodname]#setMinorTickInterval(Number)# was removed, use +[methodname]#setMinorTickInterval(String)# instead. The [methodname]#setMinTickInterval()# method +was added. Be aware of mixing up these two methods. The [propertyname]#minorTickInterval# property specifies +the interval between minor ticks, while [propertyname]#minTickInterval# specifies the minimum tick interval allowed +in axis values. +* In [classname]#YAxis#, [classname]#Stop# is not an inner class anymore. + + + +[[charts.migration.example]] +== Example + +[[charts.migration.example.charts2]] +=== Original Charts 2 configuration + +[source, java] +---- +private Chart getChart() { + Chart chart = new Chart(); + + Configuration config = chart.getConfiguration(); + config.setTitle("Charts migration"); + config.getTitle().setHorizontalAlign(HorizontalAlign.LEFT); + + config.getTooltip().setCrosshairs( + new CrosshairStyle(10, SolidColor.BLACK, DashStyle.SOLID, 0), + new CrosshairStyle(5, "#880000", DashStyle.DOT, 1)); + + config.getLegend().setEnabled(false); + config.getTooltip().setEnabled(false); + + ListSeries ls = new ListSeries(); + ls.setName("Data"); + ls.setData(29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, + 194.1, 95.6, 54.4); + ls.setPlotOptions(new PlotOptionsAreaSpline()); + ls.getPlotOptions().setColor(SolidColor.BURLYWOOD); + ls.getPlotOptions().setDataLabels(new Labels(false)); + config.setSeries(ls); + return chart; +} +---- + +[[charts.migration.example.changes]] +=== Changes needed +Horizontal alignment of the title should now be set using the [methodname]#setAlign()# method. + +[classname]#CrosshairStyle# is now [classname]#Crosshair# and one instance should be set in both [classname]#XAxis# and [classname]#YAxis#. + +[classname]#PlotOptionsAreaSpline# is now [classname]#PlotOptionsAreaspline#. + +[classname]#DataLabels# should be used in the [methodname]#setDataLabels()# method instead of the [classname]#Labels# class. + +[[charts.migration.example.result]] +=== Resulting Charts 3 Configuration + +[source, java] +---- +private Chart getChart() { + Chart chart = new Chart(); + + Configuration config = chart.getConfiguration(); + config.setTitle("Charts migration"); + config.getTitle().setAlign(HorizontalAlign.LEFT); + + Crosshair xCrossHair = new Crosshair(); + xCrossHair.setColor(SolidColor.BLACK); + xCrossHair.setDashStyle(DashStyle.SOLID); + xCrossHair.setWidth(10); + xCrossHair.setZIndex(0); + config.getxAxis().setCrosshair(xCrossHair); + + Crosshair yCrossHair = new Crosshair(); + yCrossHair.setColor(new SolidColor("#880000")); + yCrossHair.setDashStyle(DashStyle.DOT); + yCrossHair.setWidth(5); + yCrossHair.setZIndex(1); + config.getyAxis().setCrosshair(yCrossHair); + + config.getLegend().setEnabled(false); + config.getTooltip().setEnabled(false); + + ListSeries ls = new ListSeries(); + ls.setName("Data"); + ls.setData(29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, + 194.1, 95.6, 54.4); + PlotOptionsAreaspline plotOptions = new PlotOptionsAreaspline(); + plotOptions.setColor(SolidColor.BURLYWOOD); + plotOptions.setDataLabels(new DataLabels(false)); + ls.setPlotOptions(plotOptions); + config.setSeries(ls); + + return chart; +} +---- diff --git a/articles/charts/java-api/charts-timeline.asciidoc b/articles/charts/java-api/charts-timeline.asciidoc new file mode 100644 index 0000000000..4a0f9fea14 --- /dev/null +++ b/articles/charts/java-api/charts-timeline.asciidoc @@ -0,0 +1,107 @@ +--- +title: Timeline +order: 8 +layout: page +--- + +[[charts.timeline]] += Timeline + +A charts timeline feature allows selecting different time ranges for which to display the chart data, +as well as navigating between such ranges. It is especially useful when working with large time +<>. +Adding a timeline to your chart is very easy - just set the 'timeline' property to 'true', +that is, call [methodname]#setTimeline(true)#. +You can enable the timeline in a chart that displays one or more time series. +Most of the chart types support the timeline. +There are few exceptions which are listed here: +<>, +<>, +<>, +<>, and +<>. +Enabling the timeline in these chart types will raise a runtime exception. + +You can change the time range using the navigator at the bottom of the chart. +To be able to use the navigator, the X values of the corresponding data series should be of the type [classname]#Date#. +Also integer values can be used, in which case they are interpreted as milliseconds since the 01/01/1970 epoch. +If you have multiple series, the first one is presented in the navigator. + +[[figure.charts.timeline.timeline-intro]] +.Vaadin chart with a timeline. +image::img/timeline_intro_screen.png[] + +Another way to change the time range is to use the range selector. The range selector includes +a set of predefined time ranges for easier navigation, for example, 1 month, 3 month, 6 month etc. To specify a custom time range, you can +use range selector text fields for setting start and end of the time interval. + +You can configure the range navigator and selector in the chart configuration. +To show or hide the navigator, call [methodname]#setEnabled()#. You can use [classname]#Navigator# and +[classname]#PlotOptionsSeries# to change the appearance of the navigator. +[source, java] +---- +Navigator navigator = configuration.getNavigator(); +navigator.setEnabled(true); +navigator.setMargin(75); +PlotOptionsSeries plotOptions=new PlotOptionsSeries(); +plotOptions.setColor(SolidColor.BROWN); +navigator.setSeries(plotOptions); +---- + +You can change the style of the range selector buttons with the +[methodname]#setButtonTheme(theme)# method and specify the index +of the button to appear pre-selected with the [methodname]#setSelected(index)# method. + +[source, java] +---- +RangeSelector rangeSelector = new RangeSelector(); +rangeSelector.setSelected(4); +ButtonTheme theme = new ButtonTheme(); +Style style = new Style(); +style.setColor(new SolidColor("#0766d8")); +style.setFontWeight(FontWeight.BOLD); +theme.setStyle(style); +rangeSelector.setButtonTheme(theme); + +Chart chart = new Chart(); +chart.setTimeline(true); +Configuration configuration = chart.getConfiguration(); +configuration.setRangeSelector(rangeSelector); +chart.drawChart(configuration); +---- +You can customize the date format for the time range input fields by specifying formatter strings +for displaying and editing the dates, as well as a corresponding JavaScript parser +function to parse edited values: + +[source, java] +---- +RangeSelector rangeSelector = new RangeSelector(); +rangeSelector.setInputDateFormat("%YYYY-%MM-%DD:%H:%M"); +rangeSelector.setInputEditDateFormat("%YYYY-%MM-%DD:%H:%M"); +rangeSelector.setInputDateParser( + "function(value) {" + + "value = value.split(/[:\\-]/);\n" + + "return Date.UTC(\n" + + " parseInt(value[0], 10),\n" + + " parseInt(value[1], 10),\n" + + " parseInt(value[2], 10),\n" + + " parseInt(value[3], 10),\n" + + " parseInt(value[4], 10),\n" + + ");}"); +configuration.setRangeSelector(rangeSelector); +---- +Timeline charts allow comparing the charts series against each other. +Setting the compare property to either [constant]#Compare.PERCENT# or [constant]#Compare.VALUE# will show the difference between +charts data series in percentage or absolute values respectively. +[source, java] +---- +PlotOptionsSeries plotOptions = new PlotOptionsSeries(); +plotOptions.setCompare(Compare.PERCENT); +configuration.setPlotOptions(plotOptions); +---- +[[figure.charts.timeline.timeline-compare]] +.Vaadin chart with a percentage comparison between series. +image::img/timeline_charts_compare.png[] + +You can find more examples in the Timeline section of +https://demo.vaadin.com/charts/#CompareMultipleSeries[Vaadin Charts Demo]. diff --git a/articles/charts/java-api/img/charts-3d-fade.png b/articles/charts/java-api/img/charts-3d-fade.png new file mode 100644 index 0000000000..78fca7175a Binary files /dev/null and b/articles/charts/java-api/img/charts-3d-fade.png differ diff --git a/articles/charts/java-api/img/charts-3d-pie.png b/articles/charts/java-api/img/charts-3d-pie.png new file mode 100644 index 0000000000..4978f54c47 Binary files /dev/null and b/articles/charts/java-api/img/charts-3d-pie.png differ diff --git a/articles/charts/java-api/img/charts-3d-scatter.png b/articles/charts/java-api/img/charts-3d-scatter.png new file mode 100644 index 0000000000..70d924566b Binary files /dev/null and b/articles/charts/java-api/img/charts-3d-scatter.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-arearange.png b/articles/charts/java-api/img/charts-arearange.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-arearange.png rename to articles/charts/java-api/img/charts-arearange.png diff --git a/articles/charts/java-api/img/charts-axes-hi.png b/articles/charts/java-api/img/charts-axes-hi.png new file mode 100644 index 0000000000..a9d5b2b439 Binary files /dev/null and b/articles/charts/java-api/img/charts-axes-hi.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-axes-lo.png b/articles/charts/java-api/img/charts-axes-lo.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-axes-lo.png rename to articles/charts/java-api/img/charts-axes-lo.png diff --git a/articles/charts/java-api/img/charts-axes-sample.png b/articles/charts/java-api/img/charts-axes-sample.png new file mode 100644 index 0000000000..c2833a9de2 Binary files /dev/null and b/articles/charts/java-api/img/charts-axes-sample.png differ diff --git a/articles/charts/java-api/img/charts-basicexample.png b/articles/charts/java-api/img/charts-basicexample.png new file mode 100644 index 0000000000..a99febad95 Binary files /dev/null and b/articles/charts/java-api/img/charts-basicexample.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-boxplot.png b/articles/charts/java-api/img/charts-boxplot.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-boxplot.png rename to articles/charts/java-api/img/charts-boxplot.png diff --git a/articles/charts/java-api/img/charts-bubble.png b/articles/charts/java-api/img/charts-bubble.png new file mode 100644 index 0000000000..1f62452506 Binary files /dev/null and b/articles/charts/java-api/img/charts-bubble.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-candlestick.png b/articles/charts/java-api/img/charts-candlestick.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-candlestick.png rename to articles/charts/java-api/img/charts-candlestick.png diff --git a/articles/ds/components/charts/java-api/img/charts-configuration-legend.png b/articles/charts/java-api/img/charts-configuration-legend.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-configuration-legend.png rename to articles/charts/java-api/img/charts-configuration-legend.png diff --git a/articles/charts/java-api/img/charts-containerdataseries.png b/articles/charts/java-api/img/charts-containerdataseries.png new file mode 100644 index 0000000000..88dff19a77 Binary files /dev/null and b/articles/charts/java-api/img/charts-containerdataseries.png differ diff --git a/articles/charts/java-api/img/charts-dataprovider.png b/articles/charts/java-api/img/charts-dataprovider.png new file mode 100644 index 0000000000..3416daf4a7 Binary files /dev/null and b/articles/charts/java-api/img/charts-dataprovider.png differ diff --git a/articles/charts/java-api/img/charts-declarative-basic-line.png b/articles/charts/java-api/img/charts-declarative-basic-line.png new file mode 100644 index 0000000000..6f1bf0325a Binary files /dev/null and b/articles/charts/java-api/img/charts-declarative-basic-line.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-donut.png b/articles/charts/java-api/img/charts-donut.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-donut.png rename to articles/charts/java-api/img/charts-donut.png diff --git a/articles/ds/components/charts/java-api/img/charts-drilldown-details.png b/articles/charts/java-api/img/charts-drilldown-details.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-drilldown-details.png rename to articles/charts/java-api/img/charts-drilldown-details.png diff --git a/articles/charts/java-api/img/charts-elements-hi.png b/articles/charts/java-api/img/charts-elements-hi.png new file mode 100644 index 0000000000..b82f6a6053 Binary files /dev/null and b/articles/charts/java-api/img/charts-elements-hi.png differ diff --git a/articles/charts/java-api/img/charts-elements-lo.png b/articles/charts/java-api/img/charts-elements-lo.png new file mode 100644 index 0000000000..c6e5b39380 Binary files /dev/null and b/articles/charts/java-api/img/charts-elements-lo.png differ diff --git a/articles/charts/java-api/img/charts-elements-sample.png b/articles/charts/java-api/img/charts-elements-sample.png new file mode 100644 index 0000000000..6762bd5d70 Binary files /dev/null and b/articles/charts/java-api/img/charts-elements-sample.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-errorbar.png b/articles/charts/java-api/img/charts-errorbar.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-errorbar.png rename to articles/charts/java-api/img/charts-errorbar.png diff --git a/articles/ds/components/charts/java-api/img/charts-flags.png b/articles/charts/java-api/img/charts-flags.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-flags.png rename to articles/charts/java-api/img/charts-flags.png diff --git a/articles/ds/components/charts/java-api/img/charts-funnel.png b/articles/charts/java-api/img/charts-funnel.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-funnel.png rename to articles/charts/java-api/img/charts-funnel.png diff --git a/articles/ds/components/charts/java-api/img/charts-gauge.png b/articles/charts/java-api/img/charts-gauge.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-gauge.png rename to articles/charts/java-api/img/charts-gauge.png diff --git a/articles/ds/components/charts/java-api/img/charts-heatmap.png b/articles/charts/java-api/img/charts-heatmap.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-heatmap.png rename to articles/charts/java-api/img/charts-heatmap.png diff --git a/articles/ds/components/charts/java-api/img/charts-ohlc.png b/articles/charts/java-api/img/charts-ohlc.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-ohlc.png rename to articles/charts/java-api/img/charts-ohlc.png diff --git a/articles/ds/components/charts/java-api/img/charts-pie.png b/articles/charts/java-api/img/charts-pie.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-pie.png rename to articles/charts/java-api/img/charts-pie.png diff --git a/articles/ds/components/charts/java-api/img/charts-polarspiderweb.png b/articles/charts/java-api/img/charts-polarspiderweb.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-polarspiderweb.png rename to articles/charts/java-api/img/charts-polarspiderweb.png diff --git a/articles/ds/components/charts/java-api/img/charts-polygon.png b/articles/charts/java-api/img/charts-polygon.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-polygon.png rename to articles/charts/java-api/img/charts-polygon.png diff --git a/articles/charts/java-api/img/charts-scatter.png b/articles/charts/java-api/img/charts-scatter.png new file mode 100644 index 0000000000..9cf234acd3 Binary files /dev/null and b/articles/charts/java-api/img/charts-scatter.png differ diff --git a/articles/ds/components/charts/java-api/img/charts-solidgauge.png b/articles/charts/java-api/img/charts-solidgauge.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-solidgauge.png rename to articles/charts/java-api/img/charts-solidgauge.png diff --git a/articles/ds/components/charts/java-api/img/charts-treemap.png b/articles/charts/java-api/img/charts-treemap.png similarity index 100% rename from articles/ds/components/charts/java-api/img/charts-treemap.png rename to articles/charts/java-api/img/charts-treemap.png diff --git a/articles/charts/java-api/img/charts-twodimensional.png b/articles/charts/java-api/img/charts-twodimensional.png new file mode 100644 index 0000000000..7c8dc7b3ba Binary files /dev/null and b/articles/charts/java-api/img/charts-twodimensional.png differ diff --git a/articles/charts/java-api/img/charts-waterfall.png b/articles/charts/java-api/img/charts-waterfall.png new file mode 100644 index 0000000000..446fc64a7a Binary files /dev/null and b/articles/charts/java-api/img/charts-waterfall.png differ diff --git a/articles/charts/java-api/img/directory-download-license-key.png b/articles/charts/java-api/img/directory-download-license-key.png new file mode 100644 index 0000000000..1a8b2f7dde Binary files /dev/null and b/articles/charts/java-api/img/directory-download-license-key.png differ diff --git a/articles/ds/components/charts/java-api/img/timeline_charts_compare.png b/articles/charts/java-api/img/timeline_charts_compare.png similarity index 100% rename from articles/ds/components/charts/java-api/img/timeline_charts_compare.png rename to articles/charts/java-api/img/timeline_charts_compare.png diff --git a/articles/ds/components/charts/java-api/img/timeline_intro_screen.png b/articles/charts/java-api/img/timeline_intro_screen.png similarity index 100% rename from articles/ds/components/charts/java-api/img/timeline_intro_screen.png rename to articles/charts/java-api/img/timeline_intro_screen.png diff --git a/articles/charts/java-api/index.asciidoc b/articles/charts/java-api/index.asciidoc new file mode 100644 index 0000000000..c64ef7a041 --- /dev/null +++ b/articles/charts/java-api/index.asciidoc @@ -0,0 +1,5 @@ +--- +title: Java API +order: 2 +--- + diff --git a/articles/charts/java-api/original-drawings/charts-axes.svg b/articles/charts/java-api/original-drawings/charts-axes.svg new file mode 100644 index 0000000000..55c2568eac --- /dev/null +++ b/articles/charts/java-api/original-drawings/charts-axes.svg @@ -0,0 +1,441 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + Y Axis Title + + Y Axis Labels + + X Axis Labels + + X Axis Title + + + X Axis Line + + Y Axis Line + + X Axis Grid Lines + Y Axis Grid Lines + + + + + X Axis Minor Grid Lines + + + Y Axis Minor Grid Lines + + + Y Axis Ticks + + + Y Axis Minor Ticks + + + X Axis Ticks + X Axis Minor Ticks + + + + + + + + + + + + + diff --git a/articles/charts/java-api/original-drawings/charts-elements.svg b/articles/charts/java-api/original-drawings/charts-elements.svg new file mode 100644 index 0000000000..19a35e2cae --- /dev/null +++ b/articles/charts/java-api/original-drawings/charts-elements.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + Title + Subtitle + Legend + + + + + Y Axis Title + + + Y Axis Labels + + Y Axis Grid + + + + X Axis Labels + + + + + diff --git a/articles/charts/java-api/original-drawings/timeline_intro_screen.svg b/articles/charts/java-api/original-drawings/timeline_intro_screen.svg new file mode 100644 index 0000000000..cb2016e109 --- /dev/null +++ b/articles/charts/java-api/original-drawings/timeline_intro_screen.svg @@ -0,0 +1,125 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + Range selector + + Navigator + + diff --git a/articles/charts/productpage-external.asciidoc b/articles/charts/productpage-external.asciidoc new file mode 100644 index 0000000000..fc8a986bf6 --- /dev/null +++ b/articles/charts/productpage-external.asciidoc @@ -0,0 +1,5 @@ +--- +title: Product page +order: 1000 +url: https://vaadin.com/docs/v8/charts/charts-overview +--- diff --git a/articles/charts/webcomponents-api/charts-basic-use.asciidoc b/articles/charts/webcomponents-api/charts-basic-use.asciidoc new file mode 100644 index 0000000000..1f59005215 --- /dev/null +++ b/articles/charts/webcomponents-api/charts-basic-use.asciidoc @@ -0,0 +1,499 @@ +--- +title: Basic Use +order: 3 +layout: page +--- + +[[charts.basic-use]] += Basic Use + +The [classname]#vaadin--chart# is a regular web component, which you can add to a +web page. + +You can load the chart in 'header' and then use it in the 'body'. +A chart has a height of 400 pixels and takes full width by default. Anyway the chart will adapt its size +to its container element size if that has the size specified. + +Web Components: +[source, html] +---- + + + + + + +
+ + ... + +
+ + +---- + +The chart types are described in +<>. The +main parts of a chart are illustrated in <>. + +[[figure.charts.overview.elements]] +.Chart Elements +image::img/charts-elements-lo.png[] + +To actually display something in a chart, you typically need to configure the +following aspects: + +* Basic chart configuration +* Configure __plot options__ for the chart type +* Configure one or more __data series__ to display +* Configure __axes__ + +The plot options can be configured for each data series individually, or for +different chart types in mixed-type charts. + +[[charts.basic-use.configuration]] +== Basic Chart Configuration + +After adding a chart web component to your html page, you need to configure it further. At the very least, you need +to specify the data series to be displayed in the configuration. + +The chart-specific properties can be changed by adding tags into the chart. Here we add +title and subtitle to the chart. By convention, [elementname]#title# should be used, but it is a reserved +tag name in HTML and does not allow child elements. In Vaadin Charts, a `chart-` prefix is added to fix this +kind of issues. So, instead of using reserved tags, [elementname]#area#, +[elementname]#frame#, [elementname]#style#, and [elementname]#title#, +use the following elements: [elementname]#chart-area#, [elementname]#chart-frame#, [elementname]#chart-style#, +and [elementname]#chart-title#. + +[source, html] +---- + + Planets + The bigger they are the harder they pull + ... + +---- + +The configuration properties are described in more detail in +<>. + + +[[charts.basic-use.plotoptions]] +== Plot Options + +Many chart settings can be configured in the __plot options__ of the chart or +data series. Some of the options are chart type specific, as described later for +each chart type, while many are shared. + +For example, for line charts, you could disable the point markers as follows: + +[source, html] +---- + + + + + +---- + +You can set the plot options for the entire chart or for each data series +separately, allowing also mixed-type charts, as described in +<>. + +The shared plot options are described in +<>. + + +[[charts.basic-use.data]] +== Chart Data Series + +The data displayed in a chart is stored as `data-series` elements. + +[source, html] +---- + + + 4900, 12100, 12800, 6800, + 143000, 125000, 51100, 49500 + + +---- + +Data point features, such as color and size, can be defined inside the `data-series` +element. The data series configuration is described in more detail in +<>. + + +[[charts.basic-use.axis]] +== Axis Configuration + +One of the most common tasks for charts is customizing its axes. At the least, +you usually want to set the axis titles. Usually you also want to specify labels +for data values in the axes. + +When an axis is categorical rather than numeric, you can define category labels +for the items. They must be in the same order and the same number as you have +values in your data series. + +[source,html] +---- + + Planet + Mercury, Venus, Earth, Mars, + Jupiter, Saturn, Uranus, Neptune + +---- + +Formatting of numeric labels can be done with `format` attribute which is a string +where '{value}' will be replaced by the actual y-label value. + +[source,html] +---- + + Diameter + + 2 + + +---- + +More complex formatting, needs to be done using `formatter` which is a +JavaScript function to format the label. + +[source,html] +---- + + Diameter + + 2 + + +---- + + +[[charts.basic-use.two-dimensional]] +== Displaying Multiple Series + +The simplest data, which we saw in the examples earlier in this chapter, is +one-dimensional and can be represented with a single data series. Most chart +types support multiple data series, which are used for representing +two-dimensional data. For example, in line charts, you can have multiple lines +and in column charts the columns for different series are grouped by category. +Different chart types can offer alternative display modes, such as stacked +columns. The legend displays the symbols for each series. + +[source, html] +---- + + + 8, 30, 37, 13, 3 + + + 0, 1, 0, 23, 10 + + + 7, 30, 22, 4, 9 + + + 0, 2, 2, 1, 0 + +---- + +The result for both regular and stacked column chart is shown in +<>. Stacking is enabled with the +columns plot-options property `stacking`. + +[source, html] +---- + + + normal + + +---- + +[[figure.charts.basic-use.two-dimensional]] +.Multiple Series in a Chart +image::img/charts-twodimensional.png[] + + +[[charts.basic-use.mixed]] +== Mixed Type Charts + +You can enable mixed charts by setting the chart type in the +'data-series' element, which overrides the default +chart type of `vaadin--chart` element. You can also make color and +other settings for the series in the plot options. + +For example, to get a line chart, you need to use type `line`. + +[source, html] +---- + + column + blue + 8, 30, 37, 13, 3 + + + line + red + 0, 1, 0, 23, 10 + +---- + +In the above case, where we set the chart type for each series, the overall +chart type is irrelevant. As long as, it does not change the order of the axis +like 'bar' chart would do. + + +[[charts.basic-use.3d]] +== 3D Charts + +Most chart types can be made 3-dimensional by adding 3D options to the chart. +You can rotate the charts, set up the view distance, and define the thickness of +the chart features, among other things. You can also set up a 3D axis frame +around a chart. + +[[figure.charts.basic-use.3d.pie]] +.3D Charts +image::img/charts-3d-pie.png[] + +[[charts.basic-use.3d.options]] +=== 3D Options + +3D view has to be enabled in the `options3d` configuration, along +with other parameters. Minimally, to have some 3D effect, you need to rotate the +chart according to the `alpha` and `beta` parameters. + +Let us consider a basic scatter chart for an example. The basic configuration +for scatter charts is described elsewhere, but let us look how to make it 3D. + +[source,html] +---- + + ... + + + + ... + +---- + +The 3D options are as follows: + +`enabled`:: Whether 3D plot is enabled. Default is `false`. + +`alpha`:: The vertical tilt (pitch) in degrees. + +`beta`:: The horizontal tilt (yaw) in degrees. + +`depth`:: Depth of the third (Z) axis in pixel units. Default is 100. + +`chart-frame`:: Defines the 3D frame, which consists of a back, bottom, and side panels that +display the chart grid. + +[source,html] +---- + + + +---- + +`view-distance`:: View distance for creating perspective distortion. Default is 100. + +[[charts.basic-use.3d.plotoptions]] +=== 3D Plot Options + +The above sets up the general 3D view, but you also need to configure the 3D +properties of the actual chart type. The 3D plot options are chart type +specific. For example, a pie has 'depth' (or thickness), which you can +configure as follows: + +[source,html] +---- + + + 45 + + +---- + + +[[charts.basic-use.3d.data]] +=== 3D Data + +For some chart types, such as pies and columns, the 3D view is merely a visual +representation for one- or two-dimensional data. Some chart types, such as +scatter charts, also feature a third, 'depth axis' for data points. That third +axis is called a Z axis. + +Such data points can be given as arrays of three elements. +[source,html] +---- + + true + + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0], + [-1.0, 0.0, 0.0], + [0.0, -1.0, 0.0], + [0.0, 0.0, -1.0] + + +---- + +Alternatively, the data points can be given as objects which have 'x', 'y' and 'z' properties. +[source,html] +---- + + true + + {x: 0.0, y: 0.0, z:0.0}, + {x:1.0, y:0.0, z:0.0}, + {x:0.0, y:1.0, z:0.0}, + {x:0.0, y:0.0, z:1.0}, + {x:-1.0, y:0.0, z:0.0}, + {x:0.0, y:-1.0, z:0.0}, + {x:0.0, y:0.0, z:-1.0} + + +---- + +Above, we defined 7 orthogonal data points in the 2x2x2 cube centerd in origo. +The result is illustrated in +<>. + +[[figure.charts.basic-use.3d.scatter]] +.3D Scatter Chart +image::img/charts-3d-scatter.png[] + +ifdef::web[] +[[charts.basic-use.3d.distance]] +=== Distance Fade + +To add a bit more 3D effect, you can do some tricks, such as calculate the +distance of the data points from a viewpoint and set the marker size and color +according to the distance. To add custom JavaScript to do this, +https://www.polymer-project.org/2.0/docs/devguide/templates.html#dom-bind[dom-bind] +element can be used. More information about binding data to a chart can be found +<>. + +[source,html] +---- + + + + +---- + +Note that here the view distance is in the scale of the data coordinates, while +the distance defined in the 3D options has different definition and scaling. +With the above settings, which are somewhat exaggerated to illustrate the +effect, the result is shown in <>. + +[[figure.charts.basic-use.3d.fade]] +.3D Distance Fade +image::img/charts-3d-fade.png[] + +endif::web[] + +[[charts.basic-use.es6-transpile]] +== Internet Explorer 11 & Safari 9 support + +Vaadin Charts is using Polymer 2 and ES6. To support IE11 and Safari 9 you need to transpile ES6 to ES5. +The easiest way to do that, is using link:https://www.polymer-project.org/2.0/docs/tools/polymer-cli#build[Polymer CLI]. +Add a build configuration to your link:https://www.polymer-project.org/2.0/docs/tools/polymer-json[polymer.json]: + +[source, html] +---- + "builds": [{ + "name": "my-app", + "js": {"minify": true, "compile": true}, + "css": {"minify": true}, + "html": {"minify": true} + }] +---- +Running [command]`polymer build` in you application folder will create a transpiled version of your application. +Your application will be transpiled and saved in build folder. + +Another option to transpile ES6 to ES5 is to use link:https://babeljs.io/[Babel]. + +[[charts.basic-use.known-issues]] +== Known Issues + +- Because non-chrome browsers need to load a polyfill, you can see flickering, before definition of the web component comes in. +You can suspend rendering the component before it is ready by adding the `unresolved` attribute in body: + +[source, html] +---- + + //Your code here + +---- + +- There is a memory leak problem with Internet Explorer 11 and Polymer 2, see details link:https://github.com/Polymer/polymer/issues/3430[here]. diff --git a/articles/charts/webcomponents-api/charts-charttypes.asciidoc b/articles/charts/webcomponents-api/charts-charttypes.asciidoc new file mode 100644 index 0000000000..6f3ad7cbf4 --- /dev/null +++ b/articles/charts/webcomponents-api/charts-charttypes.asciidoc @@ -0,0 +1,1672 @@ +--- +title: Chart Types +order: 4 +layout: page +--- + +[[charts.charttypes]] += Chart Types + +Vaadin Charts comes with over a dozen different chart types. +The type is specified when the chart element `v--chart` is added to the HTML page. +The '' should be replaced with the wanted type. +For example, `v-line-chart` would show a chart where data is presented by lines. + +The supported chart types are: + +|=== +| <> | <> | <> | <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| <> +| `sparkline` +| <> +| <> +| <> +| <> +| <> +| +|=== + +// TODO Polar is missing as it is not a chart type as such + +Each chart type has its specific plot options and supports its specific +collection of chart features. +They also have specific requirements for the data series. +The type-specific plot options can be specified under the `` element with a type specific `'type'` element, where the `type` should be replaced with the wanted type. + +In addition, the _polar_ option enables polar coordinate system for many of the chart types, enabling charts such as <>. + +In the following, is an example of a pie chart: + +[source,html] +---- + + + ... + + +---- + +The basic chart types and their variants are covered in the following subsections. + +[[charts.charttypes.line]] +== Line and Spline Charts + +Line charts connect the series of data points with lines. +In the basic `line` charts the lines are straight, while in `spline` charts, the lines are smooth polynomial interpolations between the data points. + +[source,html] +---- + + +---- + +[[charts.charttypes.line.plotoptions]] +=== Plot Options + +The `color` property in the line plot options defines the line color, `line-width` the line width, and `dash-style` the dash pattern for the lines. + +See <> for plot options regarding markers and other +data point properties. The markers can also be configured for each data point. + +[[charts.charttypes.area]] +== Area Charts + +Area charts are like line charts, except that they fill the area between the line and some +threshold value on Y axis. The threshold depends on the chart type. +In addition to the base type, chart type combinations for spline interpolation and ranges are supported. + +[source,html] +---- + + + + +---- + +In area range charts, the area between a lower and upper value is painted with a +transparent color. The data series must specify the minimum and maximum values +for the Y coordinates. + +Here is an example of a data series for area range chart. +[source,html] +---- + + + /* [date, min, max] */ + [1388538000000, 1.1, 4.7], + [1388624400000, 1.8, 6.4], + ... + [1419987600000, 1.6, 4.2] + + +---- + +[[charts.charttypes.area.plotoptions]] +=== Plot Options + +Area charts support __stacking__, so that multiple series are piled on top of +each other. The 'normal' stacking mode does a normal summative stacking, while +the 'percent' handles them as proportions. + +[source,html] +---- + + + normal + + +---- + +Note! The plot options for area chart are exceptionally specified in an element called +`chart-area`. By convention, the `area` should be used but that is reserved +tag name in +https://html.spec.whatwg.org/#the-area-element[html specification]. + +The fill color for the area is defined with the `fill-color` element +and its transparency with `fill-opacity` (the opposite of +transparency) with a value between '0.0' and '1.0'. + +The `color` property in the line plot options defines the line color, +`line-width` the line width, and `dash-style` the dash +pattern for the lines. + +See <> for plot options regarding markers and other +data point properties. The markers can also be configured for each data point. + +[[charts.charttypes.columnbar]] +== Column and Bar Charts + +Column and bar charts illustrate values as vertical or horizontal bars, +respectively. The two chart types are essentially equivalent, just as if the +orientation of the axes was inverted. + +[source,html] +---- + + + +---- + +Multiple data series, that is, two-dimensional data, are shown with thinner bars or columns grouped by their category. +See <>. +Enabling stacking with a `stacking` element in the plot options stacks the columns or bars of different series on top of each other. + +You can also have column range charts that illustrate a range +between a lower and an upper value, as described in +<>. They require the use of +data series where lower and upper values are defined. + +See the https://demo.vaadin.com/vaadin-charts-api/[API] documentation for details regarding the plot options. + + +[[charts.charttypes.errorbar]] +== Error Bars + +An error bars visualize errors, or high and low values, in statistical data. +They typically represent high and low values in data or a multitude of standard +deviation, a percentile, or a quantile. The high and low values are represented +as horizontal lines, or "whiskers", connected by a vertical stem. + +While error bars technically are a chart type +`vaadin-errorbar-chart`, you normally use them together with some +primary chart type, such as a scatter or column chart. + +[[figure.charts.charttypes.errorbar]] +.Error Bars in a Scatter Chart +image::img/charts-errorbar.png[width="75%"] + +To display the error bars for data points, you need to have a separate data +series for the low and high values. The type of the data series needs to be +'errorbar'. + +[source, html] +---- + + + false + + Average and Extreme Tempetures in Turku + + Month + Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + + + Temperature °C + + + + #808080 + 2 + Dash + #A52A2A + 80% + 2 + + + + + [-9, -3], [-10, -3], [-8, 1], [-2, 7], [3, 14], [8, 19], [12, 22], + [11, 21], [7, 15], [2, 9], [-1, 4], [-5, 0] + + + + + -6, -6.5, -4, 3, 9, 14, 17, 16, 11, 6, 2, -2.5 + + + +---- + +Note that you should add the error bar series first, to have it rendered lower +in the chart. + +[[charts.charttypes.errorbar.plotoptions]] +=== Plot Options + +`whisker-color`, `whisker-width`, `whisker-length`:: The color, width (vertical thickness), and length of the horizontal "whiskers" +that indicate high and low values. + +`stem-color`, `stem-width`, `stem-dash-style`:: The color, width (thickness), and line style of the vertical "stems" that +connect the whiskers. In box plot charts, which also have stems, they extend +from the quadrintile box. + + +[[charts.charttypes.boxplot]] +== Box Plot Charts + +Box plot charts display the distribution of statistical variables. A data point +has a median, represented with a horizontal line, upper and lower quartiles, +represented by a box, and a low and high value, represented with T-shaped +"whiskers". The exact semantics of the box symbols are up to you. + +Box plot chart is closely related to the error bar chart described in +<>, sharing the box and whisker elements. + +[[figure.charts.charttypes.boxplot]] +.Box Plot Chart +image::img/charts-boxplot.png[width="60%"] + +The chart element for box plot charts is `vaadin-bloxplot-chart`. You +normally have just one data series, so it is meaningful to disable the legend. + +[source,html] +---- + + + false + + Orienteering Split Times + ... + +---- + +[[charts.charttypes.boxplot.plotoptions]] +=== Plot Options + +The plot options for box plot have the same properties as the plot options of error bar but +it also adds a couple of more for median indicator line: + +`median-color`, `median-width`:: Color and width (vertical thickness) of the horizontal median indicator line. + +For example: + +[source,html] +---- + + + + #0000FF + 3 + + +---- + + +[[charts.charttypes.boxplot.datamodel]] +=== Data Model + +The data points in box plots have five different values of one sample: the mininum value ('low'), +first quartile ('q1'), median ('median'), third quartile ('q3') and maximum ('high'). + +[source,html] +---- + + + + [63.0,108.25,154.0,180.5,463.0], + [107.0,149.0,281.5,333.25,520.0], + [56.0,112.0,151.5,157.75,483.0], + [194.0,319.75,371.0,451.0,885.0], + [63.0,101.5,155.5,162.25,371.0], + [72.0,95.25,136.5,155.75,217.0], + [158.0,217.25,304.0,359.75,733.0], + [80.0,105.5,120.0,144.25,240.0] + + +---- + +The data points can be also be defined as objects with the properties 'low', 'q1', 'medium', 'q2' and 'high'. + +[source,html] +---- + + + + { low: 63.0, q1: 108.25, median: 154.0, q3: 180.5, high: 463.0 }, + { low: 107.0, q1: 149.0, median: 281.5, q3: 333.25, high: 520.0 }, + ... + { low: 80.0, q1: 105.5, median: 120.0, q3: 144.25, high: 240.0 } + + +---- + +If the minimum and maximum attributes represent an even smaller quantile, or a +larger multiple of standard deviation, you can have outliers. You can plot them +with a separate data series, with + +[[charts.charttypes.scatter]] +== Scatter Charts + +Scatter charts display a set of unconnected data points. The name refers to +freely given X and Y coordinates. Also Z coordinate can be given if +<>. + +[[figure.charts.charttypes.scatter]] +.Scatter Chart +image::img/charts-scatter.png[width="50%"] + +The chart element of a scatter chart is `vaadin-scatter-chart`. + +Here is an example +of a scatter chart where 300 random points in the unit circle is shown. + +[source,html] +---- + + + + +---- + +The result was shown in <>. + +[[charts.charttypes.scatter.markers]] +=== Data Point Markers + +Scatter charts and other charts that display data points, such as line and +spline charts, visualize the points with __markers__. The markers can be +configured with the [classname]#Marker# property objects available from the plot +options of the relevant chart types, as well as at the level of each data point. + +For example, to set the marker for an individual data point: + +[source,javascript] +---- +{ x: 1, y: 1, marker: { ... } } +---- + + +[[charts.charttypes.scatter.markerproperties]] +=== Marker Shape Properties + +The colors of the marker can be specified with `lineColor` (border) and `fillColor` (content) elements. + +Marker size is determined by the `radius` element, which is given +in pixels. The actual visual radius includes also the line width. + +[source,javascript] +---- +marker: { + fillColor: "rgb("+(255-colorLevel)+",0,"+colorLevel+")", + radius: (z+1)*5, + lineWidth: 1, + lineColor: "black" +} +---- + +[[charts.charttypes.scatter.markersymbols]] +=== Marker Symbols + +Markers are visualized either with a shape or an image symbol. You can choose +the shape from a number of built-in shapes ('circle', 'square', +'diamond', 'triangle' or 'triangle_down'). +These shapes are drawn with a line and fill, which you can set as described +above. + +[source,javascript] +---- +marker: { + symbol: Math.random() > 0.9 ? "diamond" : "circle" +} +---- + +You can also use any image accessible by a URL as a marker. Anyway, the line, +radius, and color properties are not applicable to image symbols. + +[source, javascript] +---- +symbol: "url(img/vaadin-logo.png)" +---- + + + +[[figure.charts.charttypes.scatter.vaadin]] +.Scatter with image markers +image::img/charts-scatter-vaadin.png[width="50%"] + + +[[charts.charttypes.bubble]] +== Bubble Charts + +Bubble charts are a special type of scatter charts for representing +three-dimensional data points with different point sizes. We demonstrated the +same possibility with scatter charts in <>, but the +bubble charts make it easier to define the size of a point by its third (Z) +dimension, instead of the radius property. The bubble size is scaled +automatically, just like for other dimensions. The default point style is also +more bubbly. + +[[figure.charts.charttypes.bubble]] +.Bubble Chart +image::img/charts-bubble.png[] + +The chart element of a bubble chart is `vaadin-bubble-chart`. Its has a single +chart-specific property, `display-negative`, which controls whether +bubbles with negative values are displayed at all. More typically, you want to +configure the bubble `marker`. The Z coordinate value is available in the formatter +JavaScript with `this.point.z` reference. + +The bubble radius is scaled linearly between a minimum and maximum radius. If +you would rather scale by the area of the bubble, you can approximate that by +taking square root of the Z values. + +ifdef::web[] +In the following example, we overlay a bubble chart over a world map background. +We customize the bubbles to be more round with spherical color gradient. +endif::web[] + +ifdef::web[] + +[source,html] +---- + + + false + + Champagne Consumption by Country + + + + + img/neocreo_Blue_World_Map_640x.png + + + + + -180 + 180 + + + + + -90 + 90 + + 0 + + + + + + + + 0 + rgba(255, 255, 255, 0.5) + + + 1 + rgba(170, 70, 67, 0.5) + + + + + + + + { x: 1.799, y: 55.200, z: 13.476, name: "France"}, + { x: -1.725, y: 64.800, z: 5.876, name: "United Kingdom"}, + { x: -90.328, y: 45.600, z: 4.401, name: "United States"}, + { x: 7.895, y: 61.200, z: 3.768, name: "Germany"}, + { x: 3.512, y: 60.996, z: 3.092, name: "Belgium"}, + { x: 129.470, y: 43.200, z: 2.811, name: "Japan"}, + { x: 128.355, y: -32.400, z: 2.207, name: "Australia"}, + { x: -78.990, y: 72.000, z: 1.261, name: "Canada"}, + { x: 83.147, y: 72.000, z: 1.158, name: "Russia"}, + { x: 98.862, y: 42.000, z: 1.149, name: "China"} + + + +---- +endif::web[] + + +[[charts.charttypes.pie]] +== Pie Charts + +A pie chart illustrates data values as sectors of size proportionate to the sum +of all values. The pie chart element is `vaadin-pie-chart` and +type-specific settings can be done under `plot-options` element as +described later. + +A ready pie chart is shown in <>. + +[[figure.charts.charttypes.pie]] +.Pie Chart +image::img/charts-pie.png[width="50%"] + +[[charts.charttypes.pie.plotoptions]] +=== Plot Options + +The chart-specific options of a pie chart are configured with a +[classname]#PlotOptionsPie#. + +[source,html] +---- + + + 0 + 75% +
50%, 50%
+
+
+---- + +`inner-size`:: A pie with inner size greater than zero is a "donut". The inner size can be expressed either as number of pixels or as a relative percentage of the chart area with a string (such as "60%") See the section later on donuts. +`size`:: The size of the pie can be expressed either as number of pixels or as a relative percentage of the chart area with a string (such as "80%"). The default size is 75%, to leave space for the labels. +`center`:: The X and Y coordinates of the center of the pie can be expressed either as numbers of pixels or as a relative percentage of the chart sizes with a string. The default is "50%", "50%". + + + +[[charts.charttypes.pie.data]] +=== Data Model + +The labels for the pie slices are determined from the labels of the data +points. + +[source,html] +---- + + + ["Mercury", 4900], + ["Venus", 12100], + ["Earth", 12800], + ["Mars", 6800], + ["Jupiter", 143000], + ["Saturn", 125000], + ["Uranus", 51100], + ["Neptune", 49500] + + +---- + +If a data point has the 'sliced' property enabled, it is shown as +slightly cut away from the pie. + +[source,javascript] +---- +{name: "Earth", y: 12800, sliced: true} +---- + + +[[charts.charttypes.pie.donut]] +=== Donut Charts + +Setting the `inner-size` of the plot options of a pie chart to a +larger than zero value results in an empty hole at the center of the pie. + +[source,html] +---- + + + 60% + + +---- + +As you can set the plot options also for each data series, you can put two pie +charts on top of each other, with a smaller one fitted in the "hole" of the +donut. This way, you can make pie charts with more details on the outer rim, as +done in the example below: + +[source,html] +---- + + + rgb(255,255,255) + + + ... + + + + + + + + ... + + +---- + +The result is illustrated in <>. + +[[figure.charts.charttypes.pie.donut]] +.Overlaid Pie and Donut Chart +image::img/charts-donut.png[width="60%"] + +[[charts.charttypes.gauge]] +== Gauges + +A [vaadinelement]#vaadin-gauge-chart# is an one-dimensional chart with a circular Y-axis, where a rotating pointer points to a value on the axis. +A gauge can, in fact, have multiple Y-axes to display multiple scales. + +A [vaadinelement]#vaadin-solidgauge-chart# is otherwise like a regular gauge, except that a solid color arc is used to indicate current value instead of a pointer. +The color of the indicator arc can be configured to change according to color stops. + +Let us first consider [vaadinelement]#vaadin-gauge-chart# the following gauge. +After the settings done in the subsequent sections, it will show as in <>. + +[[figure.charts.charttypes.gauge]] +.A Gauge +image::img/charts-gauge.png[width="30%"] + +[[charts.charttypes.gauge.conf]] +=== Gauge Configuration + +The start and end angles of the gauge can be configured in the `pane` element. +The angles can be given as -360 to 360 degrees, with 0 at the top of the circle. + +[source,html] +---- + + Speedometer + + + ... + +---- + + +[[charts.charttypes.gauge.axis]] +=== Axis Configuration + +A gauge has only an Y-axis. You need to provide both a minimum and maximum value +for it. + +[source,html] +---- + + km/h + + + + + +---- + +You can do all kinds of other configuration to the axis - please see the +https://demo.vaadin.com/vaadin-charts-api/[API] +documentation for all the available parameters. + + +[[charts.charttypes.gauge.data]] +=== Setting Gauge Data + +A gauge only displays a single value per data series, which you can define as follows: + +[source,html] +---- + + + 80 + + +---- + +[[charts.charttypes.solidgauge]] +== Solid Gauges + +A solid gauge is much like a regular gauge described previously; a +one-dimensional chart with a circular Y-axis. However, instead of a rotating +pointer, the value is indicated by a rotating arc with solid color. The color of +the indicator arc can be configured to change according to the value using color +stops. + +Let us consider the following solid gauge: + +[source,html] +---- + + Speed + + + ... + + +---- + +After the settings done in the subsequent sections, it will show as in +<>. + +[[figure.charts.charttypes.solidgauge]] +.A Solid Gauge +image::img/charts-solidgauge.png[] + +While solid gauge is much like a regular gauge, the configuration differs + +[[charts.charttypes.solidgauge.conf]] +=== Configuration + +The solid gauge must be configured in the [elementname]#pane# element of the chart. +The gauge arc spans an angle, which is specified as -360 to 360 +degrees, with 0 degrees at the top of the arc. Typically, a semi-arc is used, +where you use -90 and 90 for the angles, and move the center lower than you +would have with a full circle. You can also adjust the size of the gauge pane; +enlargening it allows positioning tick labels better. + +The shape of the gauge +display is defined as the background of the pane. You at least need to set the +shape as either 'arc' or 'solid'. You typically also want to set background +color and inner and outer radius. + +[source,html] +---- + + + + +---- + +[[charts.charttypes.solidgauge.axis]] +=== Axis Configuration + +A gauge only has an Y-axis. You must define the value range ('min' and +'max'). + +You can configure color stops for the indicator arc. The stops are defined with +[elementname]#stops# elements having the stop points from 0.0 to 1.0 and color values. + +[source,html] +---- + + 0.1, #55BF3B + 0.5, #DDDF0D + 0.9, #DF5353 + + +---- + +Setting rotation to 'auto' makes gauge labels rotate perpendicular to the center. + +[source,html] +---- + + ... + + + +---- + +You can do all kinds of other configuration to the axis - please see the +https://demo.vaadin.com/vaadin-charts-api/[API] +documentation for all the available parameters. + +[[charts.charttypes.solidgauge.plotoptions]] +=== Plot Options + +Solid gauges do not currently have any chart type specific plot options. See +<> for common options. + +[source,html] +---- + + + + + +---- + + +[[charts.charttypes.solidgauge.data]] +=== Setting and Updating Gauge Data + +A gauge only displays a single value, which you can define as a data series of +length one, such as as follows: + +[source,html] +---- + + 80 + +---- + +Gauges are especially meaningful for displaying changing values. Here is an example +how to update the value from JavaScript. + +[source,html] +---- + + ... + + + + +---- + +[[charts.charttypes.rangecharts]] +== Area and Column Range Charts + +Ranged charts display an area or column between a minimum and maximum value, +instead of a singular data point. +An area range is created with [vaadinelement]#vaadin-arearange-chart# element, and a column range with [vaadinelement]#vaadin-columnrange-chart#. + +Consider the following example: + +[source,html] +---- + + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + Temperature °C + + + + Month + + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + + + [-51.5,10.9], + [-49.0,11.8], + [-44.3,17.5], + [-36.0,25.5], + [-24.6,31.0], + [-7.0,33.8], + [-5.0,37.2], + [-10.8,33.8], + [-18.7,28.8], + [-31.8,19.4], + [-42.0,14.1], + [-47.0,10.8] + + + +---- + +The resulting chart, as well as the same chart with a column range, is shown in +<>. + +[[figure.charts.charttypes.rangecharts]] +.Area and Column Range Chart +image::img/charts-arearange.png[] + + +[[charts.charttypes.polar]] +== Polar, Wind Rose, and Spiderweb Charts + +Most chart types having two axes can be displayed in __polar__ coordinates, +where the X axis is curved on a circle and Y axis from the center of the circle +to its rim. Polar chart is not a chart type in itself, but can be enabled for +most chart types with `true` in the `chart` options. +Therefore all chart type specific features are usable with polar +charts. + +[source,html] +---- + + + true + + ... + +---- + +Vaadin Charts allows many sorts of typical polar chart types, such as 'wind +rose', a polar column graph, or 'spiderweb', a polar chart with categorical +data and a more polygonal visual style. + +You need to define the sector of the polar projection with a [elementname]#pane# element. +The sector is defined as degrees from the north direction. + +[source,html] +---- + + +---- + +The polar and spiderweb charts are illustrated in +<>. + +[[figure.charts.charttypes.polar]] +.Wind Rose and Spiderweb Charts +image::img/charts-polarspiderweb.png[] + +[[charts.charttypes.polar.spiderweb]] +=== Spiderweb Charts + +A __spiderweb__ chart is a commonly used visual style of a polar chart with a +polygonal shape rather than a circle. The data and the X axis should be +categorical to make the polygonal interpolation meaningful. The sector is +assumed to be full circle, so no angles for the pane need to be specified. + +ifdef::web[Note the style settings done in the axis in the example below:] + +ifdef::web[] + +[source,html] +---- + + Extreme Temperature Range in Finland + https://ilmatieteenlaitos.fi/lampotilaennatyksia + + + + true + + + + 1 + + polygon + + + on + 0 + 0 + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + 10.9, 11.8, 17.5, 25.5, 31.0, 33.8, + 37.2, 33.8, 28.8, 19.4, 14.1, 10.8 + + + +---- +endif::web[] + + + +[[charts.charttypes.funnel]] +== Funnel and Pyramid Charts + +Funnel and pyramid charts are typically used to visualize stages in a sales +processes, and for other purposes to visualize subsets of diminishing size. A +funnel or pyramid chart has layers much like a stacked column: in funnel from +top-to-bottom and in pyramid from bottom-to-top. The top of the funnel has width +of the drawing area of the chart, and dinimishes in size down to a funnel "neck" +that continues as a column to the bottom. A pyramid diminishes from bottom to +top and does not have a neck. + +[[figure.charts.charttypes.funnel]] +.Funnel and Pyramid Charts +image::img/charts-funnel.png[] + +Funnels have chart element `vaadin-funnel-chart`, and pyramids have `vaadin-pyramid-chart`. + +The labels of the funnel blocks are by default placed on the right side of the +blocks, together with a connector. You can configure their style in the plot +options. + +ifdef::web[] +Here is an example. + +[source,html] +---- + + Monster Funnel + + + + + 20% + 20% + + + + + + + + + + ['Monsters Met', 340], + ['Engaged', 235], + ['Killed', 187], + ['Tinned', 70], + ['Eaten', 50] + + + +---- + +endif::web[] + +ifdef::web[] +[[charts.charttypes.funnel.plotoptions]] +=== Plot Options + +In addition to common chart options, the funnel and pyramid charts support the following +shared options: `width`, `height`, `depth`, +`allow-point-select`, `border-color`, +`border-width`, `center`, `sliced-offset`, and +`visible`. See +<> for detailed descriptions. + +They have the following chart type specific properties: + +`neck-height` (only funnel):: Height of the neck part of the funnel either as pixels or as percentage of the entire funnel height. +`neck-width` (only funnel):: Width of the neck part of the funnel either as pixels or as percentage of the top of the funnel. +`reversed`:: Whether the chart is reversed upside down from the normal direction from diminishing from the top to bottom. +The default is __false__ for funnel and __true__ for pyramid. + +endif::web[] + + +[[charts.charttypes.waterfall]] +== Waterfall Charts + +Waterfall charts are used for visualizing level changes from an initial level to +a final level through a number of changes in the level. The changes are given as +delta values, and you can have a number of intermediate totals, which are +calculated automatically. + +[[figure.charts.charttypes.waterfall]] +.Waterfall Charts +image::img/charts-waterfall.png[width="75%"] + +Waterfall charts are defined with an element `vaadin-waterfall-chart`. + +ifdef::web[For example:] + +ifdef::web[] + +[source, html] +---- + + Changes in Reindeer Population in 2011 + + + + + Population (thousands) + 330000 + + ... + +---- +endif::web[] + +ifdef::web[] +The example continues in the following subsections. +endif::web[] + +ifdef::web[] +[[charts.charttypes.waterfall.plotoptions]] +=== Plot Options + +Waterfall charts have the following chart type specific properties: + +`up-color`:: Color for the positive values. +`color`:: Default color for all the points. If `up-color` is +defined, `color` is used only for the negative values. + + +In the following, we define the colors, as well as the style and placement of +the labels for the columns: + +ifdef::web[] + +[source,html] +---- + + + #0000FF + #FF0000 + 0 + + + + + +---- +endif::web[] + +endif::web[] + +ifdef::web[] +[[charts.charttypes.waterfall.datamodel]] +=== Data Series + +The data series for waterfall charts consists of changes (deltas) starting from +an initial value and one or more cumulative sums. There should be at least a +final sum, and optionally intermediate sums. No value is needed for the sums as they +are calculated automatically. For intermediate sums, you should set the +`isIntermediateSum` property to 'true'. + +ifdef::web[] + +[source,html] +---- + + + {x: 0, y: 306503, name: "Start", color: "#000000"}, + {x: 1, y: -3330, name: "Predators"}, + {x: 2, y: -103332, name: "Slaughter"}, + {x: 3, y: 104052, name: "Reproduction"}, + {x: 4, name: "End", isSum: true, color: "#000000"} + + +---- +endif::web[] + +endif::web[] + + +[[charts.charttypes.heatmap]] +== Heat Maps + +A heat map is a two-dimensional grid, where the color of a grid cell indicates a +value. + +[[figure.charts.charttypes.heatmap]] +.Heat Maps +image::img/charts-heatmap.png[width="75%"] + +Heat maps are defined with a chart element `vaadin-heatmap-chart`. + +ifdef::web[For example:] + +ifdef::web[] +[source,html] +---- + + Heat Data + + + + white + 2 + + + + + + -51.5 + 37.2 + #00FFFF + #FF0000 + + + Month + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + + + + "High °C", "Low °C" + + + + [0, 0, 10.9], + [0, 1, -51.5], + [1, 0, 11.8], + ... + [11, 1, -47] + + + +---- +endif::web[] + +[[charts.charttypes.treemap]] +== Tree Maps + +A tree map is used to display hierarchical data. It consists of a group of +rectangles that contains other rectangles, where the size of a rectangle +indicates the item value. + +[[figure.charts.charttypes.treemap]] +.Tree Maps +image::img/charts-treemap.png[] + +Tree maps are defined with a chart element `vaadin-treemap-chart`. + +ifdef::web[For example:] + +ifdef::web[] + +[source,html] +---- + + Fruit consumption + + + + + + + + + + + + + A + Apples + #EC2500 + + + B + Bananas + #ECE100 + + + O + Oranges + #EC9800 + + + + Anne + A + 5 + + + Rick + A + 3 + + + Peter + A + 4 + + + + Anne + B + 4 + + + Rick + B + 10 + + + Peter + B + 1 + + + + Anne + O + 1 + + + Rick + O + 3 + + + Peter + O + 3 + + + + Susanne + Kiwi + 2 + #9EDE00 + + + + +---- +endif::web[] + +ifdef::web[] +[[charts.charttypes.treemap.plotoptions]] +=== Plot Options + +Tree map charts have following chart type +specific properties: + +`allow-drill-to-node`:: When enabled the user can click on a point which is a +parent and zoom in on its children. Defaults to false. +`alternate-starting-direction`:: Enabling this option will make the treemap +alternate the drawing direction between vertical and horizontal. The next levels +starting direction will always be the opposite of the previous. Defaults value +is [literal]#++false++#. +`layout-algorithm`:: This option decides which algorithm is used for setting +position and dimensions of the points. Available algorithms are +'sliceAndDice', 'stripes', 'squarified' or 'strip'. Default value is +'sliceAndDice'. +`layout-starting-direction`:: Defines which direction the layout algorithm will +start drawing. Possible values are 'horizontal' and 'vertical'. +Default value is 'vertical'. +`level-is-constant`:: Used together with the `levels` and +`allow-drill-to-node` options. When set to [literal]#++false++# +the first level visible when drilling is considered to be level one. Otherwise +the level will be the same as the tree structure. Defaults value is +[literal]#++true++#. +`levels`:: Set options on specific levels. Takes precedence over series +options, but not point options. + + +endif::web[] + +ifdef::web[] +[[charts.charttypes.treemap.dataseries]] +=== Tree Map Data Series + +Tree maps require hierarchical data. +The item hierarchy is defined with the `parent` property in the +data point. Parent argument is the `id` value of the parent. +If no matching `id` is found or if +value is null then the parent will be rendered as a root item. + +[source,html] +---- + + A + Apples + #EC2500 + + + Anne + A + 5 + +---- + +endif::web[] + + +[[charts.charttypes.polygon]] +== Polygons + +A polygon can be used to draw any freeform filled or stroked shape in the +Cartesian plane. + +Polygons consist of connected data points where the both x and y +properties should be set. + +[[figure.charts.charttypes.polygon]] +.Polygon combined with Scatter +image::img/charts-polygon.png[] + +Polygons are defined with a chart element `vaadin-polygon-chart`. + +ifdef::web[For example:] + +ifdef::web[] + +[source,html] +---- + + Height vs Weight + Polygon series + + Height (cm) + + + Weight (kg) + + + + + [153, 42], [149, 46], [149, 55], [152, 60], [159, 70], [170, 77], [180, 70], + [180, 60], [173, 52], [166, 45] + + + + [161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6], + ... + [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3] + + + +---- +endif::web[] + +[[charts.charttypes.flags]] +== Flags + +_Flags_ is a special chart type for annotating a series or the X axis with callout labels. Flags indicate interesting points or events on the series or axis. The flags are defined as items in a data series separate from the annotated series or axis. + +[[figure.charts.charttypes.flags]] +.Flags placed on an axis and a series +image::img/charts-flags.png[] + +Flags are normally used in a chart that has one or more normal data series. + +[[charts.charttypes.flags.plotoptions]] +=== Plot Options + +The flags are defined in a series that has its type set to `flags`. In addition to the common plot options properties, flag charts also have the following properties: + +[parameter]#shape#:: defines the shape of the marker. It can be one of `FLAG`, `CIRCLEPIN`, `SQUAREPIN`, or `CALLOUT`. +[parameter]#stack-distance#:: defines the vertical offset between flags on the same value in the same series. Defaults to 12. +[parameter]#draw-on-series#:: defines the ID of the series where the flags should be drawn on. If no ID is given, the flags are drawn on the X axis. +[parameter]#draw-on-key#:: in chart types that have multiple keys (Y values) for a data point, the property defines on which key the flag is placed. Line and column series have only one key, `y`. In range, OHLC, and candlestick series, the flag can be placed on the `open`, `high`, `low`, or `close` key. Defaults to `y`. + +[[charts.charttypes.flags.data]] +=== Data + +The data points for flags series require [propertyname]#x# and [propertyname]#title# properties, but can also have [propertyname]#text# property indicating the tooltip text. + +ifdef::web[] +[[charts.charttypes.flags.example]] +=== Example + +In the following, we annotate a time series as well as the axis with flags: + +[source,html] +---- + + USD to EUR exchange rate + + + + + + + + + + + + [1434499200000,0.8821], + [1434585600000,0.8802], + [1434672000000,0.8808], + [1434844800000,0.8794], + [1434931200000,0.8818], + [1435017600000,0.8952], + [1435104000000,0.8924], + [1435190400000,0.8925], + [1435276800000,0.8955] + + + + + + 1434585600000 + First Series Flag + First Series Flag Tooltip Text + + + 1435017600000 + Second Series Flag + + + + + + + 1434844800000 + First Axis Flag + First Axis Flag Tooltip Text + + + 1435190400000 + Second Axis Flag + + + + + +---- +endif::web[] + +[[charts.charttypes.ohlc]] +== OHLC and Candlestick Charts + +An Open-High-Low-Close (OHLC) chart displays the change in price over a +period of time. An OHLC chart consist of vertical lines, each +having a horizontal tickmark both on the left and the right side. The top and +bottom ends of the vertical line indicate the highest and lowest prices during +the time period. The tickmark on the left side of the vertical line shows the +opening price and the tickmark on the right side the closing price. OHLC +charts are defined with a [vaadinelement]#vaadin-ohlc-chart# element. + +[[figure.charts.charttypes.ohlc]] +.OHLC Chart. +image::img/charts-ohlc.png[] + +A candlestick chart is another way to visualize OHLC data. A candlestick has a body and two +vertical lines, called _wicks_. The body represents the opening and closing +prices. If the body is filled, the top edge of the body shows the opening +price and the bottom edge shows the closing price. If the body is unfilled, +the top edge shows the closing price and the bottom edge the opening price. +In other words, if the body is filled, the opening price is higher than the +closing price, and if not, lower. The upper wick represents the highest price +during the time period and the lower wick represents the lowest price during. +A candlestick chart is defined with a +[vaadinelement]#vaadin-candlestick-chart# element. + + +[[figure.charts.charttypes.candlestick]] +.Candlestick Chart. +image::img/charts-candlestick.png[] + +To attach data to a OHLC or a candlestick chart you need to use a +[elementname]#data-series#. See <> + for more details. An OHLC data series contains an array of objects +with a date and the open, highest, lowest, and close price on that date. + +[source,html] +---- + + + + + + +---- + +Typically the OHLC and candlestick charts contain a lot of data, so it is +useful to use them with the timeline feature enabled. The timeline feature is + described in <>. + +[[charts.charttypes.ohlc.plotoptions]] +=== Plot Options +You can use a [elementname]#data-grouping# tag to configure data grouping +properties. If the data points in a series are so dense that the spacing +between two or more points is less than value of the +[propertyname]#group-pixel-width#, the points will be grouped into +appropriate groups so that each is more or less two pixels wide. +The [propertyname]#approximation# attribute specifies which data point value +should represent the group. The possible values are: [literal]#average#, +[literal]#open#, [literal]#high#, [literal]#low#, [literal]#close#, +and [literal]#sum#. + +Using [propertyname]#up-color# and [propertyname]#line-color# allow setting +the fill and border colors of the candlestick that indicate rise in the +values. The default colors are white. diff --git a/articles/charts/webcomponents-api/charts-configuration.asciidoc b/articles/charts/webcomponents-api/charts-configuration.asciidoc new file mode 100644 index 0000000000..619a93734b --- /dev/null +++ b/articles/charts/webcomponents-api/charts-configuration.asciidoc @@ -0,0 +1,355 @@ +--- +title: Chart Configuration +order: 5 +layout: page +--- + +[[charts.configuration]] += Chart Configuration + +All the chart content configuration of charts can be defined inside the +`vaadin--chart` element. + +The configuration properties in a chart element are +summarized in the following: + +* `data-series`: the data for the chart + +* `chart`: general options + +* `credits`: credits label (text, position, href, enabled) + +* `data`: inteface for adding data from sources like CSV and HTML table + +* `drilldown`: options for drilldown + +* `exporting`: options for exporting module + +* `labels`: HTML labels + +* `legend`: a box containing a symbol and name fore each series item (see <>) + +* `loading`: options to control the appearance of the loading screen + +* `navigation`: options for buttons and menus appearing in the exporting module + +* `no-data`: options for displaying a message like "No data to display" + +* `pane`: general options for combined X and Y axes set (only polar charts and angular gauges) + +* `plot-options`: wrapper object for config objects for each series type (see <>) + +* `subtitle`: the charts subtitle + +* `chart-title`: the charts main title + +* `tooltip`: options for the tooltip + +* `x-axis`: the X axis or category axis (see <>) + +* `y-axis`: the Y axis or value axis (see <>) + +Please, see more details about these in the https://demo.vaadin.com/vaadin-charts-api/[API]. For data configuration, see <>. + +[[charts.configuration.plotoptions]] +== Plot Options + +The plot options are set under the `vaadin--chart` element. +The options are chart type specific, defined in type-spesific +element inside the `plot-options`. + +For example, the following enables stacking in column charts: + +[source,html] +---- + + + normal + + +---- + +See the https://demo.vaadin.com/vaadin-charts-api/[API] documentation of `plot-options` and each chart type under it for more +information about the chart-specific options. + +[[charts.configuration.plotoptions.other]] +=== Other Options + +The following options are supported by some chart types. + +`width` :: Defines the width of the chart either by pixels or as a percentual proportion of the drawing area. +`height`:: Defines the height of the chart either by pixels or as a percentual proportion of the drawing area. +`depth`:: Specifies the thickness of the chart in 3D mode. +`allow-point-select`:: Specifies whether data points, in whatever way they are visualized in the particular chart type, can be selected by clicking on them. Defaults to __false__. +`border-color`:: Defines the border color of the chart elements. +`border-width`:: Defines the width of the border in pixels. +`center`:: Defines the center of the chart within the chart area by left and top coordinates, which can be specified either as pixels or as a percentage (as string) of the drawing area. The default is top 50% and left 50%. +`sliced-offset`:: In chart types that support slices, such as pie and pyramid charts, specifies the offset for how far a slice is detached from other items. The amount is given in pixels and defaults to 10 pixels. +`visible`:: Specifies whether or not a chart is visible. Defaults to __true__. + +[[charts.configuration.axes]] +== Axes + +Different chart types may have one, two, or three axes; in addition to X and Y +axes, some chart types may have a Z axis. These are represented by +`x-axis`, `y-axis`, and `z-axis`, +respectively. The X axis is usually horizontal, representing the iteration over +the data series, and Y vertical, representing the values in the data series. +Some chart types invert the axes and they can be explicitly inverted with +[methodname]#getChart().setInverted()# in the chart configuration. An axis has a +caption and tick marks at intervals indicating either numeric values or symbolic +categories. Some chart types, such as gauge, have only Y-axis, which is circular +in the gauge, and some such as a pie chart have none. + +The basic elements of X and Y axes are illustrated in +<>. + +[[figure.charts.configuration.axes.elements]] +.Chart Axis Elements +image::img/charts-axes-lo.png[] + +Axis elements are added under the chart element. + +[source,html] +---- + + ... + + Title + + ... + +---- + +A chart can have more than one Y-axis, usually when different series displayed +in a graph have different units or scales. The association of a data series with +an axis is done in the `data-series` using a property `y-axis`. + +[source,html] +---- + + ... + + ... + + + ... + + ... + +---- + +For a complete reference of the many configuration parameters for the axes, +please refer to the https://demo.vaadin.com/vaadin-charts-api/[API] of Vaadin Charts. + +[[charts.configuration.axes.type]] +=== Axis Type + +Axes can be one of the following types, which you can set with +`type` property. + +[parameter]#LINEAR# (default):: For numeric values in linear scale. +[parameter]#LOGARITHMIC#:: For numerical values, as in the linear axis, but the axis will be scaled in the logarithmic scale. The minimum for the axis __must__ be a positive non-zero value ( [methodname]#log(0)# is not defined, as it has limit at negative infinity when the parameter approaches zero). +[parameter]#DATETIME#:: Enables date/time mode in the axis. The date/time values are expected to be given in milliseconds since January 1st 1970 at 00:00:00 GMT. You can get the millisecond representation of a JavaScript [classname]#Date# object with the [methodname]#UTC()# method. +[parameter]#CATEGORY#:: Enables using categorical data for the axis, as described in more detail later. With this axis type, the category labels are determined from the labels of the data points in the data series, without need to set them explicitly with [methodname]##setCategories()##. + + + +[[charts.configuration.axes.categories]] +=== Categories + +The axes display, in most chart types, tick marks and labels at some numeric +interval by default. If the items in a data series have a symbolic meaning +rather than numeric, you can associate __categories__ with the data items. The +category label is displayed between two axis tick marks and aligned with the +data point. In certain charts, such as column chart, where the corresponding +values in different data series are grouped under the same category. You can set +the category labels with `categories` property. The list should +match the items in the data series. + +[source,html] +---- + + Mercury, Venus, Earth, Mars, + Jupiter, Saturn, Uranus, Neptune + +---- + +You can only set the category labels from the data point labels by setting the +axis type to [parameter]#CATEGORY#, as described earlier. + + +[[charts.configuration.axes.labels]] +=== Labels + +The axes display, in most chart types, tick marks and labels at some numeric +interval by default. You can modify the labels options with `labels` element +inside the axis. + +[source,html] +---- + + + center + + -45 + 2 + + +---- + +Axis labels have the following configuration properties: + +`align`:: Defines the alignment of the labels relative to the centers of the ticks. +On left alignment, the left edges of labels are aligned at the tickmarks, and correspondingly the +right side on right alignment. The default is determined automatically based on the direction of +the axis and rotation of the labels. + +`distance` (only in polar charts):: Distance of labels from the perimeter of the plot area, in pixels. + +`enabled`:: Whether labels are enabled or not. Defaults to 'true'. + +`format`:: Formatting string for labels, as described in <>. Defaults to '{value}'. + +`formatter`:: A JavaScript formatter for the labels, as described in +<>. The value is available in the +`this.value` property. The `this` object also has +`axis`, `chart`, `isFirst`, and +`isLast` properties. + +Defaults to: +[source,javascript] +---- +function() {return this.value;} +---- + +`max-stagger-lines` (only horizontal axis):: When labels on the horizontal (usually X) axis are displayed so densely that they would overlap, they are automatically placed on alternating lines in "staggered" fashion. When number of lines is not set manually with staggerLines, this parameter defines the maximum number of such lines; value 1 disables automatic staggering. Default is 5 lines. + +`rotation`:: Defines rotation of labels in degrees. A positive value indicates rotation in +clockwise direction. Labels are rotated at their alignment point. Defaults to 0. + +`stagger-lines`:: Defines number of lines for placing the labels to avoid overlapping. By default 'undefined', and the number of lines is automatically determined up to `max-stagger-lines`. + +`step`:: Defines tick interval for showing labels, so that labels are shown at every +__n__th tick. The default step is automatically determined, along with +staggering, to avoid overlap. + +`style`:: Defines style for labels. + +`use-html`:: Allows using HTML in custom label formats. Otherwise, HTML is quoted. Defaults to [literal]#++false++#. + +`x`,`y`:: Offsets for the label's position, relative to the tick position. X offset defaults to '0', but Y to 'null', which enables automatic positioning based on font size. + +Gauge, pie, and polar charts allow additional properties. + +For a complete reference of the many configuration parameters for the labels, +please refer to the https://demo.vaadin.com/vaadin-charts-api/[API] of Vaadin Charts. + + +[[charts.configuration.axes.extremes]] +=== Axis Range + +The axis range is normally set automatically to fit the data, but can also be +set explicitly. The `min` and `max` elements in the axis configuration defines the +minimum and maximum values of the axis range. + +[source,html] +---- + + -1 + 1 + +---- + +[[charts.configuration.legend]] +== Legend + +The legend is a box that describes the data series shown in the chart. It is +enabled by default and is automatically populated with the names of the data +series as defined in the series objects, and the corresponding color symbol of +the series. + +[parameter]#alignment#:: Specifies the horizontal alignment of the legend box within the chart area. +Possible values are `right`, `center`, and `left`. Defaults to `center`. +[parameter]#enabled#:: Enables or disables the legend. Possible values are `true` and `false`. Defaults to `true`. +[parameter]#layout#:: Specifies the layout direction of the legend items. Possible values are `vertical` and +`horizontal`. Defaults to `horizontal`. +[parameter]#title#:: Specifies the title of the legend. +[parameter]#vertical-align#:: Specifies the vertical alignment of the legend box within the chart area. Possible values +are `bottom`, `low`, `middle`, `high`, and `top`. Defaults to `bottom`. + +[source,html] +---- + + + + City + + + +---- + +The result can be seen in <>. + +[[figure.charts.configuration.legend]] +.Legend example +image::img/charts-configuration-legend.png[] + +[[charts.configuration.format]] +== Formatting Labels + +Data point values, tooltips, and tick labels are formatted according to +formatting configuration for the elements, with configuration properties +described earlier for each element. Formatting can be set up for a data series +or for individual data points. The format can +be defined either by a 'format' string or by JavaScript function 'formatter', which are +described in the following. + +[[charts.configuration.format.string]] +=== Using Format Strings + +A formatting string contain free-form text mixed with variables. Variables are +enclosed in brackets, such as `"Here {point.y} is a value at +{point.x}"`. In different contexts, you have at least the following variables +available: + +* `value` in axis labels +* `point.x`, `point.y` in data points and tooltips +* `series.name` in data points and tooltips +* `series.color` in data points and tooltips + +Values can be formatted according to a formatting string, separated from the +variable name by a colon. + +For numeric values, a subset of C printf formatting specifiers is supported. For +example, `"{point.y:%02.2f}"` would display a floating-point value +with two decimals and two leading zeroes, such as `02.30`. + +For dates, you can use a subset of PHP `strftime()` formatting +specifiers. For example, `"{value:%Y-%m-%d %H:%M:%S}"` would +format a date and time in the ISO 8601 format. + +[[charts.configuration.format.formatter]] +=== Using a JavaScript Formatter + +A JavaScript formatter is given in a string that defines a JavaScript function +that returns the formatted string. The value to be formatted is available in +`this.value` for axis labels, or `this.x`, +`this.y` for data points. + +For example, to format tick labels on a chart axis, you could have: + +---- + + + + +---- + +[[charts.configuration.format.simplified]] +=== Simplified Formatting + +Some contexts that display labels allow defining simple formatting for the +labels. For example, data point tooltips allow defining prefix, suffix, and +floating-point precision for the values. diff --git a/articles/charts/webcomponents-api/charts-data.asciidoc b/articles/charts/webcomponents-api/charts-data.asciidoc new file mode 100644 index 0000000000..967e5431d7 --- /dev/null +++ b/articles/charts/webcomponents-api/charts-data.asciidoc @@ -0,0 +1,370 @@ +--- +title: Chart Data +order: 6 +layout: page +--- + +[[charts.data]] += Chart Data + +Chart data is stored in a data series model, which contains visual representation +information about the data points in addition to their values. Data can be attached +to a chart either by using a tag or an attribute. Using data tag is useful +in simple cases when data is ready beforehand. + +[source,html] +---- + + + 181091, 201485, 188105,188135 + + + + + + + +---- + +You can also specify plot options for each point specifically using tag. + +[source,html] +---- + + + + + 181091 + red + bar + + + 201485 + foo + blue + + + 211485 + green + + + red + + +---- + +Using data attribute allows to change an array of data points dynamically. +The points can be added to a series in three ways: as a one-dimensional array, + as a multi-dimensional array or as array of objects. + +[[charts.data.1darray]] +== Adding series as a one-dimensional array + +In case of using one-dimensional array, the data points are assumed to be at + a constant interval on the X axis, starting from the +value specified with the 'point-start' property (default value is '0') at intervals +specified with the 'point-interval' property (default value is '1.0'). +You can also add new points to a chart, by adding new items to a Data object. Data attribute +should be bound to a element property by using either one-way binding +or automatic binding. +Please, see more details about these in the Polymer + https://www.polymer-project.org/2.0/docs/devguide/data-binding.html[Data binding] + documentation. + +[source,html] +---- + + + + + + + + +---- + +[[charts.data.2darray]] +== Adding series as a multi-dimensional array +In case of using two-dimensional array, the first value is x value and the second value +is y value. If the first value is a string, it is applied as the name of the point, + and the x value is incremented following the above rules. For + [classname]#vaadin-arearange-chart# + the arrays will be interpreted as [x, low, high]. + In this cases, the X value can be skipped altogether to make use of +'point-start' and 'point-interval' properties. + +[source,javascript] +---- +mySeriesData: { + type: Array, + value: [ + [1, 1.1, 4.7], + [2, 1.8, 6.4], + [3, 1.7, 6.9], + [4, 2.6, 7.4], + [6, 3.3, 9.3], + [10, 3.0, 7.9], + [12, 3.9, 6.0], + [16, 3.9, 5.5] + ] +} +---- + +[[charts.data.objarray]] +== Adding series as an array of objects +In case of using an array of objects, these objects stores point configurations. + +Data points are associated with some visual representation parameters: +marker style, selected state, legend index, and dial style (for gauges). +Most of them can be configured at the level of individual data series items, +the series, or in the overall plot options for the chart. +The configuration options are described in + <>. + Some parameters, such as the sliced option for pie charts is only meaningful + to configure at item level. + +[source,javascript] +---- + static get properties() { + return { + mySeriesData: { + type: Array, + value: + [ + 181091, + {y:188105, + marker: { + symbol: 'square', + fillColor: "green", + radius: 10 + } + }, + 201485, + 188136 + ] + } + }; + } +---- + +[[charts.data.dataseries.add]] +=== Adding and Removing Data Items +As shown above to add new points you should add new elements +to the bound property, which contains an array of points. +All changes (add,update,remove) of the bound property affect +the chart data series. + +[source,javascript] +---- + +---- + +You can also change the chart data series using JavaScript API of the underlying library. +New [classname]#Point# items are added to a series with the +[methodname]#addPoint()# method of a [classname]#Series# class. To remove an +item from a series use [methodname]#remove()# of a [classname]#Point# class. + +[source,html] +---- + + + + +---- + +The [methodname]#addPoint()# method takes the data item and + three optional rendering parameters. + +If the [parameter]#redraw# parameter is 'false' , the chart is not + updated immediately. This is useful if you are adding many points + and do not want the chart to be redrawn every time a new point is added. + After adding all the points you need to call [methodname]#redraw()# method. + +The [parameter]#shift# parameter, when 'true' , causes removal of the first +data point in the series in an optimized manner, thereby allowing an animated +chart that moves to left as new points are added. This is most meaningful with +data with even intervals. + +The [parameter]#animation# parameter, when 'true', the series updating will + be animated with default animation options. The animation can also be a + configuration object with properties duration and easing. + +[[charts.data.dataseries.update]] +=== Updating Data Items +You can update data points with the [methodname]#update()# method in the + [classname]#Point# class. + +[[charts.data.htmltable]] +=== HTML table as a data source +An HTML table can be used a data source. You need to create a html-table, where +a table rows specify data series points and cells in the row specify x and y +coordinates. +Afterwards you need to assign the table id as an attribute to a data tag. + +[source,html] +---- + + + + + +---- + +[[charts.data.drilldown]] +== Drill-Down + +Vaadin Charts allows drilling down from a chart to a more detailed view by +clicking an item in the top-level view. To enable this feature, you need to +provide a separate data series for each of the detailed views by adding the +'drilldown' tag. When the user clicks on a +drill-down item, the current series is animated into the the linked drill-down +series. + +[source,html] +---- + + MSIE + + + MSIE + 60 + MSIE Versions + + + + + MSIE Versions + + + MSIE 6.0 + 64 + + + MSIE 7.0 + 7.35 + + ... + + + +---- + +A customizable back button is provided to navigate back to the main +series, as shown in +<>. + +[[figure.charts.data.drilldown.drilldown-details]] +.Detailed series after a drill-down +image::img/charts-drilldown-details.png[, 100%, 100%] diff --git a/articles/charts/webcomponents-api/charts-getting-started.asciidoc b/articles/charts/webcomponents-api/charts-getting-started.asciidoc new file mode 100644 index 0000000000..81f415f8a8 --- /dev/null +++ b/articles/charts/webcomponents-api/charts-getting-started.asciidoc @@ -0,0 +1,446 @@ +--- +title: Getting started +order: 1 +layout: page +--- + += Getting started with Vaadin Charts + +[[introduction]] +== Introduction + +This tutorial walks you, step-by-step, through what you need to do to add Vaadin Charts to your web page. + +You will learn how to: + +* Add Vaadin Charts to a web page +* Create a simple line chart +* Create a combined chart with dual Y-axes +* Configure settings to change the look of the chart +* Bind the chart to a REST service + +ifdef::web[] +The final result of this tutorial can be explored at +https://github.com/vaadin/charts-tutorial/tree/master/client[GitHub]. +endif::web[] + +Let us get to it. + +[[setup]] +== Project Setup + +The easiest way to get started is to use https://bower.io/[Bower]. +First, create a folder and run `bower install` command within it. +It downloads Vaadin Charts and all the dependencies that it needs. + +[subs="normal"] +---- +[prompt]#$# [command]#mkdir# [replaceable]#tutorial# +[prompt]#$# [command]#cd# [replaceable]#tutorial# +[prompt]#$# [command]#bower# install --save [replaceable]#vaadin-charts# +---- + +Next create an [filename]#index.html# file with following content. + +[source,html] +---- + + + + + + + + +---- + +The head element loads the web components. +Our web page is now ready for adding Vaadin Charts to it. + +[[first.chart]] +== Creating Your First Chart + +Add a chart element to the `` element. +In this example, we are going to use `` chart. + +[source,html] +---- + +---- + +You need to import the `vaadin-line-chart` in the `` element: + +[source,html] +---- + +---- + +So your [filename]#index.html# file should look as follows: + +[source,html] +---- + + + + + + + + + + +---- + +You can now serve the [filename]#index.html# and check it out in the browser. +One of the easiest ways to do this is to use a tool called `serve` (see https://www.npmjs.com/package/serve[npmjs.com] for installation instructions). + +[subs="normal"] +---- +[prompt]#$# [command]#serve# +serving [replaceable]#/tutorial# on port 3000 +---- + +Open `localhost:3000` with a browser. +If you do not have a Vaadin Charts license, you will see a pop-up with a link where you can get one. +Enter the license key to the pop-up. +After that, you should see an empty chart with title [guilabel]#Chart title#. + +Next, modify the `` element to have a `` child element with the content [literal]#Hello Charts!#. + +[source,html] +---- + + Hello Charts! + +---- + +Reload the page and you should see the new title in the chart. + +[[bind.data]] +=== Adding Some Data + +Next, we are going to add data to our line chart. +We have data about the average shoe size per age for girls and boys. +First, let us add the data for girls. +This is done by adding a `` element inside the ``. + +[source,html] +---- + + + [17, 0.3], [18, 0.7], [19, 0.8], [20, 1.0], [21, 1.3], [22, 1.5], + [23, 2.0], [24, 2.5], [25, 3.0], [26, 3.5], [27, 4.0], [28, 4.5], + [29, 5.0], [30, 5.5], [31, 6.5], [32, 7.0], [33, 8.0], [34, 9.0], + [35, 10.0], [36, 11.0] + + +---- + +Refresh the page and you should see the data in the chart. +That is awesome, but you may notice that the Y axis has a label named "[guilabel]#values#". +That is not so awesome. +So, let us specify our own titles there and add also the unit information. +You can do it by adding the following inside the `` element: + +[source,html] +---- + + Shoe size (EU) + + + Age (years) + +---- + +After refreshing the page, you should see a nice chart about girls average shoe +size with the nice titles in the axes. + +[[bind.another.data]] +=== Adding Another Data Set to the Same Chart + +In the previous section, we added only girls' data to the chart. +Now is time to add boys there. +You can do it by adding another `` element inside the `` element. +We again specify a `name` attribute, which value will be shown in the charts legend. + +[source,html] +---- + + + [17, 0.3], [18, 0.6], [19, 0.8], [20, 0.9], [21, 1.1], [22, 1.3], + [23, 1.7], [24, 2.0], [25, 2.5], [26, 3.0], [27, 3.5], [28, 4.0], + [29, 4.5], [30, 5.0], [31, 5.5], [32, 6.5], [33, 7.5], [34, 8.0], + [35, 9.0], [36, 10.0], [37, 11.0] + + +---- + +Refresh the page and you see two lines in the chart. +They have different colors and you can see from the legend which is which. +Try to click the legend items - this toggles the visibility of the data series. + +Finally, change the title of the chart to something describing it, such as "_Shoe size per age for boys and girls_". + +[[configure.colors]] +=== Configuring the Colors + +Our chart looks OK now, but it would be more intuitive to read if the data for girls was rendered using a color normally associated with girls, would it not? +Let us color the girl data as pink and the boy data as light blue. +The colors of the lines can be changed by adding a `` element to the ``. + +[source,html] +---- + + #FF69B4 + + [17, 0.3], ... , [36, 11.0] + + + + #0000FF + + [17, 0.3], ..., [37, 11.0] + + +---- + +Great! Refresh the page and you see the finished chart. + + +[[combination.chart]] +== Creating a Combination Chart + +Let us do something more complex next. +We have historical weather data for Turku, Finland, for most of the year 2013. +We will plot the temperature as a line chart and add columns for the humidity to the same chart to create a combination chart. +On top of that, we will create our own web component, which will fetch the data for the chart from a REST service. + +[[combination.chart.preparations]] +=== Preparations + +Download the data files for the +https://raw.githubusercontent.com/vaadin/charts-tutorial/master/client/data/temperature[temperature] and https://raw.githubusercontent.com/vaadin/charts-tutorial/master/client/data/humidity[humidity]. +Create a folder named [filename]#data# in the same folder where you ran the `serve` command and put the downloaded files there. +The data files in the folder are now served together with the [filename]#index.html#. +Those files will mimic our REST service to fetch the weather data. + +Next, we create a new web component named `weather-chart` that wraps the Charts component and makes REST calls to fetch the data. +First, let us do it so that it only wraps the `vaadin-line-chart` component. + +First, create a new file [filename]#weather-chart.html# and add the following: + +[source, html] +---- + + +---- + +These are the dependencies required for our new web-component. + +Then, let us add the component declaration: + +[source,html] +---- + + + class WeatherChart extends Polymer.Element { + static get is() { return 'weather-chart' } + } + + customElements.define(WeatherChart.is, WeatherChart); + +---- + +Then, at [filename]#index.html# we should import our newly created component, so let us add it inside ``: + +[source,html] +---- + +---- + +Then, add a `` element after ``: + +[source, html] +---- + +---- + +Next, we want to call the REST service to fetch the data and bind that to the chart. +We use the `iron-ajax` component to make the request. +Back to [filename]#weather-chart.html#, add the following inside the `